[
  {
    "path": ".git-blame-ignore-revs",
    "content": "# update prettier & eslint config (#9162)\nbfe6b459d3a0ce6168611ee1ac7e6e789709df9d\n"
  },
  {
    "path": ".github/FUNDING.yml",
    "content": "github: yyx990803\nopen_collective: vuejs\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.yml",
    "content": "name: \"\\U0001F41E Bug report\"\ndescription: Create a report to help us improve\nbody:\n  - type: markdown\n    attributes:\n      value: |\n        **Before You Start...**\n\n        This form is only for submitting bug reports. If you have a usage question\n        or are unsure if this is really a bug, make sure to:\n\n        - Read the [docs](https://vuejs.org/)\n        - Ask on [Discord Chat](https://chat.vuejs.org/)\n        - Ask on [GitHub Discussions](https://github.com/vuejs/core/discussions)\n        - Look for / ask questions on [Stack Overflow](https://stackoverflow.com/questions/ask?tags=vue.js)\n\n        Also try to search for your issue - it may have already been answered or even fixed in the development branch.\n        However, if you find that an old, closed issue still persists in the latest version,\n        you should open a new issue using the form below instead of commenting on the old issue.\n  - type: input\n    id: version\n    attributes:\n      label: Vue version\n    validations:\n      required: true\n  - type: input\n    id: reproduction-link\n    attributes:\n      label: Link to minimal reproduction\n      description: |\n        The easiest way to provide a reproduction is by showing the bug in [The SFC Playground](https://play.vuejs.org/).\n        If it cannot be reproduced in the playground and requires a proper build setup, try [StackBlitz](https://vite.new/vue).\n        If neither of these are suitable, you can always provide a GitHub repository.\n\n        The reproduction should be **minimal** - i.e. it should contain only the bare minimum amount of code needed\n        to show the bug. See [Bug Reproduction Guidelines](https://github.com/vuejs/core/blob/main/.github/bug-repro-guidelines.md) for more details.\n\n        Please do not just fill in a random link. The issue will be closed if no valid reproduction is provided.\n      placeholder: Reproduction Link\n    validations:\n      required: true\n  - type: textarea\n    id: steps-to-reproduce\n    attributes:\n      label: Steps to reproduce\n      description: |\n        What do we need to do after opening your repro in order to make the bug happen? Clear and concise reproduction instructions are important for us to be able to triage your issue in a timely manner. Note that you can use [Markdown](https://guides.github.com/features/mastering-markdown/) to format lists and code.\n      placeholder: Steps to reproduce\n    validations:\n      required: true\n  - type: textarea\n    id: expected\n    attributes:\n      label: What is expected?\n    validations:\n      required: true\n  - type: textarea\n    id: actually-happening\n    attributes:\n      label: What is actually happening?\n    validations:\n      required: true\n  - type: textarea\n    id: system-info\n    attributes:\n      label: System Info\n      description: Output of `npx envinfo --system --npmPackages vue --binaries --browsers`\n      render: shell\n      placeholder: System, Binaries, Browsers\n  - type: textarea\n    id: additional-comments\n    attributes:\n      label: Any additional comments?\n      description: e.g. some background/context of how you ran into this bug.\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "content": "blank_issues_enabled: false\ncontact_links:\n  - name: Feature Request\n    url: https://github.com/vuejs/rfcs/discussions\n    about: Suggest new features for consideration\n  - name: Discord Chat\n    url: https://chat.vuejs.org\n    about: Ask questions and discuss with other Vue users in real time.\n  - name: Questions & Discussions\n    url: https://github.com/vuejs/core/discussions\n    about: Use GitHub discussions for message-board style questions and discussions.\n  - name: Patreon\n    url: https://www.patreon.com/evanyou\n    about: Love Vue.js? Please consider supporting us via Patreon.\n  - name: Open Collective\n    url: https://opencollective.com/vuejs/donate\n    about: Love Vue.js? Please consider supporting us via Open Collective.\n"
  },
  {
    "path": ".github/bug-repro-guidelines.md",
    "content": "## About Bug Reproductions\n\nA bug reproduction is a piece of code that can run and demonstrate how a bug can happen.\n\n### Text is not enough\n\nIt's impossible to fix a bug from mere text descriptions. First, it's very difficult to precisely describe a technical problem while keeping it easy to follow; Second, the real cause may very well be something that you forgot to even mention. A reproduction is the only way that can reliably help us understand what is going on, so please provide one.\n\n### A repro must be runnable\n\nScreenshots or videos are NOT reproductions! They only show that the bug exists, but do not provide enough information on why it happens. Only runnable code provides the most complete context and allows us to properly debug the scenario. That said, in some cases videos/gifs can help explain interaction issues that are hard to describe in text.\n\n### A repro should be minimal\n\nSome users would give us a link to a real project and hope we can help them figure out what is wrong. We generally do not accept such requests because:\n\nYou are already familiar with your codebase, but we are not. It is extremely time-consuming to hunt a bug in a big and unfamiliar codebase.\n\nThe problematic behavior may very well be caused by your code rather than by a bug in Vue.\n\nA minimal reproduction means it demonstrates the bug, and the bug only. It should only contain the bare minimum amount of code that can reliably cause the bug. Try your best to get rid of anything that isn't directly related to the problem.\n\n### How to create a repro\n\nFor Vue 3 core reproductions, try reproducing it in [The SFC Playground](https://play.vuejs.org/).\n\nIf it cannot be reproduced in the playground and requires a proper build setup, try [StackBlitz](https://vite.new/vue).\n\nIf neither of these are suitable, you can always provide a GitHub repository.\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```regexp\n/^(revert: )?(feat|fix|docs|dx|style|refactor|perf|test|workflow|build|ci|chore|types|wip)(\\(.+\\))?: .{1,50}/\n```\n\n#### Examples\n\nAppears under \"Features\" header, `compiler` subheader:\n\n```\nfeat(compiler): add 'comments' option\n```\n\nAppears under \"Bug Fixes\" header, `v-model` subheader, with a link to issue #28:\n\n```\nfix(v-model): handle events on blur\n\nclose #28\n```\n\nAppears under \"Performance Improvements\" header, and under \"Breaking Changes\" with the breaking change explanation:\n\n```\nperf(core): improve vdom diffing by removing 'foo' option\n\nBREAKING CHANGE: The 'foo' option has been removed.\n```\n\nThe following commit and commit `667ecc1` do not appear in the changelog if they are under the same release. If not, the revert commit appears under the \"Reverts\" header.\n\n```\nrevert: feat(compiler): add 'comments' option\n\nThis reverts commit 667ecc1654a317a13331b17617d973392f415f02.\n```\n\n### Full Message Format\n\nA commit message consists of a **header**, **body** and **footer**. The header has a **type**, **scope** and **subject**:\n\n```\n<type>(<scope>): <subject>\n<BLANK LINE>\n<body>\n<BLANK LINE>\n<footer>\n```\n\nThe **header** is mandatory and the **scope** of the header is optional.\n\n### Revert\n\nIf the commit reverts a previous commit, it should begin with `revert: `, followed by the header of the reverted commit. In the body, it should say: `This reverts commit <hash>.`, where the hash is the SHA of the commit being reverted.\n\n### Type\n\nIf the prefix is `feat`, `fix` or `perf`, it will appear in the changelog. However, if there is any [BREAKING CHANGE](#footer), the commit will always appear in the changelog.\n\nOther prefixes are up to your discretion. Suggested prefixes are `docs`, `chore`, `style`, `refactor`, and `test` for non-changelog related tasks.\n\n### Scope\n\nThe scope could be anything specifying the place of the commit change. For example `core`, `compiler`, `ssr`, `v-model`, `transition` 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\n### Body\n\nJust as in the **subject**, use the imperative, present tense: \"change\" not \"changed\" nor \"changes\".\nThe body should include the motivation for the change and contrast this with previous behavior.\n\n### Footer\n\nThe footer should contain any information about **Breaking Changes** and is also the place to\nreference GitHub issues that this commit **Closes**.\n\n**Breaking Changes** should start with the word `BREAKING CHANGE:` with a space or two newlines. The rest of the commit message is then used for this.\n"
  },
  {
    "path": ".github/contributing.md",
    "content": "# Vue.js Contributing Guide\n\nHi! I'm really excited that you are interested in contributing to Vue.js. Before submitting your contribution, please make sure to take a moment and read through the following guidelines:\n\n- [Code of Conduct](https://vuejs.org/about/coc.html)\n- [Issue Reporting Guidelines](#issue-reporting-guidelines)\n- [Pull Request Guidelines](#pull-request-guidelines)\n- [Development Setup](#development-setup)\n- [Scripts](#scripts)\n- [Project Structure](#project-structure)\n- [Contributing Tests](#contributing-tests)\n- [Financial Contribution](#financial-contribution)\n\n## Issue Reporting Guidelines\n\n- Always use [https://new-issue.vuejs.org/](https://new-issue.vuejs.org/) to create new issues.\n\n## Pull Request Guidelines\n\n### What kinds of Pull Requests are accepted?\n\n- Bug fix that addresses a clearly identified bug. **\"Clearly identified bug\"** means the bug has a proper reproduction either from a related open issue, or is included in the PR itself. Avoid submitting PRs that claim to fix something but do not sufficiently explain what is being fixed.\n\n- New feature that addresses a clearly explained and widely applicable use case. **\"Widely applicable\"** means the new feature should provide non-trivial improvements to the majority of the user base. Vue already has a large API surface so we are quite cautious about adding new features - if the use case is niche and can be addressed via userland implementations, it likely isn't suitable to go into core.\n\n  The feature implementation should also consider the trade-off between the added complexity vs. the benefits gained. For example, if a small feature requires significant changes that spread across the codebase, it is likely not worth it, or the approach should be reconsidered.\n\n  If the feature has a non-trivial API surface addition, or significantly affects the way a common use case is approached by the users, it should go through a discussion first in the [RFC repo](https://github.com/vuejs/rfcs/discussions). PRs of such features without prior discussion make it really difficult to steer / adjust the API design due to coupling with concrete implementations, and can lead to wasted work.\n\n- Chore: typos, comment improvements, build config, CI config, etc. For typos and comment changes, try to combine multiple of them into a single PR.\n\n- **It should be noted that we discourage contributors from submitting code refactors that are largely stylistic.** Code refactors are only accepted if they improve performance, or come with sufficient explanations on why they objectively improve the code quality (e.g. makes a related feature implementation easier).\n\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.\n\n  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 make tracing behavior changes across commits more cumbersome.\n\n### Pull Request Checklist\n\n- Vue core has two primary work branches: `main` and `minor`.\n  - If your pull request is a feature that adds new API surface, it should be submitted against the `minor` branch.\n\n  - Otherwise, it should be submitted against the `main` branch.\n\n- [Make sure to tick the \"Allow edits from maintainers\" box](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/allowing-changes-to-a-pull-request-branch-created-from-a-fork). This allows us to directly make minor edits / refactors and saves a lot of time.\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. `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 applicable. You can check the coverage of your code addition by running `nr test-coverage`.\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- Commit messages must follow the [commit message convention](./commit-convention.md) so that changelogs can be automatically generated. Commit messages are automatically validated before commit (by invoking [Git Hooks](https://git-scm.com/docs/githooks) via [simple-git-hooks](https://github.com/toplenboren/simple-git-hooks)).\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### Advanced Pull Request Tips\n\n- The PR should fix the intended bug **only** and not introduce unrelated changes. This includes unnecessary refactors - a PR should focus on the fix and not code style, this makes it easier to trace changes in the future.\n\n- Consider the performance / size impact of the changes, and whether the bug being fixed justifies the cost. If the bug being fixed is a very niche edge case, we should try to minimize the size / perf cost to make it worthwhile.\n  - Is the code perf-sensitive (e.g. in \"hot paths\" like component updates or the vdom patch function?)\n    - If the branch is dev-only, performance is less of a concern.\n\n  - Check how much extra bundle size the change introduces.\n    - Make sure to put dev-only code in `__DEV__` branches so they are tree-shakable.\n    - Runtime code is more sensitive to size increase than compiler code.\n    - Make sure it doesn't accidentally cause dev-only or compiler-only code branches to be included in the runtime build. Notable case is that some functions in `@vue/shared` are compiler-only and should not be used in runtime code, e.g. `isHTMLTag` and `isSVGTag`.\n\n## Development Setup\n\nYou will need [Node.js](https://nodejs.org) with minimum version as specified in the [`.node-version`](https://github.com/vuejs/core/blob/main/.node-version) file, and [PNPM](https://pnpm.io) with minimum version as specified in the [`\"packageManager\"` field in `package.json`](https://github.com/vuejs/core/blob/main/package.json#L4).\n\nWe also recommend installing [@antfu/ni](https://github.com/antfu/ni) to help switching between repos using different package managers. `ni` also provides the handy `nr` command which makes running npm scripts easier.\n\nAfter cloning the repo, run:\n\n```bash\n$ pnpm i # install the dependencies of the project\n```\n\nA high level overview of tools used:\n\n- [TypeScript](https://www.typescriptlang.org/) as the development language\n- [Vite](https://vitejs.dev/) and [ESBuild](https://esbuild.github.io/) for development bundling\n- [Rollup](https://rollupjs.org) for production bundling\n- [Vitest](https://vitest.dev/) for unit testing\n- [Prettier](https://prettier.io/) for code formatting\n- [ESLint](https://eslint.org/) for static error prevention (outside of types)\n\n## Git Hooks\n\nThe project uses [simple-git-hooks](https://github.com/toplenboren/simple-git-hooks) to enforce the following on each commit:\n\n- Type check the entire project\n- Automatically format changed files using Prettier\n- Verify commit message format (logic in `scripts/verify-commit.js`)\n\n## Scripts\n\n**The examples below will be using the `nr` command from the [@antfu/ni](https://github.com/antfu/ni) package.** You can also use plain `npm run`, but you will need to pass all additional arguments after the command after an extra `--`. For example, `nr build runtime --all` is equivalent to `npm run build -- runtime --all`.\n\nThe `run-s` and `run-p` commands found in some scripts are from [npm-run-all](https://github.com/mysticatea/npm-run-all) for orchestrating multiple scripts. `run-s` means \"run in sequence\" while `run-p` means \"run in parallel\".\n\n- [`nr build`](#nr-build)\n- [`nr build-dts`](#nr-build-dts)\n- [`nr check`](#nr-check)\n- [`nr dev`](#nr-dev)\n- [`nr dev-sfc`](#nr-dev-sfc)\n- [`nr dev-esm`](#nr-dev-esm)\n- [`nr dev-compiler`](#nr-dev-compiler)\n- [`nr test`](#nr-test)\n- [`nr test-dts`](#nr-test-dts)\n\n### `nr build`\n\nThe `build` script builds all public packages (packages without `private: true` in their `package.json`).\n\nPackages to build can be specified with fuzzy matching:\n\n```bash\n# build runtime-core only\nnr build runtime-core\n\n# build all packages matching \"runtime\"\nnr build runtime --all\n```\n\nNote that `nr build` uses `rollup-plugin-esbuild` for transpiling typescript and **does not perform type checking**. To run type check on the entire codebase, run `nr check`. Type checks are also automatically run on each commit.\n\n#### Build Formats\n\nBy default, each package will be built in multiple distribution formats as specified in the `buildOptions.formats` field in its `package.json`. These can be overwritten via the `-f` flag. The following formats are supported:\n\n- **`global`**\n- **`esm-bundler`**\n- **`esm-browser`**\n- **`cjs`**\n\nAdditional formats that only apply to the main `vue` package:\n\n- **`global-runtime`**\n- **`esm-bundler-runtime`**\n- **`esm-browser-runtime`**\n\nMore details about each of these formats can be found in the [`vue` package README](https://github.com/vuejs/core/blob/main/packages/vue/README.md#which-dist-file-to-use) and the [Rollup config file](https://github.com/vuejs/core/blob/main/rollup.config.js).\n\nFor example, to build `runtime-core` with the global build only:\n\n```bash\nnr build runtime-core -f global\n```\n\nMultiple formats can be specified as a comma-separated list:\n\n```bash\nnr build runtime-core -f esm-browser,cjs\n```\n\n#### Build with Source Maps\n\nUse the `--sourcemap` or `-s` flag to build with source maps. Note this will make the build much slower.\n\n### `nr build-dts`\n\nThis command builds the type declarations for all packages. It first generates the raw `.d.ts` files in the `temp` directory, then uses [rollup-plugin-dts](https://github.com/Swatinem/rollup-plugin-dts) to roll the types into a single `.d.ts` file for each package.\n\n### `nr check`\n\n### `nr dev`\n\nThe `dev` script bundles a target package (default: `vue`) in a specified format (default: `global`) in dev mode and watches for changes. This is useful when you want to load up a build in an HTML page for quick debugging:\n\n```bash\n$ nr dev\n\n> built: packages/vue/dist/vue.global.js\n```\n\n- **Important:** output of the `dev` script is for development and debugging only. While it has the same runtime behavior, the generated code should never be published to npm.\n\n- The `dev` script does not support fuzzy match - you must specify the full package name, e.g. `nr dev runtime-core`.\n\n- The `dev` script supports specifying build format via the `-f` flag just like the `build` script.\n\n- The `dev` script also supports the `-s` flag for generating source maps, but it will make rebuilds slower.\n\n- The `dev` script supports the `-i` flag for inlining all deps. This is useful when debugging `esm-bundler` builds which externalize deps by default.\n\n### `nr dev-sfc`\n\nShortcut for starting the SFC Playground in local dev mode. This provides the fastest feedback loop when debugging issues that can be reproduced in the SFC Playground.\n\n### `nr dev-esm`\n\nBuilds and watches `vue/dist/vue-runtime.esm-bundler.js` with all deps inlined using esbuild. This is useful when debugging the ESM build in a reproduction that requires real build setups: link `packages/vue` globally, then link it into the project being debugged.\n\n### `nr dev-compiler`\n\nThe `dev-compiler` script builds, watches and serves the [Template Explorer](https://github.com/vuejs/core/tree/main/packages/template-explorer) at `http://localhost:3000`. This is useful when working on pure compiler issues.\n\n### `nr test`\n\nThe `test` script simply calls the `vitest` binary, so all [Vitest CLI Options](https://vitest.dev/guide/cli.html#options) can be used. Some examples:\n\n```bash\n# run all tests in watch mode\n$ nr test\n\n# run once and exit (equivalent to `vitest run`)\n$ nr test run\n\n# run all tests under the runtime-core package\n$ nr test runtime-core\n\n# run tests in files matching the pattern\n$ nr test <fileNamePattern>\n\n# run a specific test in specific files\n$ nr test <fileNamePattern> -t 'test name'\n```\n\nTests that test against source code are grouped under `nr test-unit`, while tests that test against built files that run in real browsers are grouped under `nr test-e2e`.\n\n### `nr test-dts`\n\nRuns `nr build-dts` first, then verify the type tests in `packages-private/dts-test` are working correctly against the actual built type declarations.\n\n## Project Structure\n\nThis repository employs a [monorepo](https://en.wikipedia.org/wiki/Monorepo) setup which hosts a number of associated packages under the `packages` directory:\n\n- `reactivity`: The reactivity system. It can be used standalone as a framework-agnostic package.\n\n- `runtime-core`: The platform-agnostic runtime core. Includes code for the virtual dom renderer, component implementation and JavaScript APIs. Higher-order runtimes (i.e. custom renderers) targeting specific platforms can be created using this package.\n\n- `runtime-dom`: The runtime targeting the browser. Includes handling of native DOM API, attributes, properties, event handlers etc.\n\n- `runtime-test`: The lightweight runtime for testing. Can be used in any JavaScript environment since it \"renders\" a tree of plain JavaScript objects. The tree can be used to assert correct render output. Also provides utilities for serializing the tree, triggering events, and recording actual node operations performed during an update.\n\n- `server-renderer`: Package for server-side rendering.\n\n- `compiler-core`: The platform-agnostic compiler core. Includes the extensible base of the compiler and all platform-agnostic plugins.\n\n- `compiler-dom`: Compiler with additional plugins specifically targeting the browser.\n\n- `compiler-sfc`: Lower level utilities for compiling Vue Single File Components.\n\n- `compiler-ssr`: Compiler that produces render functions optimized for server-side rendering.\n\n- `shared`: Internal utilities shared across multiple packages (especially environment-agnostic utils used by both runtime and compiler packages).\n\n- `vue`: The public facing \"full build\" which includes both the runtime AND the compiler.\n\n- Private utility packages:\n  - `dts-test`: Contains type-only tests against generated dts files.\n\n  - `sfc-playground`: The playground continuously deployed at https://play.vuejs.org. To run the playground locally, use [`nr dev-sfc`](#nr-dev-sfc).\n\n  - `template-explorer`: A development tool for debugging compiler output, continuously deployed at https://template-explorer.vuejs.org/. To run it locally, run [`nr dev-compiler`](#nr-dev-compiler).\n\n### Importing Packages\n\nThe packages can import each other directly using their package names. Note that when importing a package, the name listed in its `package.json` should be used. Most of the time the `@vue/` prefix is needed:\n\n```js\nimport { h } from '@vue/runtime-core'\n```\n\nThis is made possible via several configurations:\n\n- For TypeScript, `compilerOptions.paths` in `tsconfig.json`\n- Vitest and Rollup share the same set of aliases from `scripts/aliases.js`\n- For plain Node.js, they are linked using [PNPM Workspaces](https://pnpm.io/workspaces).\n\n### Package Dependencies\n\n```mermaid\n  flowchart LR\n    compiler-sfc[\"@vue/compiler-sfc\"]\n    compiler-dom[\"@vue/compiler-dom\"]\n    compiler-core[\"@vue/compiler-core\"]\n    vue[\"vue\"]\n    runtime-dom[\"@vue/runtime-dom\"]\n    runtime-core[\"@vue/runtime-core\"]\n    reactivity[\"@vue/reactivity\"]\n\n    subgraph \"Runtime Packages\"\n      runtime-dom --> runtime-core\n      runtime-core --> reactivity\n    end\n\n    subgraph \"Compiler Packages\"\n      compiler-sfc --> compiler-core\n      compiler-sfc --> compiler-dom\n      compiler-dom --> compiler-core\n    end\n\n    vue ---> compiler-dom\n    vue --> runtime-dom\n```\n\nThere are some rules to follow when importing across package boundaries:\n\n- Never use direct relative paths when importing items from another package - export it in the source package and import it at the package level.\n\n- Compiler packages should not import items from the runtime, and vice versa. If something needs to be shared between the compiler-side and runtime-side, it should be extracted into `@vue/shared` instead.\n\n- If a package (A) has a non-type import, or re-exports a type from another package (B), then (B) should be listed as a dependency in (A)'s `package.json`. This is because the packages are externalized in the ESM-bundler/CJS builds and type declaration files, so the dependency packages must be actually installed as a dependency when consumed from package registries.\n\n## Contributing Tests\n\nUnit tests are collocated with the code being tested in each package, inside directories named `__tests__`. Consult the [Vitest docs](https://vitest.dev/api/) and existing test cases for how to write new test specs. Here are some additional guidelines:\n\n- Use the minimal API needed for a test case. For example, if a test can be written without involving the reactivity system or a component, it should be written so. This limits the test's exposure to changes in unrelated parts and makes it more stable.\n\n- If testing platform agnostic behavior or asserting low-level virtual DOM operations, use `@vue/runtime-test`.\n\n- Only use platform-specific runtimes if the test is asserting platform-specific behavior.\n\nTest coverage is continuously deployed at https://coverage.vuejs.org. PRs that improve test coverage are welcome, but in general the test coverage should be used as a guidance for finding API use cases that are not covered by tests. We don't recommend adding tests that only improve coverage but not actually test a meaningful use case.\n\n### Testing Type Definition Correctness\n\nType tests are located in the `packages-private/dts-test` directory. To run the dts tests, run `nr test-dts`. Note that the type test requires all relevant `*.d.ts` files to be built first (and the script does it for you). Once the `d.ts` files are built and up-to-date, the tests can be re-run by running `nr test-dts-only`.\n\n## Financial Contribution\n\nAs a pure community-driven project without major corporate backing, we also welcome financial contributions via Patreon and OpenCollective.\n\n- [Become a backer or sponsor on Patreon](https://www.patreon.com/evanyou)\n- [Become a backer or sponsor on OpenCollective](https://opencollective.com/vuejs)\n\n### What's the difference between Patreon and OpenCollective funding?\n\nFunds donated via Patreon go directly to support Evan You's full-time work on Vue.js. Funds donated via OpenCollective are managed with transparent expenses and will be used for compensating work and expenses for core team members or sponsoring community events. Your name/logo will receive proper recognition and exposure by donating on either platform.\n\n## Credits\n\nThank you to all the people who have already contributed to Vue.js!\n\n<a href=\"https://github.com/vuejs/core/graphs/contributors\"><img src=\"https://opencollective.com/vuejs/contributors.svg?width=890\" /></a>\n"
  },
  {
    "path": ".github/git-branch-workflow.excalidraw",
    "content": "{\n  \"type\": \"excalidraw\",\n  \"version\": 2,\n  \"source\": \"https://excalidraw.com\",\n  \"elements\": [\n    {\n      \"type\": \"arrow\",\n      \"version\": 799,\n      \"versionNonce\": 529220601,\n      \"isDeleted\": false,\n      \"id\": \"Gao2krnDddLMCj468JSWD\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 860.0129225738813,\n      \"y\": 663.9911710635109,\n      \"strokeColor\": \"#f08c00\",\n      \"backgroundColor\": \"#ffc9c9\",\n      \"width\": 133.75296854079784,\n      \"height\": 149.58016791936518,\n      \"seed\": 1415631543,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1698927613071,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": {\n        \"elementId\": \"hDC6an14QljktaZCUhcPF\",\n        \"focus\": 0.09950793234484598,\n        \"gap\": 1.2432497743127229\n      },\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": \"arrow\",\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          25.209039386719837,\n          85.96948921803892\n        ],\n        [\n          133.75296854079784,\n          149.58016791936518\n        ]\n      ]\n    },\n    {\n      \"type\": \"arrow\",\n      \"version\": 563,\n      \"versionNonce\": 290881303,\n      \"isDeleted\": false,\n      \"id\": \"N3wyyEU7TQ8BsOQgxCmlR\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 292.88008929085873,\n      \"y\": 660.7027503334302,\n      \"strokeColor\": \"#2f9e44\",\n      \"backgroundColor\": \"#b2f2bb\",\n      \"width\": 936.9972134376155,\n      \"height\": 1.3184243543457796,\n      \"seed\": 534235417,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1698927613071,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": \"arrow\",\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          936.9972134376155,\n          -1.3184243543457796\n        ]\n      ]\n    },\n    {\n      \"type\": \"arrow\",\n      \"version\": 302,\n      \"versionNonce\": 883286489,\n      \"isDeleted\": false,\n      \"id\": \"nRDWQs5nQa37yzCWTBiXC\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 293.1231624544633,\n      \"y\": 820.6017661012943,\n      \"strokeColor\": \"#f08c00\",\n      \"backgroundColor\": \"#b2f2bb\",\n      \"width\": 790.7091601354882,\n      \"height\": 0.35284814071621895,\n      \"seed\": 515907671,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1698927613071,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": {\n        \"elementId\": \"ggogfJT7E_bbfEog7Hjnp\",\n        \"focus\": -0.14000162237652433,\n        \"gap\": 1\n      },\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": \"arrow\",\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          790.7091601354882,\n          -0.35284814071621895\n        ]\n      ]\n    },\n    {\n      \"type\": \"text\",\n      \"version\": 36,\n      \"versionNonce\": 981763127,\n      \"isDeleted\": false,\n      \"id\": \"ZPdMAnEUq5Jgj1W07Zqiw\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 292.0450153578305,\n      \"y\": 619.3959946602608,\n      \"strokeColor\": \"#1e1e1e\",\n      \"backgroundColor\": \"#b2f2bb\",\n      \"width\": 46.875,\n      \"height\": 24,\n      \"seed\": 1311694519,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1698927613071,\n      \"link\": null,\n      \"locked\": false,\n      \"fontSize\": 20,\n      \"fontFamily\": 3,\n      \"text\": \"main\",\n      \"textAlign\": \"left\",\n      \"verticalAlign\": \"top\",\n      \"containerId\": null,\n      \"originalText\": \"main\",\n      \"lineHeight\": 1.2,\n      \"baseline\": 20\n    },\n    {\n      \"type\": \"text\",\n      \"version\": 94,\n      \"versionNonce\": 18759353,\n      \"isDeleted\": false,\n      \"id\": \"g9IkEIfu4vA8Qkwtw01Hi\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 290.88990199912035,\n      \"y\": 779.1760596323645,\n      \"strokeColor\": \"#1e1e1e\",\n      \"backgroundColor\": \"#b2f2bb\",\n      \"width\": 58.59375,\n      \"height\": 24,\n      \"seed\": 329886135,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1698927613071,\n      \"link\": null,\n      \"locked\": false,\n      \"fontSize\": 20,\n      \"fontFamily\": 3,\n      \"text\": \"minor\",\n      \"textAlign\": \"left\",\n      \"verticalAlign\": \"top\",\n      \"containerId\": null,\n      \"originalText\": \"minor\",\n      \"lineHeight\": 1.2,\n      \"baseline\": 20\n    },\n    {\n      \"type\": \"ellipse\",\n      \"version\": 50,\n      \"versionNonce\": 1442112855,\n      \"isDeleted\": false,\n      \"id\": \"RrdEQ7hwgGGDPhzDnuZj1\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 361.55609907891005,\n      \"y\": 649.8742329483416,\n      \"strokeColor\": \"#2f9e44\",\n      \"backgroundColor\": \"#b2f2bb\",\n      \"width\": 18.814646969963974,\n      \"height\": 18.814646969963974,\n      \"seed\": 2077639991,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1698927613071,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"ellipse\",\n      \"version\": 79,\n      \"versionNonce\": 1547173785,\n      \"isDeleted\": false,\n      \"id\": \"Zmp49FKWxGSzKnVKomjQc\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 427.3015090315691,\n      \"y\": 650.256485100784,\n      \"strokeColor\": \"#2f9e44\",\n      \"backgroundColor\": \"#b2f2bb\",\n      \"width\": 18.814646969963974,\n      \"height\": 18.814646969963974,\n      \"seed\": 372652121,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1698927613071,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"ellipse\",\n      \"version\": 76,\n      \"versionNonce\": 586949239,\n      \"isDeleted\": false,\n      \"id\": \"UOl9nLBksM7RPdH9mzjJa\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 490.9435520120701,\n      \"y\": 651.2601420343765,\n      \"strokeColor\": \"#2f9e44\",\n      \"backgroundColor\": \"#b2f2bb\",\n      \"width\": 18.814646969963974,\n      \"height\": 18.814646969963974,\n      \"seed\": 508667545,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1698927613071,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"ellipse\",\n      \"version\": 120,\n      \"versionNonce\": 874947705,\n      \"isDeleted\": false,\n      \"id\": \"oMC55V0VO_hOXoZ1se8Kl\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 555.4481126698772,\n      \"y\": 650.7975189165487,\n      \"strokeColor\": \"#2f9e44\",\n      \"backgroundColor\": \"#b2f2bb\",\n      \"width\": 18.814646969963974,\n      \"height\": 18.814646969963974,\n      \"seed\": 1914963513,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1698927613071,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"ellipse\",\n      \"version\": 66,\n      \"versionNonce\": 39762839,\n      \"isDeleted\": false,\n      \"id\": \"DZY5DC5uVP7-U5c3ngIZ4\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 622.5167031502219,\n      \"y\": 649.3743647489936,\n      \"strokeColor\": \"#2f9e44\",\n      \"backgroundColor\": \"#b2f2bb\",\n      \"width\": 18.814646969963974,\n      \"height\": 18.814646969963974,\n      \"seed\": 165914713,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1698927613071,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"ellipse\",\n      \"version\": 107,\n      \"versionNonce\": 1689103705,\n      \"isDeleted\": false,\n      \"id\": \"Vsw6oIiTM3fQypkiCic3f\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 690.330195260967,\n      \"y\": 650.6681412649529,\n      \"strokeColor\": \"#2f9e44\",\n      \"backgroundColor\": \"#b2f2bb\",\n      \"width\": 18.814646969963974,\n      \"height\": 18.814646969963974,\n      \"seed\": 280044345,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [\n        {\n          \"id\": \"lwYvAs-7FTjcwxKjcx0KV\",\n          \"type\": \"arrow\"\n        }\n      ],\n      \"updated\": 1698927613071,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"ellipse\",\n      \"version\": 148,\n      \"versionNonce\": 1986194201,\n      \"isDeleted\": false,\n      \"id\": \"D14w9erv_2l53mINe2nSt\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 361.004283792179,\n      \"y\": 810.2809579853473,\n      \"strokeColor\": \"#f08c00\",\n      \"backgroundColor\": \"#ffc9c9\",\n      \"width\": 18.814646969963974,\n      \"height\": 18.814646969963974,\n      \"seed\": 1203257975,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1698927613071,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"ellipse\",\n      \"version\": 179,\n      \"versionNonce\": 1172811511,\n      \"isDeleted\": false,\n      \"id\": \"6WO8xOpG0rf673b_bT0m7\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 426.74969374483805,\n      \"y\": 810.6632101377896,\n      \"strokeColor\": \"#f08c00\",\n      \"backgroundColor\": \"#b2f2bb\",\n      \"width\": 18.814646969963974,\n      \"height\": 18.814646969963974,\n      \"seed\": 2056706967,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [\n        {\n          \"id\": \"mE8Mu0qKfFaWPCC5vmF_f\",\n          \"type\": \"arrow\"\n        }\n      ],\n      \"updated\": 1698927613071,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"ellipse\",\n      \"version\": 173,\n      \"versionNonce\": 820518905,\n      \"isDeleted\": false,\n      \"id\": \"VB9U8oH-78hf530hIb_mG\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 490.391736725339,\n      \"y\": 811.6668670713822,\n      \"strokeColor\": \"#f08c00\",\n      \"backgroundColor\": \"#b2f2bb\",\n      \"width\": 18.814646969963974,\n      \"height\": 18.814646969963974,\n      \"seed\": 1149587639,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1698927613071,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"ellipse\",\n      \"version\": 218,\n      \"versionNonce\": 1227143191,\n      \"isDeleted\": false,\n      \"id\": \"Bxv1hcS0VmxUwI0JLFH97\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 554.8962973831461,\n      \"y\": 811.2042439535543,\n      \"strokeColor\": \"#f08c00\",\n      \"backgroundColor\": \"#b2f2bb\",\n      \"width\": 18.814646969963974,\n      \"height\": 18.814646969963974,\n      \"seed\": 1864901079,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [\n        {\n          \"id\": \"M14Q0Uo1DBy2Ss2SOFSgW\",\n          \"type\": \"arrow\"\n        }\n      ],\n      \"updated\": 1698927613071,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"ellipse\",\n      \"version\": 167,\n      \"versionNonce\": 1387509977,\n      \"isDeleted\": false,\n      \"id\": \"4v23gkfhy-hzk18YdkfLz\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 621.9648878634908,\n      \"y\": 809.7810897859994,\n      \"strokeColor\": \"#f08c00\",\n      \"backgroundColor\": \"#ffc9c9\",\n      \"width\": 18.814646969963974,\n      \"height\": 18.814646969963974,\n      \"seed\": 462671607,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [\n        {\n          \"id\": \"vEF1cIIYYWKm84KLKqEz3\",\n          \"type\": \"arrow\"\n        }\n      ],\n      \"updated\": 1698927613071,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"ellipse\",\n      \"version\": 200,\n      \"versionNonce\": 774085943,\n      \"isDeleted\": false,\n      \"id\": \"AtEf7o4WZQn4Zxq8EN5fH\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 689.7783799742359,\n      \"y\": 811.0748663019584,\n      \"strokeColor\": \"#f08c00\",\n      \"backgroundColor\": \"#b2f2bb\",\n      \"width\": 18.814646969963974,\n      \"height\": 18.814646969963974,\n      \"seed\": 1414322199,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [\n        {\n          \"id\": \"3heKY3vfe3-6ni4dX7Uqo\",\n          \"type\": \"arrow\"\n        }\n      ],\n      \"updated\": 1698927613071,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"ellipse\",\n      \"version\": 199,\n      \"versionNonce\": 1834563001,\n      \"isDeleted\": false,\n      \"id\": \"ugDby5sBv4NKdNt8eC1sg\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 762.6179978227377,\n      \"y\": 810.2986003923828,\n      \"strokeColor\": \"#f08c00\",\n      \"backgroundColor\": \"#b2f2bb\",\n      \"width\": 18.814646969963974,\n      \"height\": 18.814646969963974,\n      \"seed\": 1598537015,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1698927613071,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"ellipse\",\n      \"version\": 211,\n      \"versionNonce\": 407428695,\n      \"isDeleted\": false,\n      \"id\": \"Fwe4F2sB_0jptOZGYsusj\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 837.1081608628116,\n      \"y\": 810.859236882632,\n      \"strokeColor\": \"#f08c00\",\n      \"backgroundColor\": \"#b2f2bb\",\n      \"width\": 18.814646969963974,\n      \"height\": 18.814646969963974,\n      \"seed\": 1340669527,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [\n        {\n          \"id\": \"M14Q0Uo1DBy2Ss2SOFSgW\",\n          \"type\": \"arrow\"\n        }\n      ],\n      \"updated\": 1698927613071,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"arrow\",\n      \"version\": 57,\n      \"versionNonce\": 335287961,\n      \"isDeleted\": false,\n      \"id\": \"mE8Mu0qKfFaWPCC5vmF_f\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 437.60867586595543,\n      \"y\": 830.4227236701945,\n      \"strokeColor\": \"#f08c00\",\n      \"backgroundColor\": \"#ffc9c9\",\n      \"width\": 0.5232394659406623,\n      \"height\": 33.25787987764363,\n      \"seed\": 482155929,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1698927613071,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": {\n        \"elementId\": \"6WO8xOpG0rf673b_bT0m7\",\n        \"focus\": -0.1727591064041787,\n        \"gap\": 1.046152088903881\n      },\n      \"endBinding\": {\n        \"elementId\": \"JALHBtowuh3_a86loej2x\",\n        \"focus\": 0.015156451076917701,\n        \"gap\": 15.586906139714472\n      },\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": \"arrow\",\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          -0.5232394659406623,\n          33.25787987764363\n        ]\n      ]\n    },\n    {\n      \"type\": \"arrow\",\n      \"version\": 59,\n      \"versionNonce\": 1248394103,\n      \"isDeleted\": false,\n      \"id\": \"AI-_jSAuzesxTqwRvpk0s\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 501.2878833373983,\n      \"y\": 652.3088851192829,\n      \"strokeColor\": \"#2f9e44\",\n      \"backgroundColor\": \"#ffc9c9\",\n      \"width\": 0,\n      \"height\": 40.40111211199792,\n      \"seed\": 1052632343,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1698927613071,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": \"arrow\",\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          0,\n          -40.40111211199792\n        ]\n      ]\n    },\n    {\n      \"type\": \"arrow\",\n      \"version\": 261,\n      \"versionNonce\": 693099385,\n      \"isDeleted\": false,\n      \"id\": \"lwYvAs-7FTjcwxKjcx0KV\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 786.7392304423553,\n      \"y\": 649.6016935672433,\n      \"strokeColor\": \"#2f9e44\",\n      \"backgroundColor\": \"#ffc9c9\",\n      \"width\": 0,\n      \"height\": 40.40111211199792,\n      \"seed\": 1233043511,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1698927613071,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": {\n        \"elementId\": \"s0PKxsWTJSDbQeEl_WI-C\",\n        \"focus\": 0.016372633695398757,\n        \"gap\": 1\n      },\n      \"endBinding\": {\n        \"elementId\": \"9ia1Uwc5X0fRw5iaahmcT\",\n        \"focus\": 0.025318405829282714,\n        \"gap\": 14.862364635333904\n      },\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": \"arrow\",\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          0,\n          -40.40111211199792\n        ]\n      ]\n    },\n    {\n      \"type\": \"text\",\n      \"version\": 121,\n      \"versionNonce\": 952661143,\n      \"isDeleted\": false,\n      \"id\": \"qWW8uxDIcV3Bkj28uvRLr\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 454.32425448306674,\n      \"y\": 537.8854189061962,\n      \"strokeColor\": \"#1e1e1e\",\n      \"backgroundColor\": \"#ffc9c9\",\n      \"width\": 93.75,\n      \"height\": 57.599999999999994,\n      \"seed\": 809847769,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1698927613071,\n      \"link\": null,\n      \"locked\": false,\n      \"fontSize\": 16,\n      \"fontFamily\": 3,\n      \"text\": \"patch\\nrelease\\ne.g. 3.3.8\",\n      \"textAlign\": \"center\",\n      \"verticalAlign\": \"top\",\n      \"containerId\": null,\n      \"originalText\": \"patch\\nrelease\\ne.g. 3.3.8\",\n      \"lineHeight\": 1.2,\n      \"baseline\": 53\n    },\n    {\n      \"type\": \"text\",\n      \"version\": 257,\n      \"versionNonce\": 1838679129,\n      \"isDeleted\": false,\n      \"id\": \"9ia1Uwc5X0fRw5iaahmcT\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 741.0510307156029,\n      \"y\": 536.7382168199114,\n      \"strokeColor\": \"#1e1e1e\",\n      \"backgroundColor\": \"#ffc9c9\",\n      \"width\": 93.75,\n      \"height\": 57.599999999999994,\n      \"seed\": 213765431,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [\n        {\n          \"id\": \"lwYvAs-7FTjcwxKjcx0KV\",\n          \"type\": \"arrow\"\n        }\n      ],\n      \"updated\": 1698927613071,\n      \"link\": null,\n      \"locked\": false,\n      \"fontSize\": 16,\n      \"fontFamily\": 3,\n      \"text\": \"patch\\nrelease\\ne.g. 3.3.9\",\n      \"textAlign\": \"center\",\n      \"verticalAlign\": \"top\",\n      \"containerId\": null,\n      \"originalText\": \"patch\\nrelease\\ne.g. 3.3.9\",\n      \"lineHeight\": 1.2,\n      \"baseline\": 53\n    },\n    {\n      \"type\": \"text\",\n      \"version\": 222,\n      \"versionNonce\": 1528547767,\n      \"isDeleted\": false,\n      \"id\": \"JALHBtowuh3_a86loej2x\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 350.7264132088442,\n      \"y\": 879.2675096875524,\n      \"strokeColor\": \"#1e1e1e\",\n      \"backgroundColor\": \"#ffc9c9\",\n      \"width\": 168.75,\n      \"height\": 57.599999999999994,\n      \"seed\": 41180921,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [\n        {\n          \"id\": \"mE8Mu0qKfFaWPCC5vmF_f\",\n          \"type\": \"arrow\"\n        }\n      ],\n      \"updated\": 1698927613071,\n      \"link\": null,\n      \"locked\": false,\n      \"fontSize\": 16,\n      \"fontFamily\": 3,\n      \"text\": \"pre minor\\nrelease\\ne.g. 3.4.0-alpha.1\",\n      \"textAlign\": \"center\",\n      \"verticalAlign\": \"top\",\n      \"containerId\": null,\n      \"originalText\": \"pre minor\\nrelease\\ne.g. 3.4.0-alpha.1\",\n      \"lineHeight\": 1.2,\n      \"baseline\": 53\n    },\n    {\n      \"type\": \"arrow\",\n      \"version\": 345,\n      \"versionNonce\": 1286082873,\n      \"isDeleted\": false,\n      \"id\": \"3heKY3vfe3-6ni4dX7Uqo\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 699.5281288163526,\n      \"y\": 831.0290882554708,\n      \"strokeColor\": \"#f08c00\",\n      \"backgroundColor\": \"#ffc9c9\",\n      \"width\": 0.5502191262773977,\n      \"height\": 33.25154356841597,\n      \"seed\": 627698359,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1698927613071,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": {\n        \"elementId\": \"AtEf7o4WZQn4Zxq8EN5fH\",\n        \"focus\": -0.05612657009295625,\n        \"gap\": 1.1451322685712295\n      },\n      \"endBinding\": {\n        \"elementId\": \"9t6qH-tAxVUexkHHi2pd2\",\n        \"focus\": 0.015156451076917755,\n        \"gap\": 15.586906139714358\n      },\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": \"arrow\",\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          -0.5502191262773977,\n          33.25154356841597\n        ]\n      ]\n    },\n    {\n      \"type\": \"text\",\n      \"version\": 365,\n      \"versionNonce\": 1049066199,\n      \"isDeleted\": false,\n      \"id\": \"9t6qH-tAxVUexkHHi2pd2\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 617.3409291322284,\n      \"y\": 879.8675379636011,\n      \"strokeColor\": \"#1e1e1e\",\n      \"backgroundColor\": \"#ffc9c9\",\n      \"width\": 159.375,\n      \"height\": 57.599999999999994,\n      \"seed\": 1013545943,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [\n        {\n          \"id\": \"3heKY3vfe3-6ni4dX7Uqo\",\n          \"type\": \"arrow\"\n        }\n      ],\n      \"updated\": 1698927613071,\n      \"link\": null,\n      \"locked\": false,\n      \"fontSize\": 16,\n      \"fontFamily\": 3,\n      \"text\": \"pre minor\\nrelease\\ne.g. 3.4.0-beta.1\",\n      \"textAlign\": \"center\",\n      \"verticalAlign\": \"top\",\n      \"containerId\": null,\n      \"originalText\": \"pre minor\\nrelease\\ne.g. 3.4.0-beta.1\",\n      \"lineHeight\": 1.2,\n      \"baseline\": 53\n    },\n    {\n      \"type\": \"arrow\",\n      \"version\": 788,\n      \"versionNonce\": 1810072089,\n      \"isDeleted\": false,\n      \"id\": \"vEF1cIIYYWKm84KLKqEz3\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 630.3597332113623,\n      \"y\": 667.2735668205443,\n      \"strokeColor\": \"#f08c00\",\n      \"backgroundColor\": \"#ffc9c9\",\n      \"width\": 2.258228100583324,\n      \"height\": 140.75112333166828,\n      \"seed\": 2091697367,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1698927613072,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": {\n        \"elementId\": \"4v23gkfhy-hzk18YdkfLz\",\n        \"focus\": 0.13930391883256707,\n        \"gap\": 1.8256906627890626\n      },\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": \"arrow\",\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          1.8426514015177418,\n          69.09942755691065\n        ],\n        [\n          2.258228100583324,\n          140.75112333166828\n        ]\n      ]\n    },\n    {\n      \"type\": \"arrow\",\n      \"version\": 687,\n      \"versionNonce\": 2017318649,\n      \"isDeleted\": false,\n      \"id\": \"M14Q0Uo1DBy2Ss2SOFSgW\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 370.5976915356099,\n      \"y\": 667.5155013947814,\n      \"strokeColor\": \"#f08c00\",\n      \"backgroundColor\": \"#ffc9c9\",\n      \"width\": 1.5329291446666957,\n      \"height\": 145.39303664953377,\n      \"seed\": 361678233,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1698927613072,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": \"arrow\",\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          -0.34892760581925586,\n          83.56228079137543\n        ],\n        [\n          1.1840015388474399,\n          145.39303664953377\n        ]\n      ]\n    },\n    {\n      \"type\": \"text\",\n      \"version\": 537,\n      \"versionNonce\": 342487319,\n      \"isDeleted\": false,\n      \"id\": \"CHAOOJMz7tNaG1VsG_uzT\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 384.81046417498214,\n      \"y\": 725.4677076298137,\n      \"strokeColor\": \"#1e1e1e\",\n      \"backgroundColor\": \"#ffc9c9\",\n      \"width\": 131.25,\n      \"height\": 57.599999999999994,\n      \"seed\": 1656007289,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1698927613072,\n      \"link\": null,\n      \"locked\": false,\n      \"fontSize\": 16,\n      \"fontFamily\": 3,\n      \"text\": \"merge main\\ninto minor\\nbefore release\",\n      \"textAlign\": \"left\",\n      \"verticalAlign\": \"top\",\n      \"containerId\": null,\n      \"originalText\": \"merge main\\ninto minor\\nbefore release\",\n      \"lineHeight\": 1.2,\n      \"baseline\": 53\n    },\n    {\n      \"type\": \"ellipse\",\n      \"version\": 202,\n      \"versionNonce\": 876253145,\n      \"isDeleted\": false,\n      \"id\": \"hDC6an14QljktaZCUhcPF\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 993.0386151813434,\n      \"y\": 810.335845473903,\n      \"strokeColor\": \"#1e1e1e\",\n      \"backgroundColor\": \"#ffc9c9\",\n      \"width\": 18.814646969963974,\n      \"height\": 18.814646969963974,\n      \"seed\": 1433430105,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [\n        {\n          \"id\": \"Gao2krnDddLMCj468JSWD\",\n          \"type\": \"arrow\"\n        }\n      ],\n      \"updated\": 1698927613072,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"arrow\",\n      \"version\": 1525,\n      \"versionNonce\": 777631287,\n      \"isDeleted\": false,\n      \"id\": \"ces8IwHCpQlTnELpjFDIn\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1092.5386800881793,\n      \"y\": 827.5114796878765,\n      \"strokeColor\": \"#f08c00\",\n      \"backgroundColor\": \"#ffc9c9\",\n      \"width\": 0.3315362017829102,\n      \"height\": 49.45191086419197,\n      \"seed\": 225867737,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1698927613072,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": {\n        \"elementId\": \"8rWUxp-jRNGrGRmhHHfm4\",\n        \"focus\": -0.2047594653982401,\n        \"gap\": 10.392197401393389\n      },\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": \"arrow\",\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          -0.3315362017829102,\n          49.45191086419197\n        ]\n      ]\n    },\n    {\n      \"type\": \"text\",\n      \"version\": 894,\n      \"versionNonce\": 1173171385,\n      \"isDeleted\": false,\n      \"id\": \"8rWUxp-jRNGrGRmhHHfm4\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1047.251646167428,\n      \"y\": 887.3555879534618,\n      \"strokeColor\": \"#1e1e1e\",\n      \"backgroundColor\": \"#ffc9c9\",\n      \"width\": 112.5,\n      \"height\": 57.599999999999994,\n      \"seed\": 1600918713,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [\n        {\n          \"id\": \"ces8IwHCpQlTnELpjFDIn\",\n          \"type\": \"arrow\"\n        }\n      ],\n      \"updated\": 1698927613072,\n      \"link\": null,\n      \"locked\": false,\n      \"fontSize\": 16,\n      \"fontFamily\": 3,\n      \"text\": \"stable minor\\nrelease\\ne.g. 3.4.0\",\n      \"textAlign\": \"center\",\n      \"verticalAlign\": \"top\",\n      \"containerId\": null,\n      \"originalText\": \"stable minor\\nrelease\\ne.g. 3.4.0\",\n      \"lineHeight\": 1.2,\n      \"baseline\": 53\n    },\n    {\n      \"type\": \"ellipse\",\n      \"version\": 201,\n      \"versionNonce\": 78435447,\n      \"isDeleted\": false,\n      \"id\": \"3RHuRn_evSK0YUe02B4MY\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 909.9742423218671,\n      \"y\": 810.4142561718397,\n      \"strokeColor\": \"#2f9e44\",\n      \"backgroundColor\": \"#b2f2bb\",\n      \"width\": 18.814646969963974,\n      \"height\": 18.814646969963974,\n      \"seed\": 1199705047,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1698927613072,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"ellipse\",\n      \"version\": 371,\n      \"versionNonce\": 2093872087,\n      \"isDeleted\": false,\n      \"id\": \"9h2Cu__8owLUgUGjGcWDe\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 848.4414471158692,\n      \"y\": 650.826922928275,\n      \"strokeColor\": \"#1e1e1e\",\n      \"backgroundColor\": \"#b2f2bb\",\n      \"width\": 18.814646969963974,\n      \"height\": 18.814646969963974,\n      \"seed\": 603147257,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1698927613072,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"ellipse\",\n      \"version\": 361,\n      \"versionNonce\": 1981618457,\n      \"isDeleted\": false,\n      \"id\": \"s0PKxsWTJSDbQeEl_WI-C\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 777.1778842958995,\n      \"y\": 650.2466837635417,\n      \"strokeColor\": \"#2f9e44\",\n      \"backgroundColor\": \"#b2f2bb\",\n      \"width\": 18.814646969963974,\n      \"height\": 18.814646969963974,\n      \"seed\": 326722777,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [\n        {\n          \"id\": \"lwYvAs-7FTjcwxKjcx0KV\",\n          \"type\": \"arrow\"\n        }\n      ],\n      \"updated\": 1698927613072,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"text\",\n      \"version\": 871,\n      \"versionNonce\": 1528156247,\n      \"isDeleted\": false,\n      \"id\": \"3JAdSa7kqqSDSom5ZFDoE\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 904.3603861670398,\n      \"y\": 707.2413714353705,\n      \"strokeColor\": \"#1e1e1e\",\n      \"backgroundColor\": \"#ffc9c9\",\n      \"width\": 140.625,\n      \"height\": 57.599999999999994,\n      \"seed\": 1011049431,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1698927613072,\n      \"link\": null,\n      \"locked\": false,\n      \"fontSize\": 16,\n      \"fontFamily\": 3,\n      \"text\": \"final merge\\nmain into minor\\nbefore release\",\n      \"textAlign\": \"center\",\n      \"verticalAlign\": \"top\",\n      \"containerId\": null,\n      \"originalText\": \"final merge\\nmain into minor\\nbefore release\",\n      \"lineHeight\": 1.2,\n      \"baseline\": 53\n    },\n    {\n      \"type\": \"arrow\",\n      \"version\": 591,\n      \"versionNonce\": 1714373785,\n      \"isDeleted\": false,\n      \"id\": \"7kFBLq2Iczmj0lVnVk8Ad\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"dotted\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1100.7141458557703,\n      \"y\": 814.2034531496416,\n      \"strokeColor\": \"#2f9e44\",\n      \"backgroundColor\": \"#ffffff\",\n      \"width\": 127.38209933342364,\n      \"height\": 144.5383600420214,\n      \"seed\": 25829591,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1698927613072,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": {\n        \"elementId\": \"Y7VXnuc9QEz2N2l9i0xrc\",\n        \"focus\": 0.3932764551319699,\n        \"gap\": 5.928572790502042\n      },\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": \"arrow\",\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          88.94909573964219,\n          -43.721805169626464\n        ],\n        [\n          127.38209933342364,\n          -144.5383600420214\n        ]\n      ]\n    },\n    {\n      \"type\": \"text\",\n      \"version\": 1208,\n      \"versionNonce\": 1254600055,\n      \"isDeleted\": false,\n      \"id\": \"gwFWlPLabuYhxCOweJjWz\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1223.0464288187204,\n      \"y\": 725.1565933898091,\n      \"strokeColor\": \"#1e1e1e\",\n      \"backgroundColor\": \"#ffc9c9\",\n      \"width\": 150,\n      \"height\": 38.4,\n      \"seed\": 51102743,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1698927613072,\n      \"link\": null,\n      \"locked\": false,\n      \"fontSize\": 16,\n      \"fontFamily\": 3,\n      \"text\": \"main merge minor\\n(fast forward)\",\n      \"textAlign\": \"center\",\n      \"verticalAlign\": \"top\",\n      \"containerId\": null,\n      \"originalText\": \"main merge minor\\n(fast forward)\",\n      \"lineHeight\": 1.2,\n      \"baseline\": 34\n    },\n    {\n      \"type\": \"ellipse\",\n      \"version\": 597,\n      \"versionNonce\": 1760381305,\n      \"isDeleted\": false,\n      \"id\": \"Y7VXnuc9QEz2N2l9i0xrc\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1227.4473966637659,\n      \"y\": 647.6689320688656,\n      \"strokeColor\": \"#1e1e1e\",\n      \"backgroundColor\": \"#a5d8ff\",\n      \"width\": 18.814646969963974,\n      \"height\": 18.814646969963974,\n      \"seed\": 412038615,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [\n        {\n          \"id\": \"7kFBLq2Iczmj0lVnVk8Ad\",\n          \"type\": \"arrow\"\n        }\n      ],\n      \"updated\": 1698927613072,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"ellipse\",\n      \"version\": 547,\n      \"versionNonce\": 1585505943,\n      \"isDeleted\": false,\n      \"id\": \"ggogfJT7E_bbfEog7Hjnp\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1083.7911569735343,\n      \"y\": 809.5203742153592,\n      \"strokeColor\": \"#1e1e1e\",\n      \"backgroundColor\": \"#a5d8ff\",\n      \"width\": 18.814646969963974,\n      \"height\": 18.814646969963974,\n      \"seed\": 741463161,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [\n        {\n          \"id\": \"nRDWQs5nQa37yzCWTBiXC\",\n          \"type\": \"arrow\"\n        }\n      ],\n      \"updated\": 1698927613072,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"text\",\n      \"version\": 229,\n      \"versionNonce\": 1935127129,\n      \"isDeleted\": false,\n      \"id\": \"eU-EgpwDD42CLYUEIDLaD\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"dotted\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 305.8405004265049,\n      \"y\": 389.31989430571576,\n      \"strokeColor\": \"#1e1e1e\",\n      \"backgroundColor\": \"#a5d8ff\",\n      \"width\": 581.25,\n      \"height\": 19.2,\n      \"seed\": 1086231577,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1698927613072,\n      \"link\": null,\n      \"locked\": false,\n      \"fontSize\": 16,\n      \"fontFamily\": 3,\n      \"text\": \"- merge feature PRs into, and release minors from minor branch\",\n      \"textAlign\": \"left\",\n      \"verticalAlign\": \"top\",\n      \"containerId\": null,\n      \"originalText\": \"- merge feature PRs into, and release minors from minor branch\",\n      \"lineHeight\": 1.2,\n      \"baseline\": 15\n    },\n    {\n      \"type\": \"text\",\n      \"version\": 397,\n      \"versionNonce\": 116088535,\n      \"isDeleted\": false,\n      \"id\": \"Kt6VBAVD4sLM4IexsRGoX\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"dotted\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 305.4136207977353,\n      \"y\": 358.61173442109686,\n      \"strokeColor\": \"#1e1e1e\",\n      \"backgroundColor\": \"#a5d8ff\",\n      \"width\": 618.75,\n      \"height\": 19.2,\n      \"seed\": 273353945,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1698927617946,\n      \"link\": null,\n      \"locked\": false,\n      \"fontSize\": 16,\n      \"fontFamily\": 3,\n      \"text\": \"- merge fix / chore PRs into, and release patches from main branch\",\n      \"textAlign\": \"left\",\n      \"verticalAlign\": \"top\",\n      \"containerId\": null,\n      \"originalText\": \"- merge fix / chore PRs into, and release patches from main branch\",\n      \"lineHeight\": 1.2,\n      \"baseline\": 15\n    },\n    {\n      \"type\": \"text\",\n      \"version\": 459,\n      \"versionNonce\": 440532793,\n      \"isDeleted\": false,\n      \"id\": \"JwKEdnU6H_Nu74WbEAX5M\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"dotted\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 305.6723761009271,\n      \"y\": 418.3724478537203,\n      \"strokeColor\": \"#1e1e1e\",\n      \"backgroundColor\": \"#a5d8ff\",\n      \"width\": 459.375,\n      \"height\": 19.2,\n      \"seed\": 1001222329,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1698927613072,\n      \"link\": null,\n      \"locked\": false,\n      \"fontSize\": 16,\n      \"fontFamily\": 3,\n      \"text\": \"- merge main into minor before each minor release\",\n      \"textAlign\": \"left\",\n      \"verticalAlign\": \"top\",\n      \"containerId\": null,\n      \"originalText\": \"- merge main into minor before each minor release\",\n      \"lineHeight\": 1.2,\n      \"baseline\": 15\n    },\n    {\n      \"type\": \"text\",\n      \"version\": 602,\n      \"versionNonce\": 1108720119,\n      \"isDeleted\": false,\n      \"id\": \"mb9ZoP803MiH7MTO8wH-2\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"dotted\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 305.0895924262568,\n      \"y\": 447.44321411383333,\n      \"strokeColor\": \"#1e1e1e\",\n      \"backgroundColor\": \"#a5d8ff\",\n      \"width\": 534.375,\n      \"height\": 19.2,\n      \"seed\": 264651479,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1698927613072,\n      \"link\": null,\n      \"locked\": false,\n      \"fontSize\": 16,\n      \"fontFamily\": 3,\n      \"text\": \"- fast forward main to minor after a stable minor release\",\n      \"textAlign\": \"left\",\n      \"verticalAlign\": \"top\",\n      \"containerId\": null,\n      \"originalText\": \"- fast forward main to minor after a stable minor release\",\n      \"lineHeight\": 1.2,\n      \"baseline\": 15\n    },\n    {\n      \"type\": \"text\",\n      \"version\": 612,\n      \"versionNonce\": 1588872441,\n      \"isDeleted\": false,\n      \"id\": \"IfJPOFiwrCibpaBQqc5g-\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 646.7131179044119,\n      \"y\": 724.4984335940012,\n      \"strokeColor\": \"#1e1e1e\",\n      \"backgroundColor\": \"#ffc9c9\",\n      \"width\": 131.25,\n      \"height\": 57.599999999999994,\n      \"seed\": 1301100087,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1698927613072,\n      \"link\": null,\n      \"locked\": false,\n      \"fontSize\": 16,\n      \"fontFamily\": 3,\n      \"text\": \"merge main\\ninto minor\\nbefore release\",\n      \"textAlign\": \"left\",\n      \"verticalAlign\": \"top\",\n      \"containerId\": null,\n      \"originalText\": \"merge main\\ninto minor\\nbefore release\",\n      \"lineHeight\": 1.2,\n      \"baseline\": 53\n    }\n  ],\n  \"appState\": {\n    \"gridSize\": null,\n    \"viewBackgroundColor\": \"#ffffff\"\n  },\n  \"files\": {}\n}"
  },
  {
    "path": ".github/maintenance.md",
    "content": "# Vue Core Maintenance Handbook\n\nUnlike [contributing.md](./contributing.md), which targets external contributors, this document is mainly intended for team members responsible for maintaining the project. It provides guidelines on how to triage issues, review & merge PRs, and publish releases. However, it should also be valuable to external contributors even if you are not a maintainer, as it gives you a better idea of how the maintainers operate, and how you can better collaborate with them. And who knows - maybe one day you will join as a maintainer as well!\n\n- [Issue Triage Workflow](#issue-triage-workflow)\n- [Pull Request Review Guidelines](#pull-request-review-guidelines)\n  - [Reviewing a Fix](#reviewing-a-fix)\n  - [Reviewing a Refactor](#reviewing-a-refactor)\n  - [Reviewing a Feature](#reviewing-a-feature)\n  - [Common Considerations for All PRs](#common-considerations-for-all-prs)\n- [PR Merge Rules for Team Members](#pr-merge-rules-for-team-members)\n- [Git Branch and Release Workflow](#git-branch-and-release-workflow)\n\n## Issue Triage Workflow\n\n![Workflow](./issue-workflow.png)\n\n## Pull Request Review Guidelines\n\nThe first step of reviewing a PR is to identify its purpose. We can usually put a PR in one of these categories:\n\n- **Fix**: fixes some wrong behavior. Usually associated with an issue that has a reproduction of the behavior being fixed.\n- **Refactor**: improves performance or code quality, but does not affect behavior.\n- **Feature**: implements something that increases the public API surface.\n\nDepending on the type of the PR, different considerations need to be taken into account.\n\n### Reviewing a Fix\n\n- Is the PR fixing a well defined issue / bug report?\n  - If not, ask to clarify context / provide reproduction or failing test case\n- In most cases, a fix PR should include a test case that fails without the fix.\n- Is it the right fix?\n  - If not, guide user to rework the PR.\n  - If the needed change is small and obvious, can directly push to the PR or add inline suggestions to reduce the back-and-forth.\n- Is the cost justified?\n  - Sometimes the fix for a rare edge case might be introducing disproportionately large overhead (perf or code size). We should try our best to reduce the overhead to make the fix a reasonable tradeoff.\n- If the reviewer is not sure about a fix, try to leave a comment explaining the concerns / reservations so the contributor at least gets some feedback.\n\n#### Verifying a Fix\n\n- **Always locally verify that the fix indeed fixes the original behavior, either through a reproduction or a failing test case.**\n- We will run [ecosystem-ci](https://github.com/vuejs/ecosystem-ci) before every release, but if you are concerned about the potential impact of a change, it never hurts to manually run ecosystem-ci by leaving a `/ecosystem-ci run` comment (only works for team members).\n- Take extra caution with snapshot tests! The CI can be \"passing\" even if the code generated in the snapshot contains bugs. It's best to always accompany a snapshot test with extra `expect(code).toMatch(...)` assertions.\n\n### Reviewing a Refactor\n\n- Performance: if a refactor PR claims to improve performance, there should be benchmarks showcasing said performance unless the improvement is self-explanatory.\n\n- Code quality / stylistic PRs: we should be conservative on merging this type of PRs because (1) they can be subjective in many cases, and (2) they often come with large git diffs, causing merge conflicts with other pending PRs, and leading to unwanted noise when tracing changes through git history. Use your best judgement on this type of PRs on whether they are worth it.\n  - For PRs in this category that are approved, do not merge immediately. Group them before releasing a new minor, after all feature-oriented PRs are merged.\n\n### Reviewing a Feature\n\n- Feature PRs should always have clear context and explanation on why the feature should be added, ideally in the form of an RFC. If the PR doesn't explain what real-world problem it is solving, ask the contributor to clarify.\n\n- Decide if the feature should require an RFC process. The line isn't always clear, but a rough criteria is whether it is augmenting an existing API vs. adding a new API. Some examples:\n  - Adding a new built-in component or directive is \"significant\" and definitely requires an RFC.\n  - Template syntax additions like adding a new `v-on` modifier or a new `v-bind` syntax sugar are \"substantial\". It would be nice to have an RFC for it, but a detailed explanation on the use case and reasoning behind the design directly in the PR itself can be acceptable.\n  - Small, low-impact additions like exposing a new utility type or adding a new app config option can be self-explanatory, but should still provide enough context in the PR.\n\n- Always ask if the use case can be solved with existing APIs. Vue already has a pretty large API surface, so we want to make sure every new addition either solves something that wasn't possible before, or significantly improves the DX of a common task.\n\n### Common Considerations for All PRs\n\n- Scope: a PR should only contain changes directly related to the problem being addressed. It should not contain unnecessary code style changes.\n\n- Implementation: code style should be consistent with the rest of the codebase, follow common best practices. Prefer code that is boring but easy to understand over \"clever\" code.\n\n- Size: bundle size matters. We have a GitHub action that compares the size change for every PR. We should always aim to realize the desired changes with the smallest amount of code size increase.\n  - Sometimes we need to compare the size increase vs. perceived benefits to decide whether a change is justifiable. Also take extra care to make sure added code can be tree-shaken if not needed.\n\n  - Make sure to put dev-only code in `__DEV__` branches so they are tree-shakable.\n\n  - Runtime code is more sensitive to size increase than compiler code.\n\n  - Make sure it doesn't accidentally cause dev-only or compiler-only code branches to be included in the runtime build. Notable case is that some functions in @vue/shared are compiler-only and should not be used in runtime code, e.g. `isHTMLTag` and `isSVGTag`.\n\n- Performance\n  - Be careful about code changes in \"hot paths\", in particular the Virtual DOM renderer (`runtime-core/src/renderer.ts`) and component instantiation code.\n\n- Potential Breakage\n  - avoiding runtime behavior breakage is the highest priority\n    - if not sure, use `ecosystem-ci` to verify!\n  - some fixes inevitably cause behavior change, these must be discussed case-by-case\n  - type level breakage (e.g upgrading TS) is possible between minors\n\n## PR Merge Rules for Team Members\n\nGiven that the PR meets the review requirements:\n\n- Chore / dependencies bumps: can merge directly.\n- Fixes / refactors: can merge with two or more approvals from team members.\n  - If you believe a PR looks good but you are not 100% confident to merge, label with \"ready for merge\" and Evan will provide a final review before merging.\n- Features: if approved by two or more team members, label with \"ready to merge\". Evan will review periodically, or they can be raised and discussed at team meetings.\n\n## Git Branch and Release Workflow\n\nWe use two primary work branches: `main` and `minor`.\n\n- The `main` branch is for stable releases. Changes that are bug fixes or refactors that do not affect the public API surface should land in this branch. We periodically release patch releases from the `main` branch.\n\n- The `minor` branch is the WIP branch for the next minor release. Changes that are new features or those that affect public API behavior should land in this branch. We will periodically release pre-releases (alpha / beta) for the next minor from this branch.\n\nBefore each release, we merge latest `main` into `minor` so it would include the latest bug fixes.\n\nWhen the minor is ready, we do a final merge of `main` into `minor`, and then release a stable minor from this branch (e.g. `3.4.0`). After that, the `main` branch is fast-forwarded to the release commit, so the two branches are synced at each stable minor release.\n\n![Workflow](./git-branch-workflow.png)\n\n### Reasoning Behind the Workflow\n\nThe reason behind this workflow is to allow merging and releasing of fixes and features in parallel. In the past, we used a linear trunk-based development model. While the linear model results in a clean git history, the downside is that we need to be careful about when to merge patches vs. features.\n\nVue typically groups a number of features with the same scope in a minor release. We don't want to release a minor just because we happened to merge a feature PR along with a bunch of small bug fixes. So we usually \"wait\" until we feel we are ready to start working on a minor release before merging feature PRs.\n\nBut in reality, there are always bugs to fix and patch release to work on - this caused the intervals between minors to drag on longer than we had hoped, and many feature PRs were left waiting for a long period of time.\n\nThis is why we decided to separate bug fixes and feature PRs into separate branches. With this two-branch model, we are able to merge and release both types of changes in parallel.\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  packageRules: [\n    {\n      matchDepTypes: ['peerDependencies'],\n      enabled: false,\n    },\n    {\n      groupName: 'test',\n      matchPackageNames: ['vitest', 'jsdom', 'puppeteer', '@vitest{/,}**'],\n    },\n    {\n      groupName: 'playground',\n      matchFileNames: [\n        'packages-private/sfc-playground/package.json',\n        'packages-private/template-explorer/package.json',\n      ],\n    },\n    {\n      groupName: 'compiler',\n      matchPackageNames: ['magic-string', '@babel{/,}**', 'postcss{/,}**'],\n    },\n    {\n      groupName: 'build',\n      matchPackageNames: [\n        'vite',\n        '@swc/core',\n        'rollup{/,}**',\n        'esbuild{/,}**',\n        '@rollup{/,}**',\n        '@vitejs{/,}**',\n      ],\n    },\n    {\n      groupName: 'lint',\n      matchPackageNames: [\n        'simple-git-hooks',\n        'lint-staged',\n        'typescript-eslint{/,}**',\n        'eslint{/,}**',\n        'prettier{/,}**',\n      ],\n    },\n  ],\n  ignoreDeps: [\n    'vue',\n\n    // manually bumping\n    'node',\n    'typescript',\n\n    // ESM only\n    'estree-walker',\n\n    // pinned\n    // https://github.com/vuejs/core/issues/10300#issuecomment-1940855364\n    'lru-cache',\n\n    // pinned\n    // https://github.com/vuejs/core/commit/a012e39b373f1b6918e5c89856e8f902e1bfa14d\n    '@rollup/plugin-replace',\n\n    // pinned\n    // only used in example for e2e tests\n    'marked',\n  ],\n}\n"
  },
  {
    "path": ".github/workflows/autofix.yml",
    "content": "name: autofix.ci\n\non:\n  pull_request:\npermissions:\n  contents: read\n\njobs:\n  autofix:\n    runs-on: ubuntu-latest\n    env:\n      PUPPETEER_SKIP_DOWNLOAD: 'true'\n    steps:\n      - uses: actions/checkout@v6\n\n      - name: Install pnpm\n        uses: pnpm/action-setup@v4.2.0\n\n      - name: Install Node.js\n        uses: actions/setup-node@v6\n        with:\n          node-version-file: '.node-version'\n          registry-url: 'https://registry.npmjs.org'\n          cache: 'pnpm'\n\n      - run: pnpm install\n\n      - name: Run eslint\n        run: pnpm run lint --fix\n\n      - name: Run prettier\n        run: pnpm run format\n\n      - uses: autofix-ci/action@7a166d7532b277f34e16238930461bf77f9d7ed8\n"
  },
  {
    "path": ".github/workflows/ci.yml",
    "content": "name: 'ci'\non:\n  push:\n    branches:\n      - '**'\n    tags:\n      - '!**'\n  pull_request:\n    branches:\n      - main\n      - minor\n\njobs:\n  test:\n    if: ${{ ! startsWith(github.event.head_commit.message, 'release:') && (github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository) }}\n    uses: ./.github/workflows/test.yml\n\n  continuous-release:\n    if: github.repository == 'vuejs/core'\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v6\n\n      - name: Install pnpm\n        uses: pnpm/action-setup@v4\n\n      - name: Install Node.js\n        uses: actions/setup-node@v6\n        with:\n          node-version-file: '.node-version'\n          registry-url: 'https://registry.npmjs.org'\n          cache: 'pnpm'\n\n      - name: Install deps\n        run: pnpm install\n\n      - name: Build\n        run: pnpm build --withTypes\n\n      - name: Release\n        run: pnpx pkg-pr-new publish --compact --pnpm './packages/*' --packageManager=pnpm,npm,yarn\n"
  },
  {
    "path": ".github/workflows/close-cant-reproduce-issues.yml",
    "content": "name: Auto close issues with \"can't reproduce\" label\n\non:\n  schedule:\n    - cron: '0 0 * * *'\n\npermissions:\n  issues: write\n\njobs:\n  close-issues:\n    if: github.repository == 'vuejs/core'\n    runs-on: ubuntu-latest\n    steps:\n      - name: can't reproduce\n        uses: actions-cool/issues-helper@v3\n        with:\n          actions: 'close-issues'\n          token: ${{ secrets.GITHUB_TOKEN }}\n          labels: \"can't reproduce\"\n          inactive-day: 3\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-latest\n    if: github.repository == 'vuejs/core' && github.event.issue.pull_request && startsWith(github.event.comment.body, '/ecosystem-ci run')\n    steps:\n      - name: Check user permission\n        uses: actions/github-script@v8\n        with:\n          script: |\n            const user = context.payload.sender.login\n            console.log(`Validate user: ${user}`)\n\n            let isVuejsMember = false\n            try {\n              const { status } = await github.rest.orgs.checkMembershipForUser({\n                org: 'vuejs',\n                username: user\n              });\n\n              isVuejsMember = (status === 204)\n            } catch (e) {}\n\n            if (isVuejsMember) {\n              console.log('Allowed')\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('Not allowed')\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('not allowed')\n            }\n      - name: Get PR info\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            return {\n              num: context.issue.number,\n              branchName: pr.head.ref,\n              repo: pr.head.repo.full_name,\n              commit: pr.head.sha\n            }\n      - name: Trigger run\n        uses: actions/github-script@v8\n        id: trigger\n        env:\n          COMMENT: ${{ github.event.comment.body }}\n        with:\n          github-token: ${{ secrets.ECOSYSTEM_CI_ACCESS_TOKEN }}\n          result-encoding: string\n          script: |\n            const comment = process.env.COMMENT.trim()\n            const prData = ${{ steps.get-pr-data.outputs.result }}\n\n            const suite = comment.replace(/^\\/ecosystem-ci run/, '').trim()\n\n            await github.rest.actions.createWorkflowDispatch({\n              owner: context.repo.owner,\n              repo: '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                suite: suite === '' ? '-' : suite,\n                commit: prData.commit\n              }\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 == 'vuejs/core'\n    runs-on: ubuntu-latest\n    steps:\n      - uses: dessant/lock-threads@v6\n        with:\n          github-token: ${{ secrets.GITHUB_TOKEN }}\n          issue-inactive-days: '14'\n          issue-lock-reason: ''\n          process-only: 'issues'\n"
  },
  {
    "path": ".github/workflows/release.yml",
    "content": "name: Release\n\non:\n  push:\n    tags:\n      - 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10\n\njobs:\n  test:\n    uses: ./.github/workflows/test.yml\n\n  release:\n    # prevents this action from running on forks\n    if: github.repository == 'vuejs/core'\n    needs: [test]\n    runs-on: ubuntu-latest\n    permissions:\n      contents: write\n      id-token: write\n    # Use Release environment for deployment protection\n    environment: Release\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v6\n\n      - name: Install pnpm\n        uses: pnpm/action-setup@v4\n\n      - name: Install Node.js\n        uses: actions/setup-node@v6\n        with:\n          node-version-file: '.node-version'\n          registry-url: 'https://registry.npmjs.org'\n          cache: 'pnpm'\n\n      - name: Install deps\n        run: pnpm install\n\n      - name: Update npm\n        run: npm i -g npm@latest\n\n      - name: Build and publish\n        id: publish\n        run: |\n          pnpm release --publishOnly\n\n      - name: Create GitHub release\n        id: release_tag\n        uses: yyx990803/release-tag@master\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n        with:\n          tag_name: ${{ github.ref }}\n          body: |\n            For stable releases, please refer to [CHANGELOG.md](https://github.com/vuejs/core/blob/main/CHANGELOG.md) for details.\n            For pre-releases, please refer to [CHANGELOG.md](https://github.com/vuejs/core/blob/minor/CHANGELOG.md) of the `minor` branch.\n"
  },
  {
    "path": ".github/workflows/size-data.yml",
    "content": "name: size data\n\non:\n  push:\n    branches:\n      - main\n      - minor\n  pull_request:\n    branches:\n      - main\n      - minor\n\npermissions:\n  contents: read\n\nenv:\n  PUPPETEER_SKIP_DOWNLOAD: 'true'\n\njobs:\n  upload:\n    if: github.repository == 'vuejs/core'\n    runs-on: ubuntu-latest\n\n    steps:\n      - uses: actions/checkout@v6\n\n      - name: Install pnpm\n        uses: pnpm/action-setup@v4.2.0\n\n      - name: Install Node.js\n        uses: actions/setup-node@v6\n        with:\n          node-version-file: '.node-version'\n          cache: pnpm\n\n      - name: Install dependencies\n        run: pnpm install\n\n      - run: pnpm run size\n\n      - name: Save PR number & base branch\n        if: ${{github.event_name == 'pull_request'}}\n        run: |\n          echo ${{ github.event.number }} > ./temp/size/number.txt\n          echo ${{ github.base_ref }} > ./temp/size/base.txt\n\n      - name: Upload Size Data\n        uses: actions/upload-artifact@v7\n        with:\n          name: size-data\n          path: temp/size\n"
  },
  {
    "path": ".github/workflows/size-report.yml",
    "content": "name: size report\n\non:\n  workflow_run:\n    workflows: ['size data']\n    types:\n      - completed\n\npermissions:\n  contents: read\n  pull-requests: write\n  issues: write\n\nenv:\n  PUPPETEER_SKIP_DOWNLOAD: 'true'\n\njobs:\n  size-report:\n    runs-on: ubuntu-latest\n    if: >\n      github.repository == 'vuejs/core' &&\n      github.event.workflow_run.event == 'pull_request' &&\n      github.event.workflow_run.conclusion == 'success'\n    steps:\n      - uses: actions/checkout@v6\n\n      - name: Install pnpm\n        uses: pnpm/action-setup@v4.2.0\n\n      - name: Install Node.js\n        uses: actions/setup-node@v6\n        with:\n          node-version-file: '.node-version'\n          cache: pnpm\n\n      - name: Install dependencies\n        run: pnpm install\n\n      - name: Download Size Data\n        uses: dawidd6/action-download-artifact@v14\n        with:\n          name: size-data\n          run_id: ${{ github.event.workflow_run.id }}\n          path: temp/size\n\n      - name: Read PR Number\n        id: pr-number\n        uses: juliangruber/read-file-action@v1\n        with:\n          path: temp/size/number.txt\n\n      - name: Read base branch\n        id: pr-base\n        uses: juliangruber/read-file-action@v1\n        with:\n          path: temp/size/base.txt\n\n      - name: Download Previous Size Data\n        uses: dawidd6/action-download-artifact@v14\n        with:\n          branch: ${{ steps.pr-base.outputs.content }}\n          workflow: size-data.yml\n          event: push\n          name: size-data\n          path: temp/size-prev\n          if_no_artifact_found: warn\n\n      - name: Prepare report\n        run: node scripts/size-report.js > size-report.md\n\n      - name: Read Size Report\n        id: size-report\n        uses: juliangruber/read-file-action@v1\n        with:\n          path: ./size-report.md\n\n      - name: Create Comment\n        uses: actions-cool/maintain-one-comment@v3\n        with:\n          token: ${{ secrets.GITHUB_TOKEN }}\n          number: ${{ steps.pr-number.outputs.content }}\n          body: |\n            ${{ steps.size-report.outputs.content }}\n            <!-- VUE_CORE_SIZE -->\n          body-include: '<!-- VUE_CORE_SIZE -->'\n"
  },
  {
    "path": ".github/workflows/test.yml",
    "content": "name: 'test'\n\non: workflow_call\n\npermissions:\n  contents: read # to fetch code (actions/checkout)\n\njobs:\n  unit-test:\n    runs-on: ubuntu-latest\n    env:\n      PUPPETEER_SKIP_DOWNLOAD: 'true'\n    steps:\n      - uses: actions/checkout@v6\n\n      - name: Install pnpm\n        uses: pnpm/action-setup@v4.2.0\n\n      - name: Install Node.js\n        uses: actions/setup-node@v6\n        with:\n          node-version-file: '.node-version'\n          cache: 'pnpm'\n\n      - run: pnpm install\n\n      - name: Run unit tests\n        run: pnpm run test-unit\n\n  unit-test-windows:\n    runs-on: windows-latest\n    env:\n      PUPPETEER_SKIP_DOWNLOAD: 'true'\n    steps:\n      - uses: actions/checkout@v6\n\n      - name: Install pnpm\n        uses: pnpm/action-setup@v4.2.0\n\n      - name: Install Node.js\n        uses: actions/setup-node@v6\n        with:\n          node-version-file: '.node-version'\n          cache: 'pnpm'\n\n      - run: pnpm install\n\n      - name: Run compiler unit tests\n        run: pnpm run test-unit compiler\n\n      - name: Run ssr unit tests\n        run: pnpm run test-unit server-renderer\n\n  e2e-test:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v6\n\n      - name: Setup cache for Chromium binary\n        uses: actions/cache@v5\n        with:\n          path: ~/.cache/puppeteer\n          key: chromium-${{ hashFiles('pnpm-lock.yaml') }}\n\n      - name: Install pnpm\n        uses: pnpm/action-setup@v4.2.0\n\n      - name: Install Node.js\n        uses: actions/setup-node@v6\n        with:\n          node-version-file: '.node-version'\n          cache: 'pnpm'\n\n      - run: pnpm install\n      - run: node node_modules/puppeteer/install.mjs\n\n      - name: Run e2e tests\n        run: pnpm run test-e2e\n\n      - name: verify treeshaking\n        run: node scripts/verify-treeshaking.js\n\n  lint-and-test-dts:\n    runs-on: ubuntu-latest\n    env:\n      PUPPETEER_SKIP_DOWNLOAD: 'true'\n    steps:\n      - uses: actions/checkout@v6\n\n      - name: Install pnpm\n        uses: pnpm/action-setup@v4.2.0\n\n      - name: Install Node.js\n        uses: actions/setup-node@v6\n        with:\n          node-version-file: '.node-version'\n          cache: 'pnpm'\n\n      - run: pnpm install\n\n      - name: Run eslint\n        run: pnpm run lint\n\n      - name: Run prettier\n        run: pnpm run format-check\n\n      - name: Run tsc\n        run: pnpm run check\n\n      - name: Run type declaration tests\n        run: pnpm run test-dts\n"
  },
  {
    "path": ".gitignore",
    "content": "dist\n.DS_Store\nnode_modules\ncoverage\ntemp\nexplorations\nTODOs.md\n*.log\n.idea\n.eslintcache\ndts-build/packages\n*.tsbuildinfo\n*.tgz\n"
  },
  {
    "path": ".node-version",
    "content": "lts/*"
  },
  {
    "path": ".prettierignore",
    "content": "dist\npnpm-lock.yaml\nCHANGELOG*.md\n"
  },
  {
    "path": ".prettierrc",
    "content": "{\n  \"semi\": false,\n  \"singleQuote\": true,\n  \"arrowParens\": \"avoid\"\n}\n"
  },
  {
    "path": ".vscode/extensions.json",
    "content": "{\n  \"recommendations\": [\"vitest.explorer\"]\n}\n"
  },
  {
    "path": ".vscode/launch.json",
    "content": "{\n  // Use IntelliSense to learn about possible attributes.\n  // Hover to view descriptions of existing attributes.\n  // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387\n  \"version\": \"0.2.0\",\n  \"configurations\": [\n    {\n      \"type\": \"node\",\n      \"request\": \"launch\",\n      \"name\": \"Vitest - Debug Current Test File\",\n      \"autoAttachChildProcesses\": true,\n      \"skipFiles\": [\"<node_internals>/**\", \"**/node_modules/**\"],\n      \"program\": \"${workspaceRoot}/node_modules/vitest/vitest.mjs\",\n      \"args\": [\"run\", \"${relativeFile}\"],\n      \"smartStep\": true,\n      \"console\": \"integratedTerminal\"\n    }\n  ]\n}\n"
  },
  {
    "path": ".vscode/settings.json",
    "content": "{\n  // Use the project's typescript version\n  \"typescript.tsdk\": \"node_modules/typescript/lib\",\n\n  \"cSpell.enabledLanguageIds\": [\"markdown\", \"plaintext\", \"text\", \"yml\"],\n\n  // Use prettier to format TypeScript, JavaScript and JSON files\n  \"[typescript]\": {\n    \"editor.defaultFormatter\": \"esbenp.prettier-vscode\"\n  },\n  \"[javascript]\": {\n    \"editor.defaultFormatter\": \"esbenp.prettier-vscode\"\n  },\n  \"[json]\": {\n    \"editor.defaultFormatter\": \"esbenp.prettier-vscode\"\n  },\n  \"editor.formatOnSave\": true\n}\n"
  },
  {
    "path": ".well-known/funding-manifest-urls",
    "content": "https://vuejs.org/funding.json\n"
  },
  {
    "path": "BACKERS.md",
    "content": "<h1 align=\"center\">Sponsors &amp; Backers</h1>\n\nVue.js is an MIT-licensed open source project with its ongoing development made possible entirely by the support of the awesome sponsors and backers listed in this file. If you'd like to join them, please consider [ sponsoring Vue's development](https://vuejs.org/sponsor/).\n\n<p align=\"center\">\n  <a target=\"_blank\" href=\"https://sponsors.vuejs.org/backers.svg\">\n    <img alt=\"sponsors\" src=\"https://sponsors.vuejs.org/backers.svg?v1\">\n  </a>\n</p>\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "## [3.5.30](https://github.com/vuejs/core/compare/v3.5.29...v3.5.30) (2026-03-09)\n\n\n### Bug Fixes\n\n* **compat:** add `entities` to @vue/compat deps to fix CJS edge cases ([#12514](https://github.com/vuejs/core/issues/12514)) ([e725a67](https://github.com/vuejs/core/commit/e725a679e434a688c3493fc9af496501a8d1eeec)), closes [#10609](https://github.com/vuejs/core/issues/10609)\n* **custom-element:** ensure child component styles are injected in correct order before parent styles ([#13374](https://github.com/vuejs/core/issues/13374)) ([1398bf8](https://github.com/vuejs/core/commit/1398bf8dfbfef6b1bca154fc98d37044011a51be)), closes [#13029](https://github.com/vuejs/core/issues/13029)\n* **custom-element:** properly locate parent when slotted in shadow dom ([#12480](https://github.com/vuejs/core/issues/12480)) ([f06c81a](https://github.com/vuejs/core/commit/f06c81aa3dddbeff8bc2e2e63c0b6b6debcbdc13)), closes [#12479](https://github.com/vuejs/core/issues/12479)\n* **custom-element:** should properly patch as props for vue custom elements ([#12409](https://github.com/vuejs/core/issues/12409)) ([740983e](https://github.com/vuejs/core/commit/740983e6736255b183ee27a3f8b40e89ad7e3ba3)), closes [#12408](https://github.com/vuejs/core/issues/12408)\n* **reactivity:** avoid duplicate raw/proxy entries in Set.add ([#14545](https://github.com/vuejs/core/issues/14545)) ([d943612](https://github.com/vuejs/core/commit/d943612e59feb656e16568dea77b97856923c58c))\n* **reactivity:** fix reduce on reactive arrays to preserve reactivity ([#12737](https://github.com/vuejs/core/issues/12737)) ([16ef165](https://github.com/vuejs/core/commit/16ef165415224def18ec8247dabb84d5a1338c17)), closes [#12735](https://github.com/vuejs/core/issues/12735)\n* **reactivity:** handle `Set` with initial reactive values edge case ([#12393](https://github.com/vuejs/core/issues/12393)) ([5dc27ca](https://github.com/vuejs/core/commit/5dc27ca68fdbab95b37af15870d91515fc2412b2)), closes [#8647](https://github.com/vuejs/core/issues/8647)\n* **runtime-core:** warn about negative number in v-for ([#12308](https://github.com/vuejs/core/issues/12308)) ([9438cc5](https://github.com/vuejs/core/commit/9438cc54506a38038a1bf4b6698025f9a4cafb48))\n* **ssr:** prevent watch from firing after async setup await ([#14547](https://github.com/vuejs/core/issues/14547)) ([6cda71d](https://github.com/vuejs/core/commit/6cda71d48bd45c5e0ed2822866b83c4fafff1be9)), closes [#14546](https://github.com/vuejs/core/issues/14546)\n* **types:** make generics with runtime props in defineComponent work (fix [#11374](https://github.com/vuejs/core/issues/11374)) ([#13119](https://github.com/vuejs/core/issues/13119)) ([cea3cf7](https://github.com/vuejs/core/commit/cea3cf758645c9683db51822590b073ce3069dda)), closes [#13763](https://github.com/vuejs/core/issues/13763)\n* **types:** narrow useAttrs class/style typing for TSX ([#14492](https://github.com/vuejs/core/issues/14492)) ([bbb8977](https://github.com/vuejs/core/commit/bbb89775b137eac12b92ae4eb49999a7fd6b52b0)), closes [#14489](https://github.com/vuejs/core/issues/14489)\n\n\n\n## [3.5.29](https://github.com/vuejs/core/compare/v3.5.28...v3.5.29) (2026-02-24)\n\n\n### Bug Fixes\n\n* **runtime-core:** prevent instance leak in withAsyncContext ([#14445](https://github.com/vuejs/core/issues/14445)) ([702284f](https://github.com/vuejs/core/commit/702284f6a7d0dd6d4e648142e7977a3eb02d77f5)), closes [nuxt/nuxt#33644](https://github.com/nuxt/nuxt/issues/33644)\n* **server-renderer:** render className as escaped string ([#14469](https://github.com/vuejs/core/issues/14469)) ([da6690c](https://github.com/vuejs/core/commit/da6690cae359ec3576403c18040a1a5f017a63b1))\n* **transition:** prevent enter if leave is in progress ([#14443](https://github.com/vuejs/core/issues/14443)) ([df059f8](https://github.com/vuejs/core/commit/df059f890460e4c703b62a54f410627ff29c489b)), closes [#12091](https://github.com/vuejs/core/issues/12091) [#12133](https://github.com/vuejs/core/issues/12133)\n\n\n\n## [3.5.28](https://github.com/vuejs/core/compare/v3.5.27...v3.5.28) (2026-02-09)\n\n\n### Bug Fixes\n\n* **transition:** avoid unexpected `cancelled` parameter in transition `done` callback ([#14391](https://github.com/vuejs/core/issues/14391)) ([6798853](https://github.com/vuejs/core/commit/67988530f6a3cfdd0d80bf967033cb9abf377174))\n* **compiler-sfc:** add resolution trying for `.mts/.cts` files ([#14402](https://github.com/vuejs/core/issues/14402)) ([c09d41f](https://github.com/vuejs/core/commit/c09d41ffe150903b1fcd69a6f6bdeea2d2c6c243)), closes [vuejs/router#2611](https://github.com/vuejs/router/issues/2611)\n* **compiler-sfc:** no params were generated when using withDefaults ([#12823](https://github.com/vuejs/core/issues/12823)) ([b0a1f05](https://github.com/vuejs/core/commit/b0a1f0504a67fb1a6a110a5d05cdec0b878dde29)), closes [#12822](https://github.com/vuejs/core/issues/12822)\n* **reactivity:** add `__v_skip` flag to `EffectScope` to prevent reactive conversion ([#14359](https://github.com/vuejs/core/issues/14359)) ([48b7552](https://github.com/vuejs/core/commit/48b7552cce784725376a4fab078272676ce02d69)), closes [#14357](https://github.com/vuejs/core/issues/14357)\n* **runtime-core:** avoid retaining el on cached text vnodes during static traversal ([#14419](https://github.com/vuejs/core/issues/14419)) ([4ace79a](https://github.com/vuejs/core/commit/4ace79ac4c66a4f96cd330b47474ce117bc851ab)), closes [#14134](https://github.com/vuejs/core/issues/14134)\n* **runtime-core:** prevent child component updates when style remains unchanged ([#12825](https://github.com/vuejs/core/issues/12825)) ([57866b5](https://github.com/vuejs/core/commit/57866b5af1aff7ce1026b529443b81465c56f802)), closes [#12826](https://github.com/vuejs/core/issues/12826)\n* **runtime-core:** properly handle async component update before resolve ([#11619](https://github.com/vuejs/core/issues/11619)) ([e71c26c](https://github.com/vuejs/core/commit/e71c26c03d44c9c93569ed7ebfe7dabaf3bbdb06)), closes [#11617](https://github.com/vuejs/core/issues/11617)\n* **runtime-dom:** handle null/undefined handler in withModifiers ([#14362](https://github.com/vuejs/core/issues/14362)) ([261de54](https://github.com/vuejs/core/commit/261de547cd6685fc8862679941d93b530d504731)), closes [#14361](https://github.com/vuejs/core/issues/14361)\n* **teleport:** properly handling disabled teleport target anchor ([#14417](https://github.com/vuejs/core/issues/14417)) ([d7bcd85](https://github.com/vuejs/core/commit/d7bcd858883d90a1593b45cdc43f9fa55bc790bc)), closes [#14412](https://github.com/vuejs/core/issues/14412)\n* **transition-group:** correct move translation under scale via element rect ([#14360](https://github.com/vuejs/core/issues/14360)) ([0243a79](https://github.com/vuejs/core/commit/0243a792ac1cf8b0308f552927ed2ecd8627b839)), closes [#14356](https://github.com/vuejs/core/issues/14356)\n* **useTemplateRef:** don't update setup ref for useTemplateRef key ([#12756](https://github.com/vuejs/core/issues/12756)) ([fc40ca0](https://github.com/vuejs/core/commit/fc40ca0216a7028f6ec0195344c976423e239ef3)), closes [#12749](https://github.com/vuejs/core/issues/12749)\n\n\n\n## [3.5.27](https://github.com/vuejs/core/compare/v3.5.26...v3.5.27) (2026-01-19)\n\n\n### Bug Fixes\n\n* **compile-sfc:** correctly handle variable shadowing in for loop for `defineProps` destructuring. ([#14296](https://github.com/vuejs/core/issues/14296)) ([6a1bb50](https://github.com/vuejs/core/commit/6a1bb50594db03904f401fc33ea85afa8fa71cf7)), closes [#14294](https://github.com/vuejs/core/issues/14294)\n* **compiler-sfc:** handle indexed access types in declare global blocks ([#14260](https://github.com/vuejs/core/issues/14260)) ([e4091fe](https://github.com/vuejs/core/commit/e4091fe1f917346a66ffa8d013b3cf4b331b6682)), closes [#14236](https://github.com/vuejs/core/issues/14236)\n* **compiler-sfc:** use correct scope when resolving indexed access types from external files ([#14297](https://github.com/vuejs/core/issues/14297)) ([f0f0a21](https://github.com/vuejs/core/commit/f0f0a21dfaf0f41bb2198106db0f4ff32b97dcd3)), closes [#14292](https://github.com/vuejs/core/issues/14292)\n* **reactivity:** collection iteration should inherit iterator instance methods ([#12644](https://github.com/vuejs/core/issues/12644)) ([3c8b2fc](https://github.com/vuejs/core/commit/3c8b2fc836b2f60c90c2459933e66b2fd9fb8c08)), closes [#12615](https://github.com/vuejs/core/issues/12615)\n* **runtime-core:** skip patching reserved props for custom elements ([#14275](https://github.com/vuejs/core/issues/14275)) ([19cc7e2](https://github.com/vuejs/core/commit/19cc7e2cd053629f3233cd55dff98951e69f5391)), closes [#14274](https://github.com/vuejs/core/issues/14274)\n* **server-renderer:** use ssrRenderClass helper for className attribute ([#14327](https://github.com/vuejs/core/issues/14327)) ([a4708f3](https://github.com/vuejs/core/commit/a4708f324f62ac2122f87c4ee039deb2745f0905))\n* **ssr:** handle v-bind modifiers during render attrs ([#14263](https://github.com/vuejs/core/issues/14263)) ([c2f5964](https://github.com/vuejs/core/commit/c2f5964c47890321cab40fcf0ebc528e6d00337f)), closes [#14262](https://github.com/vuejs/core/issues/14262)\n\n\n\n## [3.5.26](https://github.com/vuejs/core/compare/v3.5.25...v3.5.26) (2025-12-18)\n\n\n### Bug Fixes\n\n* **compat:** fix compat handler of draggable ([#12445](https://github.com/vuejs/core/issues/12445)) ([ed85953](https://github.com/vuejs/core/commit/ed85953e28741ae1913cfc92b7b66e1a8da47f8c)), closes [#12444](https://github.com/vuejs/core/issues/12444)\n* **compat:** handle v-model deprecation warning with missing appContext ([#14203](https://github.com/vuejs/core/issues/14203)) ([945a543](https://github.com/vuejs/core/commit/945a543152e8d80903d4f7a18a84ebe8d36e56f8)), closes [#14202](https://github.com/vuejs/core/issues/14202)\n* **compiler-sfc:** demote const reactive bindings used in v-model ([#14214](https://github.com/vuejs/core/issues/14214)) ([e24ff7d](https://github.com/vuejs/core/commit/e24ff7d302a887ea532571c231a385362fa17279)), closes [#11265](https://github.com/vuejs/core/issues/11265) [#11275](https://github.com/vuejs/core/issues/11275)\n* **compiler-ssr:** handle ssr attr fallthrough when preserve whitespace ([#12304](https://github.com/vuejs/core/issues/12304)) ([4783118](https://github.com/vuejs/core/commit/47831189196b62b12dd17f6e909efc51d9d22fd2)), closes [#8072](https://github.com/vuejs/core/issues/8072)\n* **hmr:** handle cached text node update ([#14134](https://github.com/vuejs/core/issues/14134)) ([69ce3c7](https://github.com/vuejs/core/commit/69ce3c7d755db868cfa66d67ab5b3f383a44e053)), closes [#14127](https://github.com/vuejs/core/issues/14127)\n* **keep-alive:** use resolved component name for async components in cache pruning ([#14212](https://github.com/vuejs/core/issues/14212)) ([dfe667c](https://github.com/vuejs/core/commit/dfe667c8567d48167c250062483d2d2cfc7bdc03)), closes [#14210](https://github.com/vuejs/core/issues/14210)\n* **runtime-core:** ensure correct anchor el for deeper unresolved async components ([#14182](https://github.com/vuejs/core/issues/14182)) ([f5b3bf2](https://github.com/vuejs/core/commit/f5b3bf264d2e12725381bed1c492069437069b03)), closes [#14173](https://github.com/vuejs/core/issues/14173)\n* **runtime-core:** handle patch stable fragment edge case ([#12411](https://github.com/vuejs/core/issues/12411)) ([94aeb64](https://github.com/vuejs/core/commit/94aeb64ccdf20d541059b533c9780977c14db9cb)), closes [#12410](https://github.com/vuejs/core/issues/12410)\n* **runtime-core:** pass component instance to flushPreFlushCbs on unmount ([#14221](https://github.com/vuejs/core/issues/14221)) ([e857e12](https://github.com/vuejs/core/commit/e857e12c0aff03c0148e3e52d92935918872dc33)), closes [#14215](https://github.com/vuejs/core/issues/14215)\n\n\n### Performance Improvements\n\n* **compiler-core:** use binary-search to get line and column ([#14222](https://github.com/vuejs/core/issues/14222)) ([1904053](https://github.com/vuejs/core/commit/1904053f1f7986c2d6dbe858ee1b594b4b229c17))\n\n\n\n## [3.5.25](https://github.com/vuejs/core/compare/v3.5.24...v3.5.25) (2025-11-24)\n\n\n### Bug Fixes\n\n* **compiler:** share logic for comments and whitespace ([#13550](https://github.com/vuejs/core/issues/13550)) ([2214f7a](https://github.com/vuejs/core/commit/2214f7ab2940bcb751cd20130c020d895db6c042))\n* **provide:** warn when using `provide` after mounting ([#13954](https://github.com/vuejs/core/issues/13954)) ([247b2c2](https://github.com/vuejs/core/commit/247b2c2067afc4dee52f9f7bc194f3aab347ac55)), closes [#13921](https://github.com/vuejs/core/issues/13921) [#13924](https://github.com/vuejs/core/issues/13924)\n* **reactivity:** correctly wrap iterated array items to preserve their readonly status ([#14120](https://github.com/vuejs/core/issues/14120)) ([301020b](https://github.com/vuejs/core/commit/301020b481e85d03b0c96000f3221372063c41c6))\n* **reactivity:** toRef edge cases for ref unwrapping ([#12420](https://github.com/vuejs/core/issues/12420)) ([0d2357e](https://github.com/vuejs/core/commit/0d2357e6974678d5484751c869f429dc6ea85582))\n* **runtime-core:** keep options API typing intact when expose is used ([#14118](https://github.com/vuejs/core/issues/14118)) ([8f82f23](https://github.com/vuejs/core/commit/8f82f238463160284e504d1751d61b72dabb395e)), closes [#14117](https://github.com/vuejs/core/issues/14117) [vuejs/language-tools#5069](https://github.com/vuejs/language-tools/issues/5069)\n* **suspense:** defer clearing fallback vnode el in case it has dirs ([#14080](https://github.com/vuejs/core/issues/14080)) ([c0f63dd](https://github.com/vuejs/core/commit/c0f63ddbfa8fa221d66b683b5c26e471851c2b50)), closes [#14078](https://github.com/vuejs/core/issues/14078)\n\n\n\n## [3.5.24](https://github.com/vuejs/core/compare/v3.5.23...v3.5.24) (2025-11-07)\n\n\n### Reverts\n\n* Revert \"fix(compiler-core): correctly handle ts type assertions in expression…\" (#14062) ([11ec51a](https://github.com/vuejs/core/commit/11ec51aa5a7914745fee10ed2b9f9464fab4d02c)), closes [#14062](https://github.com/vuejs/core/issues/14062) [#14060](https://github.com/vuejs/core/issues/14060)\n\n\n\n## [3.5.23](https://github.com/vuejs/core/compare/v3.5.22...v3.5.23) (2025-11-06)\n\n\n### Bug Fixes\n\n* **compiler-core:** correctly handle ts type assertions in expressions ([#13397](https://github.com/vuejs/core/issues/13397)) ([e6544ac](https://github.com/vuejs/core/commit/e6544ac292b5b473274f87cdb83ebeac3e7e61a4)), closes [#13395](https://github.com/vuejs/core/issues/13395)\n* **compiler-core:** fix v-bind shorthand handling for in-DOM templates ([#13933](https://github.com/vuejs/core/issues/13933)) ([b3cca26](https://github.com/vuejs/core/commit/b3cca2611c656b85f0c4e737b9ec248d2627dded)), closes [#13930](https://github.com/vuejs/core/issues/13930)\n* **compiler-sfc:** resolve numeric literals and template literals without expressions as static property key ([#13998](https://github.com/vuejs/core/issues/13998)) ([75d44c7](https://github.com/vuejs/core/commit/75d44c718981f91843e197265cc68e82fe2532dd))\n* **compiler-ssr:** textarea with v-text directive SSR ([#13975](https://github.com/vuejs/core/issues/13975)) ([006a0c1](https://github.com/vuejs/core/commit/006a0c1011a224bcbf21195c6df76812c3a7e757))\n* **compiler:** using guard instead of non-nullish assertion ([#13982](https://github.com/vuejs/core/issues/13982)) ([dcc6f36](https://github.com/vuejs/core/commit/dcc6f362577ed86ccad31c2623c6cf75137dd27a))\n* **custom-element:** batch custom element prop patching ([#13478](https://github.com/vuejs/core/issues/13478)) ([c13e674](https://github.com/vuejs/core/commit/c13e674fb9f92ab9339d28a862d18de460faf56e)), closes [#12619](https://github.com/vuejs/core/issues/12619)\n* **custom-element:** optimize slot retrieval to avoid duplicates ([#13961](https://github.com/vuejs/core/issues/13961)) ([84ca349](https://github.com/vuejs/core/commit/84ca349fef73f6f55fc98299fcfa5c1eeef721db)), closes [#13955](https://github.com/vuejs/core/issues/13955)\n* **hydration:** avoid mismatch during hydrate text with newlines in interpolation ([#9232](https://github.com/vuejs/core/issues/9232)) ([6cbdf78](https://github.com/vuejs/core/commit/6cbdf7823b0c961190bee5b7c117b7f2bbeb832f)), closes [#9229](https://github.com/vuejs/core/issues/9229)\n* **runtime-core:** pass props and children to loadingComponent ([#13997](https://github.com/vuejs/core/issues/13997)) ([40c4b2a](https://github.com/vuejs/core/commit/40c4b2a876ce606973521dfc3024e26bfc10953a))\n* **runtime-dom:** ensure iframe sandbox is handled as an attribute to prevent unintended behavior ([#13950](https://github.com/vuejs/core/issues/13950)) ([5689884](https://github.com/vuejs/core/commit/5689884c8e32cda6a802ac36b4d23218f67b38ed)), closes [#13946](https://github.com/vuejs/core/issues/13946)\n* **suspense:** clear placeholder and fallback el after resolve to enable GC ([#13928](https://github.com/vuejs/core/issues/13928)) ([f411c66](https://github.com/vuejs/core/commit/f411c6604c12c531883aa0d30b81a7f69092f8a6))\n* **transition-group:** use offsetLeft and offsetTop instead of getBoundingClientRect  to avoid transform scale affect animation ([#6108](https://github.com/vuejs/core/issues/6108)) ([dc4dd59](https://github.com/vuejs/core/commit/dc4dd594fbecce6ed7f44ffa69dc8b5d022287b6)), closes [#6105](https://github.com/vuejs/core/issues/6105)\n* **v-model:** handle number modifier on change ([#13959](https://github.com/vuejs/core/issues/13959)) ([8fbe48f](https://github.com/vuejs/core/commit/8fbe48fe396d830999afd07f9413d899157d5f5e)), closes [#13958](https://github.com/vuejs/core/issues/13958)\n\n\n\n## [3.5.22](https://github.com/vuejs/core/compare/v3.5.21...v3.5.22) (2025-09-25)\n\n\n### Bug Fixes\n\n* **compiler-core:** identifiers in switch-case should not be inferred as references ([#13923](https://github.com/vuejs/core/issues/13923)) ([5953c9f](https://github.com/vuejs/core/commit/5953c9ff90090e128372f645d377bd99137a5fb4))\n* **compiler-dom:** nodes with v-once shouldn't be stringified ([#13878](https://github.com/vuejs/core/issues/13878)) ([95c1975](https://github.com/vuejs/core/commit/95c197560409f5d39a0d376c0a43d89a47a604e8))\n* **compiler-sfc:** add support for `@vue-ignore` in runtime type resolution ([#13906](https://github.com/vuejs/core/issues/13906)) ([ba7f7f9](https://github.com/vuejs/core/commit/ba7f7f90f689f6e7e0417a192d081db542de28ec))\n* **compiler-sfc:** enhance inferRuntimeType to support TSMappedType with indexed access ([#13848](https://github.com/vuejs/core/issues/13848)) ([e388f1a](https://github.com/vuejs/core/commit/e388f1a09fde78cf006450f060813d972ac8c23d)), closes [#13847](https://github.com/vuejs/core/issues/13847)\n* **compiler-sfc:** ensure css custom properties do not start with a digit ([#13870](https://github.com/vuejs/core/issues/13870)) ([9c27951](https://github.com/vuejs/core/commit/9c279517b9bc1f4c250c555ec9b9eb6104756d56))\n* **compiler-sfc:** ensure props bindings register before compiling template ([#13922](https://github.com/vuejs/core/issues/13922)) ([abd5638](https://github.com/vuejs/core/commit/abd563822abafe63047f7b599bff266380ee2b64)), closes [#13920](https://github.com/vuejs/core/issues/13920)\n* **compiler-ssr:** ensure v-show has a higher priority in SSR ([#12171](https://github.com/vuejs/core/issues/12171)) ([836b829](https://github.com/vuejs/core/commit/836b82976ffb7aa0ea9cbe417bef07deae3ca47c)), closes [#12162](https://github.com/vuejs/core/issues/12162)\n* **custom-element:** properly mount multiple Teleports in custom element component w/ shadowRoot false ([#13900](https://github.com/vuejs/core/issues/13900)) ([5e1e791](https://github.com/vuejs/core/commit/5e1e791880238380a1038ae2c505e206ceb34d77)), closes [#13899](https://github.com/vuejs/core/issues/13899)\n* **custom-element:** set prop runs pending mutations before disconnect ([#13897](https://github.com/vuejs/core/issues/13897)) ([c4a88cd](https://github.com/vuejs/core/commit/c4a88cdd0dfed3ef46a8aa9be448c01781fdc4f0)), closes [#13315](https://github.com/vuejs/core/issues/13315)\n* **custom-element:** use `PatchFlags.BAIL` for slot when props are present ([#13907](https://github.com/vuejs/core/issues/13907)) ([5358bca](https://github.com/vuejs/core/commit/5358bca4a80cf52d19ed91967eeaa025a786083d)), closes [#13904](https://github.com/vuejs/core/issues/13904)\n* **reactivity:** respect readonly during ref unwrapping ([#13905](https://github.com/vuejs/core/issues/13905)) ([aba7fed](https://github.com/vuejs/core/commit/aba7feda1703e69e5a7c37f784718de0371adadc)), closes [#13903](https://github.com/vuejs/core/issues/13903)\n* **reactivity:** update iterator to check for completion instead of value presence ([#13761](https://github.com/vuejs/core/issues/13761)) ([2078f8b](https://github.com/vuejs/core/commit/2078f8b7565cf637f47fcd5b0abdfb2b264225bb))\n* **runtime-core:** simplify block-tracking disabling in `h` helper ([#13841](https://github.com/vuejs/core/issues/13841)) ([75220c7](https://github.com/vuejs/core/commit/75220c7995a13a483ae9599a739075be1c8e17f8))\n* **transition-group:** run `forceReflow` on the correct document (fix [#13849](https://github.com/vuejs/core/issues/13849)) ([#13853](https://github.com/vuejs/core/issues/13853)) ([1be5ddf](https://github.com/vuejs/core/commit/1be5ddfe878c8bfddaa2c50e82105b247f50b9ba))\n* **types:** more precise types for Events and added missing definitions ([#9675](https://github.com/vuejs/core/issues/9675)) ([8bb8fb2](https://github.com/vuejs/core/commit/8bb8fb236257c03bfa0bccadcfffe3eb4592f71b))\n* **types:** set dom stub type to `never` instead of `{}` ([#13915](https://github.com/vuejs/core/issues/13915)) ([8620a61](https://github.com/vuejs/core/commit/8620a616eb02a64fe32dd52d9be68e360687ef9d)), closes [#11564](https://github.com/vuejs/core/issues/11564)\n* **types:** widen directive arg type from string to any ([#13758](https://github.com/vuejs/core/issues/13758)) ([4b71706](https://github.com/vuejs/core/commit/4b7170625d0bc93b26a3343aeda98850c1138f82)), closes [#13757](https://github.com/vuejs/core/issues/13757)\n\n\n### Features\n\n* **custom-element:** allow specifying additional options for `shadowRoot` in custom elements ([#12965](https://github.com/vuejs/core/issues/12965)) ([47e628d](https://github.com/vuejs/core/commit/47e628df1ce1914c5677010ad5bddd18d037cb3c)), closes [#12964](https://github.com/vuejs/core/issues/12964)\n\n\n### Reverts\n\n* Revert \"fix(hmr): prevent __VUE_HMR_RUNTIME__ from being overwritten by vue runtime in 3rd-party libraries\" (#13925) ([6b68f72](https://github.com/vuejs/core/commit/6b68f72673dac5db349f26eeefb2f2e0e342586b)), closes [#13925](https://github.com/vuejs/core/issues/13925)\n\n\n\n## [3.5.21](https://github.com/vuejs/core/compare/v3.5.20...v3.5.21) (2025-09-02)\n\n\n### Bug Fixes\n\n* **compiler-core:** force dynamic slots when slot referencing scope vars ([#9427](https://github.com/vuejs/core/issues/9427)) ([99d54b2](https://github.com/vuejs/core/commit/99d54b28b46dbea006205dff71c383a31dd1b87a)), closes [#9380](https://github.com/vuejs/core/issues/9380)\n* **compiler-sfc:** check lang before attempt to compile script ([#13508](https://github.com/vuejs/core/issues/13508)) ([55922ff](https://github.com/vuejs/core/commit/55922ff3168a1397ad72f18946eb1c4051cdab3b)), closes [#8368](https://github.com/vuejs/core/issues/8368)\n* **compiler-sfc:** support `${configDir}` in paths for TypeScript 5.5+ ([#13491](https://github.com/vuejs/core/issues/13491)) ([8696e34](https://github.com/vuejs/core/commit/8696e346b4780d88247464490f1a992cc0c3658c)), closes [#13484](https://github.com/vuejs/core/issues/13484)\n* **compiler-sfc:** support global augments with named exports ([#13789](https://github.com/vuejs/core/issues/13789)) ([35da3c6](https://github.com/vuejs/core/commit/35da3c6dcb30030ef60fa22e30aa83a56e396c60))\n* **custom-element:** prevent defineCustomElement from mutating the options object ([#13791](https://github.com/vuejs/core/issues/13791)) ([e322436](https://github.com/vuejs/core/commit/e322436887549c129e61eb58a0084167103451bb))\n* **hmr:** prevent `__VUE_HMR_RUNTIME__` from being overwritten by vue runtime in 3rd-party libraries ([#13817](https://github.com/vuejs/core/issues/13817)) ([1392734](https://github.com/vuejs/core/commit/1392734ae5d5a3b2be124753e198eafa324f6815)), closes [vitejs/vite-plugin-vue#644](https://github.com/vitejs/vite-plugin-vue/issues/644)\n* **hmr:** prevent update unmounting component during HMR reload ([#13815](https://github.com/vuejs/core/issues/13815)) ([ef20b86](https://github.com/vuejs/core/commit/ef20b86b36a127e317f8981df970dc8efd277053)), closes [vitejs/vite-plugin-vue#599](https://github.com/vitejs/vite-plugin-vue/issues/599)\n* **runtime-core:** disable tracking block in h function ([#8213](https://github.com/vuejs/core/issues/8213)) ([8f6b505](https://github.com/vuejs/core/commit/8f6b5050518441a5047d128138da44f798836002)), closes [#6913](https://github.com/vuejs/core/issues/6913)\n* **runtime-core:** use separate emits caches for components and mixins ([#11661](https://github.com/vuejs/core/issues/11661)) ([15fc75f](https://github.com/vuejs/core/commit/15fc75f4031dea805c3bbb67a75e48a9dc307c11))\n* **Suspence:** handle Suspense + KeepAlive HMR updating edge case ([#13076](https://github.com/vuejs/core/issues/13076)) ([5d75a17](https://github.com/vuejs/core/commit/5d75a170c8d23acd11ef2513173d4cbc4d0b54de)), closes [#13075](https://github.com/vuejs/core/issues/13075)\n* **Teleport:** hydrate disabled Teleport with undefined target ([#11235](https://github.com/vuejs/core/issues/11235)) ([00978f7](https://github.com/vuejs/core/commit/00978f7d14e85b49d9d334ea92fa8c03733ce64c)), closes [#11230](https://github.com/vuejs/core/issues/11230)\n* **templateRef:** prevent unnecessary set ref on dynamic ref change or component unmount ([#12642](https://github.com/vuejs/core/issues/12642)) ([93ba107](https://github.com/vuejs/core/commit/93ba10767230872fcdca974a1e19e8bd69b7eb6a)), closes [#12639](https://github.com/vuejs/core/issues/12639)\n* **watch:** use maximum depth for duplicates ([#13434](https://github.com/vuejs/core/issues/13434)) ([f2699a5](https://github.com/vuejs/core/commit/f2699a5cb376ffa452a54feb171c14411c67287c))\n\n\n### Performance Improvements\n\n* improve regexp performance with non-capturing groups ([#13567](https://github.com/vuejs/core/issues/13567)) ([1e8b65a](https://github.com/vuejs/core/commit/1e8b65aa4934c94ef6142b4f49cdfb13ba5e6ce5))\n\n\n\n## [3.5.20](https://github.com/vuejs/core/compare/v3.5.19...v3.5.20) (2025-08-25)\n\n\n### Bug Fixes\n\n* **runtime-dom:** add name to vShow for prop mismatch check ([#13806](https://github.com/vuejs/core/issues/13806)) ([1031e8d](https://github.com/vuejs/core/commit/1031e8de08b735059217b1ad0057f62565c99c4f)), closes [#13805](https://github.com/vuejs/core/issues/13805) re-fix [#13744](https://github.com/vuejs/core/issues/13744) revert [#13777](https://github.com/vuejs/core/issues/13777) \n\n\n\n## [3.5.19](https://github.com/vuejs/core/compare/v3.5.18...v3.5.19) (2025-08-21)\n\n\n### Bug Fixes\n\n* **compiler-core:** adjacent v-else should cause a compiler error ([#13699](https://github.com/vuejs/core/issues/13699)) ([911e670](https://github.com/vuejs/core/commit/911e67045e2a63e0ecbd198ed4f567530f6d1c17)), closes [#13698](https://github.com/vuejs/core/issues/13698)\n* **compiler-core:** prevent cached array children from retaining detached dom nodes ([#13691](https://github.com/vuejs/core/issues/13691)) ([7f60ef8](https://github.com/vuejs/core/commit/7f60ef83e735dbd29d323347acecf69f22b06d53)), closes [element-plus/element-plus#21408](https://github.com/element-plus/element-plus/issues/21408) [#13211](https://github.com/vuejs/core/issues/13211)\n* **compiler-sfc:** improve type inference for generic type aliases types ([#12876](https://github.com/vuejs/core/issues/12876)) ([d9dd628](https://github.com/vuejs/core/commit/d9dd628800ae32e673bdfabfe79f1988037991d0)), closes [#12872](https://github.com/vuejs/core/issues/12872)\n* **compiler-sfc:** throw mismatched script langs error before invoking babel ([#13194](https://github.com/vuejs/core/issues/13194)) ([0562548](https://github.com/vuejs/core/commit/0562548ab3a040073386021222225e0e9d43c632)), closes [#13193](https://github.com/vuejs/core/issues/13193)\n* **compiler-ssr:** disable v-memo transform in ssr vdom fallback branch ([#13725](https://github.com/vuejs/core/issues/13725)) ([0a202d8](https://github.com/vuejs/core/commit/0a202d890ff2a564b1fab51e4ac621708640818e)), closes [#13724](https://github.com/vuejs/core/issues/13724)\n* **devtools:** clear performance measures ([#13701](https://github.com/vuejs/core/issues/13701)) ([c875019](https://github.com/vuejs/core/commit/c875019d49b4c36a88d929ccadc31ad414747c7b)), closes [#13700](https://github.com/vuejs/core/issues/13700)\n* **hmr:** prevent updating unmounting component during HMR rerender ([#13775](https://github.com/vuejs/core/issues/13775)) ([6e5143d](https://github.com/vuejs/core/commit/6e5143d9635dac3f20fb394a827109df30e232ae)), closes [#13771](https://github.com/vuejs/core/issues/13771) [#13772](https://github.com/vuejs/core/issues/13772)\n* **hydration:** also set vShow name if `__FEATURE_PROD_HYDRATION_MISMATCH_DETAILS__` flag is enabled ([#13777](https://github.com/vuejs/core/issues/13777)) ([439e1a5](https://github.com/vuejs/core/commit/439e1a543e62de4dbf7658d78d05c358c9677c86)), closes [#13744](https://github.com/vuejs/core/issues/13744)\n* **reactivity:** warn on nested readonly ref update during unwrapping ([#12141](https://github.com/vuejs/core/issues/12141)) ([1498821](https://github.com/vuejs/core/commit/1498821ed9eeb22a0767e53ddc1f6a2840598a29))\n* **runtime-core:** avoid setting direct ref of useTemplateRef in dev ([#13449](https://github.com/vuejs/core/issues/13449)) ([4a2953f](https://github.com/vuejs/core/commit/4a2953f57b90dfc24e34ff1a87cc1ebb0b97636d))\n* **runtime-core:** improve consistency of `PublicInstanceProxyHandlers.has` ([#13507](https://github.com/vuejs/core/issues/13507)) ([d7283f3](https://github.com/vuejs/core/commit/d7283f3b7f0631c8b8a4a31a05983dac9f078c4f))\n* **suspense:** don't immediately resolve suspense on last dep unmount ([#13456](https://github.com/vuejs/core/issues/13456)) ([a871315](https://github.com/vuejs/core/commit/a8713159ee24602c7c2b70c5fd52d2e5cd37dca5)), closes [#13453](https://github.com/vuejs/core/issues/13453)\n* **transition:** handle KeepAlive + transition leaving edge case ([#13152](https://github.com/vuejs/core/issues/13152)) ([3190b17](https://github.com/vuejs/core/commit/3190b179b0545a3dc4549737793eec630cf9f0d1)), closes [#13153](https://github.com/vuejs/core/issues/13153)\n\n\n\n## [3.5.18](https://github.com/vuejs/core/compare/v3.5.17...v3.5.18) (2025-07-23)\n\n\n### Bug Fixes\n\n* **compiler-core:** avoid cached text vnodes retaining detached DOM nodes ([#13662](https://github.com/vuejs/core/issues/13662)) ([00695a5](https://github.com/vuejs/core/commit/00695a5b41b2d032deaeada83831ff83aa6bfd4e)), closes [#13661](https://github.com/vuejs/core/issues/13661)\n* **compiler-core:** avoid self updates of `v-pre` ([#12556](https://github.com/vuejs/core/issues/12556)) ([21b685a](https://github.com/vuejs/core/commit/21b685ad9d9d0e6060fc7d07b719bf35f2d9ae1f))\n* **compiler-core:** identifiers in function parameters should not be inferred as references ([#13548](https://github.com/vuejs/core/issues/13548)) ([9b02923](https://github.com/vuejs/core/commit/9b029239edf88558465b941e1e4c085f92b1ebff))\n* **compiler-core:** recognize empty string as non-identifier ([#12553](https://github.com/vuejs/core/issues/12553)) ([ce93339](https://github.com/vuejs/core/commit/ce933390ad1c72bed258f7ad959a78f0e8acdf57))\n* **compiler-core:** transform empty `v-bind` dynamic argument content correctly ([#12554](https://github.com/vuejs/core/issues/12554)) ([d3af67e](https://github.com/vuejs/core/commit/d3af67e878790892f9d34cfea15d13625aabe733))\n* **compiler-sfc:** transform empty srcset w/ includeAbsolute: true ([#13639](https://github.com/vuejs/core/issues/13639)) ([d8e40ef](https://github.com/vuejs/core/commit/d8e40ef7e1c20ee86b294e7cf78e2de60d12830e)), closes [vitejs/vite-plugin-vue#631](https://github.com/vitejs/vite-plugin-vue/issues/631)\n* **css-vars:** nullish v-bind in style should not lead to unexpected inheritance ([#12461](https://github.com/vuejs/core/issues/12461)) ([c85f1b5](https://github.com/vuejs/core/commit/c85f1b5a132eb8ec25f71b250e25e65a5c20964f)), closes [#12434](https://github.com/vuejs/core/issues/12434) [#12439](https://github.com/vuejs/core/issues/12439) [#7474](https://github.com/vuejs/core/issues/7474) [#7475](https://github.com/vuejs/core/issues/7475)\n* **custom-element:** ensure exposed methods are accessible from custom elements by making them enumerable ([#13634](https://github.com/vuejs/core/issues/13634)) ([90573b0](https://github.com/vuejs/core/commit/90573b06bf6fb6c14c6bbff6c4e34e0ab108953a)), closes [#13632](https://github.com/vuejs/core/issues/13632)\n* **hydration:** prevent lazy hydration for updated components ([#13511](https://github.com/vuejs/core/issues/13511)) ([a9269c6](https://github.com/vuejs/core/commit/a9269c642bf944560bc29adb5dae471c11cd9ee8)), closes [#13510](https://github.com/vuejs/core/issues/13510)\n* **runtime-core:** ensure correct anchor el for unresolved async components ([#13560](https://github.com/vuejs/core/issues/13560)) ([7f29943](https://github.com/vuejs/core/commit/7f2994393dcdb82cacbf62e02b5ba5565f32588b)), closes [#13559](https://github.com/vuejs/core/issues/13559)\n* **slots:** refine internal key checking to support slot names starting with an underscore ([#13612](https://github.com/vuejs/core/issues/13612)) ([c5f7db1](https://github.com/vuejs/core/commit/c5f7db11542bb2246363aef78c88a8e6cef0ee93)), closes [#13611](https://github.com/vuejs/core/issues/13611)\n* **ssr:** ensure empty slots render as a comment node in Transition ([#13396](https://github.com/vuejs/core/issues/13396)) ([8cfc10a](https://github.com/vuejs/core/commit/8cfc10a80b9cbf5d801ab149e49b8506d192e7e1)), closes [#13394](https://github.com/vuejs/core/issues/13394)\n\n\n\n## [3.5.17](https://github.com/vuejs/core/compare/v3.5.16...v3.5.17) (2025-06-18)\n\n\n### Bug Fixes\n\n* **compat:** allow v-model built in modifiers on component ([#12654](https://github.com/vuejs/core/issues/12654)) ([cb14b86](https://github.com/vuejs/core/commit/cb14b860f150c4a83bcd52cd26096b7a5aa3a2bf)), closes [#12652](https://github.com/vuejs/core/issues/12652)\n* **compile-sfc:** handle mapped types work with omit and pick ([#12648](https://github.com/vuejs/core/issues/12648)) ([4eb46e4](https://github.com/vuejs/core/commit/4eb46e443f1878199755cb73d481d318a9714392)), closes [#12647](https://github.com/vuejs/core/issues/12647)\n* **compiler-core:** do not increase newlines in `InEntity` state ([#13362](https://github.com/vuejs/core/issues/13362)) ([f05a8d6](https://github.com/vuejs/core/commit/f05a8d613bd873b811cfdb9979ccac8382dba322))\n* **compiler-core:** ignore whitespace when matching adjacent v-if ([#12321](https://github.com/vuejs/core/issues/12321)) ([10ebcef](https://github.com/vuejs/core/commit/10ebcef8c870dbc042b0ea49b1424b2e8f692145)), closes [#9173](https://github.com/vuejs/core/issues/9173)\n* **compiler-core:** prevent comments from blocking static node hoisting  ([#13345](https://github.com/vuejs/core/issues/13345)) ([55dad62](https://github.com/vuejs/core/commit/55dad625acd9e9ddd5a933d5e323ecfdec1a612f)), closes [#13344](https://github.com/vuejs/core/issues/13344)\n* **compiler-sfc:** improved type resolution for function type aliases ([#13452](https://github.com/vuejs/core/issues/13452)) ([f3479aa](https://github.com/vuejs/core/commit/f3479aac9625f4459e650d1c0a70e73863147903)), closes [#13444](https://github.com/vuejs/core/issues/13444)\n* **custom-element:** ensure configureApp is applied to async component ([#12607](https://github.com/vuejs/core/issues/12607)) ([5ba1afb](https://github.com/vuejs/core/commit/5ba1afba09c3ea56c1c17484f5d8aeae210ce52a)), closes [#12448](https://github.com/vuejs/core/issues/12448)\n* **custom-element:** prevent injecting child styles if shadowRoot is false ([#12769](https://github.com/vuejs/core/issues/12769)) ([73055d8](https://github.com/vuejs/core/commit/73055d8d9578d485e3fe846726b50666e1aa56f5)), closes [#12630](https://github.com/vuejs/core/issues/12630)\n* **reactivity:** add `__v_skip` flag to `Dep` to prevent reactive conversion ([#12804](https://github.com/vuejs/core/issues/12804)) ([e8d8f5f](https://github.com/vuejs/core/commit/e8d8f5f604e821acc46b4200d5b06979c05af1c2)), closes [#12803](https://github.com/vuejs/core/issues/12803)\n* **runtime-core:** unset old ref during patching when new ref is absent ([#12900](https://github.com/vuejs/core/issues/12900)) ([47ddf98](https://github.com/vuejs/core/commit/47ddf986021dff8de68b0da72787e53a6c19de4c)), closes [#12898](https://github.com/vuejs/core/issues/12898)\n* **slots:** make cache indexes marker non-enumerable ([#13469](https://github.com/vuejs/core/issues/13469)) ([919c447](https://github.com/vuejs/core/commit/919c44744bba1f0c661c87d2059c3b429611aa7e)), closes [#13468](https://github.com/vuejs/core/issues/13468)\n* **ssr:** handle initial selected state for select with v-model + v-for/v-if option ([#13487](https://github.com/vuejs/core/issues/13487)) ([1552095](https://github.com/vuejs/core/commit/15520954f9f1c7f834175938a50dba5d4be0e6c4)), closes [#13486](https://github.com/vuejs/core/issues/13486)\n* **types:** typo of `vOnce` and `vSlot` ([#13343](https://github.com/vuejs/core/issues/13343)) ([762fae4](https://github.com/vuejs/core/commit/762fae4b57ad60602e5c84465a3bff562785b314))\n\n\n\n## [3.5.16](https://github.com/vuejs/core/compare/v3.5.15...v3.5.16) (2025-05-29)\n\n\n### Reverts\n\n* Revert \"fix(compiler-sfc): add scoping tag to trailing universal selector\" (#13406) ([19f23b1](https://github.com/vuejs/core/commit/19f23b180bb679e38db95d6a10a420abeedc8e1c)), closes [#13406](https://github.com/vuejs/core/issues/13406)\n* Revert \"fix(compiler-sfc): add error handling for defineModel() without variable\" (#13390) ([42f879f](https://github.com/vuejs/core/commit/42f879fcab48e0e1011967a771b4ad9e8838d760)), closes [#13390](https://github.com/vuejs/core/issues/13390)\n\n\n\n## [3.5.15](https://github.com/vuejs/core/compare/v3.5.14...v3.5.15) (2025-05-26)\n\n\n### Bug Fixes\n\n* **compat:** ensure false value on input retains value attribute ([#13216](https://github.com/vuejs/core/issues/13216)) ([1a66474](https://github.com/vuejs/core/commit/1a664749d4d65a345589a6d78106ede7574cb2e1)), closes [#13205](https://github.com/vuejs/core/issues/13205)\n* **compat:** should not warn COMPILER_V_BIND_OBJECT_ORDER when using v-bind together with v-for ([#12993](https://github.com/vuejs/core/issues/12993)) ([93949e6](https://github.com/vuejs/core/commit/93949e6587ee019bccd5b8b9d76f0e1ed6ea16fc)), closes [#12992](https://github.com/vuejs/core/issues/12992)\n* **compile-sfc:** handle inline template source map in prod build ([#12701](https://github.com/vuejs/core/issues/12701)) ([89edc6c](https://github.com/vuejs/core/commit/89edc6cdcbd34ea6394927ecbfaa61dc4f871de7)), closes [#12682](https://github.com/vuejs/core/issues/12682) [vitejs/vite-plugin-vue#500](https://github.com/vitejs/vite-plugin-vue/issues/500)\n* **compiler-core:** ensure mapping is added only if node source is available ([#13285](https://github.com/vuejs/core/issues/13285)) ([d37a2ac](https://github.com/vuejs/core/commit/d37a2ac59d904ac0e3257ba552b6c04920a363f0)), closes [#13261](https://github.com/vuejs/core/issues/13261) [vitejs/vite-plugin-vue#368](https://github.com/vitejs/vite-plugin-vue/issues/368)\n* **compiler-dom:** improve HTML nesting validation to allow any child element within template tag ([#13320](https://github.com/vuejs/core/issues/13320)) ([163b365](https://github.com/vuejs/core/commit/163b3651d174321911648a164052effa9249a2aa)), closes [#13318](https://github.com/vuejs/core/issues/13318)\n* **compiler-sfc:** add error handling for defineModel() without variable assignment ([#13352](https://github.com/vuejs/core/issues/13352)) ([00734af](https://github.com/vuejs/core/commit/00734afef5f7bddbdaee52aa5359a6ef989f32d3)), closes [#13280](https://github.com/vuejs/core/issues/13280)\n* **compiler-sfc:** add scoping tag to trailing universal selector ([#12918](https://github.com/vuejs/core/issues/12918)) ([949df80](https://github.com/vuejs/core/commit/949df808809fd7cccf7718797beab0654aa68302)), closes [#12906](https://github.com/vuejs/core/issues/12906)\n* **compiler-sfc:** improve type inference for TSTypeAliasDeclaration with better runtime type detection ([#13245](https://github.com/vuejs/core/issues/13245)) ([cf5a5e0](https://github.com/vuejs/core/commit/cf5a5e0edf0efcab25c27aa2d13eba91f7372d39)), closes [#13240](https://github.com/vuejs/core/issues/13240)\n* **compiler-sfc:** simulate `allowArbitraryExtensions` on resolving type ([#13301](https://github.com/vuejs/core/issues/13301)) ([f7ce5ae](https://github.com/vuejs/core/commit/f7ce5ae666129339c006b339437c2dff6bceffe0)), closes [#13295](https://github.com/vuejs/core/issues/13295)\n* **custom-element:** allow injecting values ​​from app context in nested elements ([#13219](https://github.com/vuejs/core/issues/13219)) ([b991075](https://github.com/vuejs/core/commit/b9910755a50c7d6c52b28c3aef20cf97810295c9)), closes [#13212](https://github.com/vuejs/core/issues/13212)\n* **custom-element:** ensure proper remount and prevent redundant slot parsing with shadowRoot false ([#13201](https://github.com/vuejs/core/issues/13201)) ([1d41d4d](https://github.com/vuejs/core/commit/1d41d4de7f64a37160c8171d0137fd8d35c346c9)), closes [#13199](https://github.com/vuejs/core/issues/13199)\n* **custom-element:** preserve appContext during update ([#12455](https://github.com/vuejs/core/issues/12455)) ([013749e](https://github.com/vuejs/core/commit/013749e75ef3b51762a86da379ea4ba4501b54ae)), closes [#12453](https://github.com/vuejs/core/issues/12453)\n* **custom-element:** properly resolve props for sync component defs ([#12855](https://github.com/vuejs/core/issues/12855)) ([a683c80](https://github.com/vuejs/core/commit/a683c80cf44ecc482f8ac9c76bf2381443c1b0bb)), closes [#12854](https://github.com/vuejs/core/issues/12854)\n* **hydration:** handle transition appear hydration edge case ([#13339](https://github.com/vuejs/core/issues/13339)) ([35aeae7](https://github.com/vuejs/core/commit/35aeae7fa3168adcf9ed95fd35495d17c8b93eeb)), closes [#13335](https://github.com/vuejs/core/issues/13335)\n* **hydration:** skip lazy hydration for patched components ([#13283](https://github.com/vuejs/core/issues/13283)) ([80055fd](https://github.com/vuejs/core/commit/80055fddfb3ca1e2a44f19c7f0ffaeba00de5140)), closes [#13255](https://github.com/vuejs/core/issues/13255)\n* **suspense:** handle edge case in patching list nodes within Suspense ([#13306](https://github.com/vuejs/core/issues/13306)) ([772b008](https://github.com/vuejs/core/commit/772b0087cb7be151c514a1d30365fb0f61a652ba)), closes [#13305](https://github.com/vuejs/core/issues/13305)\n* **teleport:** handle deferred teleport updates before and after mount ([#13350](https://github.com/vuejs/core/issues/13350)) ([d15dce3](https://github.com/vuejs/core/commit/d15dce3142474f2ef9fffed38383acdadcb26c4c)), closes [#13349](https://github.com/vuejs/core/issues/13349)\n* **types:** avoid merging component instance into `$props` in `ComponentInstance` ([#12870](https://github.com/vuejs/core/issues/12870)) ([f44feed](https://github.com/vuejs/core/commit/f44feed6fa461a9c4c724e9631c19e9e214c0a20)), closes [#12751](https://github.com/vuejs/core/issues/12751)\n* **types:** exclude `undefined` from inferred prop types with default values ([#13007](https://github.com/vuejs/core/issues/13007)) ([5179d32](https://github.com/vuejs/core/commit/5179d328d950015e7fb2a74fe1a8518fd8d2c94e)), closes [#13006](https://github.com/vuejs/core/issues/13006)\n* **watch:** update `oldValue` before running `cb` to prevent stale value ([#12296](https://github.com/vuejs/core/issues/12296)) ([c69c4bb](https://github.com/vuejs/core/commit/c69c4bb59c114f2b5e03733b55ef9ace3087b5c3)), closes [#12294](https://github.com/vuejs/core/issues/12294)\n\n\n\n## [3.5.14](https://github.com/vuejs/core/compare/v3.5.13...v3.5.14) (2025-05-15)\n\n\n### Bug Fixes\n\n* **compat:** correct deprecation message for v-bind.sync usage ([#13137](https://github.com/vuejs/core/issues/13137)) ([466b30f](https://github.com/vuejs/core/commit/466b30f4049ec89fb282624ec17d1a93472ab93f)), closes [#13133](https://github.com/vuejs/core/issues/13133)\n* **compiler-core:** remove slot cache from parent renderCache during unmounting ([#13215](https://github.com/vuejs/core/issues/13215)) ([5d166f3](https://github.com/vuejs/core/commit/5d166f3796a03a497435fc079c6a83a4e9c6cf52))\n* **compiler-sfc:** fix scope handling for props destructure in function parameters and catch clauses ([8e34357](https://github.com/vuejs/core/commit/8e3435779a667de485cf9efd78667d0ca14c5f84)), closes [#12790](https://github.com/vuejs/core/issues/12790)\n* **compiler-sfc:** treat the return value of `useTemplateRef` as a definite ref ([#13197](https://github.com/vuejs/core/issues/13197)) ([8ae1122](https://github.com/vuejs/core/commit/8ae11226e8ee938615e17c7b81dc38ae3f7cefb9))\n* **compiler:** fix spelling error in domTagConfig ([#13043](https://github.com/vuejs/core/issues/13043)) ([388295b](https://github.com/vuejs/core/commit/388295b27f3cc69eba25d325bbe60a36a3df831a))\n* **customFormatter:** properly accessing ref value during debugger ([#12948](https://github.com/vuejs/core/issues/12948)) ([fdbd026](https://github.com/vuejs/core/commit/fdbd02658301dd794fe0c84f0018d080a07fca9f))\n* **hmr/teleport:** adjust static children traversal for HMR in dev mode ([#12819](https://github.com/vuejs/core/issues/12819)) ([5e37dd0](https://github.com/vuejs/core/commit/5e37dd009562bcd8080a200c32abde2d6e4f0305)), closes [#12816](https://github.com/vuejs/core/issues/12816)\n* **hmr:** avoid hydration for hmr root reload ([#12450](https://github.com/vuejs/core/issues/12450)) ([1f98a9c](https://github.com/vuejs/core/commit/1f98a9c493d01c21befa90107f0593bc92a58932)), closes [vitejs/vite-plugin-vue#146](https://github.com/vitejs/vite-plugin-vue/issues/146) [vitejs/vite-plugin-vue#477](https://github.com/vitejs/vite-plugin-vue/issues/477)\n* **hmr:** avoid hydration for hmr updating ([#12262](https://github.com/vuejs/core/issues/12262)) ([9c4dbbc](https://github.com/vuejs/core/commit/9c4dbbc5185125835ad3e49baba303bd54676111)), closes [#7706](https://github.com/vuejs/core/issues/7706) [#8170](https://github.com/vuejs/core/issues/8170)\n* **reactivity:** ensure markRaw objects are not reactive ([#12824](https://github.com/vuejs/core/issues/12824)) ([295b5ec](https://github.com/vuejs/core/commit/295b5ec19b6a52c4a56652cc4d6e93a4ea7c14ed)), closes [#12807](https://github.com/vuejs/core/issues/12807)\n* **reactivity:** ensure multiple effectScope on() and off() calls maintains correct active scope ([22dcbf3](https://github.com/vuejs/core/commit/22dcbf3e20eb84f69c8952f6f70d9990136a4a68)), closes [#12631](https://github.com/vuejs/core/issues/12631) [#12632](https://github.com/vuejs/core/issues/12632) [#12641](https://github.com/vuejs/core/issues/12641)\n* **reactivity:** should not recompute if computed does not track reactive data ([#12341](https://github.com/vuejs/core/issues/12341)) ([0b23fd2](https://github.com/vuejs/core/commit/0b23fd23833cf085e7e112bf4435cfc9b360d072)), closes [#12337](https://github.com/vuejs/core/issues/12337)\n* **runtime-core:**  stop tracking deps in setRef during unmount ([#13210](https://github.com/vuejs/core/issues/13210)) ([016c472](https://github.com/vuejs/core/commit/016c472bd2e7604b21c69dee1da8545ce26e4d2f))\n* **runtime-core:**  update __vnode of static nodes when patching along the optimized path ([#13223](https://github.com/vuejs/core/issues/13223)) ([b3ecee3](https://github.com/vuejs/core/commit/b3ecee3da8ed5c55dea89ce6b4b376b2b722b018))\n* **runtime-core:** inherit comment nodes during block patch in production build  ([#10748](https://github.com/vuejs/core/issues/10748)) ([6264505](https://github.com/vuejs/core/commit/626450590d81f79117b34d2a73073b1dc8f551bd)), closes [#10747](https://github.com/vuejs/core/issues/10747) [#12650](https://github.com/vuejs/core/issues/12650)\n* **runtime-core:** prevent unmounted vnode from being inserted during transition leave ([#12862](https://github.com/vuejs/core/issues/12862)) ([d6a6ec1](https://github.com/vuejs/core/commit/d6a6ec13ce521683bfb2a22932778ef7b51f8600)), closes [#12860](https://github.com/vuejs/core/issues/12860)\n* **runtime-core:** respect immutability for readonly reactive arrays in `v-for` ([#13091](https://github.com/vuejs/core/issues/13091)) ([3f27c58](https://github.com/vuejs/core/commit/3f27c58ffbd4309df369bc89493fdc284dc540bb)), closes [#13087](https://github.com/vuejs/core/issues/13087)\n* **runtime-dom:** always treat autocorrect as attribute ([#13001](https://github.com/vuejs/core/issues/13001)) ([1499135](https://github.com/vuejs/core/commit/1499135c227236e037bb746beeb777941b0b58ff)), closes [#5705](https://github.com/vuejs/core/issues/5705)\n* **slots:** properly warn if slot invoked in setup ([#12195](https://github.com/vuejs/core/issues/12195)) ([9196222](https://github.com/vuejs/core/commit/9196222ae1d63b52b35ac5fbf5e71494587ccf05)), closes [#12194](https://github.com/vuejs/core/issues/12194)\n* **ssr:** properly init slots during ssr rendering ([#12441](https://github.com/vuejs/core/issues/12441)) ([2206cd2](https://github.com/vuejs/core/commit/2206cd235a1627c540e795e378b7564a55b47313)), closes [#12438](https://github.com/vuejs/core/issues/12438)\n* **transition:** fix KeepAlive with transition out-in mode behavior in production ([#12468](https://github.com/vuejs/core/issues/12468)) ([343c891](https://github.com/vuejs/core/commit/343c89122448719bd6ed6bd9de986dfb2721d6bf)), closes [#12465](https://github.com/vuejs/core/issues/12465)\n* **TransitionGroup:** reset prevChildren to prevent memory leak ([#13183](https://github.com/vuejs/core/issues/13183)) ([8b848cb](https://github.com/vuejs/core/commit/8b848cbbd2af337d23e19e202f9ab433f8580855)), closes [#13181](https://github.com/vuejs/core/issues/13181)\n* **types:** allow return any for Options API lifecycle hooks ([#5914](https://github.com/vuejs/core/issues/5914)) ([06310e8](https://github.com/vuejs/core/commit/06310e82f5bed62d1b9733dcb18cd8d6edc988de))\n* **types:** the directive's modifiers should be optional ([#12605](https://github.com/vuejs/core/issues/12605)) ([10e54dc](https://github.com/vuejs/core/commit/10e54dcc86a7967f3196d96200bcbd1d3d42082f))\n* **typos:** fix comments referencing transformElement.ts ([#12551](https://github.com/vuejs/core/issues/12551))[ci-skip] ([11c053a](https://github.com/vuejs/core/commit/11c053a5429ad0d27a0e2c78b6b026ea00ace116))\n\n\n### Features\n\n* **types:** add type TemplateRef ([#12645](https://github.com/vuejs/core/issues/12645)) ([636a861](https://github.com/vuejs/core/commit/636a8619f06c71dfd79f7f6412fd130c4f84226f))\n\n\n\n## [3.5.13](https://github.com/vuejs/core/compare/v3.5.12...v3.5.13) (2024-11-15)\n\n\n### Bug Fixes\n\n* **compiler-core:** handle v-memo + v-for with functional key ([#12014](https://github.com/vuejs/core/issues/12014)) ([99009ee](https://github.com/vuejs/core/commit/99009eee0efc238392daba93792d478525b21afa)), closes [#12013](https://github.com/vuejs/core/issues/12013)\n* **compiler-dom:** properly stringify template string style ([#12392](https://github.com/vuejs/core/issues/12392)) ([2d78539](https://github.com/vuejs/core/commit/2d78539da35322aea5f821b3cf9b02d006abac72)), closes [#12391](https://github.com/vuejs/core/issues/12391)\n* **custom-element:** avoid triggering mutationObserver when relecting props ([352bc88](https://github.com/vuejs/core/commit/352bc88c1bd2fda09c61ab17ea1a5967ffcd7bc0)), closes [#12214](https://github.com/vuejs/core/issues/12214) [#12215](https://github.com/vuejs/core/issues/12215)\n* **deps:** update dependency postcss to ^8.4.48 ([#12356](https://github.com/vuejs/core/issues/12356)) ([b5ff930](https://github.com/vuejs/core/commit/b5ff930089985a58c3553977ef999cec2a6708a4))\n* **hydration:** the component vnode's el should be updated when a mismatch occurs. ([#12255](https://github.com/vuejs/core/issues/12255)) ([a20a4cb](https://github.com/vuejs/core/commit/a20a4cb36a3e717d1f8f259d0d59f133f508ff0a)), closes [#12253](https://github.com/vuejs/core/issues/12253)\n* **reactivity:** avoid unnecessary watcher effect removal from inactive scope ([2193284](https://github.com/vuejs/core/commit/21932840eae72ffcd357a62ec596aaecc7ec224a)), closes [#5783](https://github.com/vuejs/core/issues/5783) [#5806](https://github.com/vuejs/core/issues/5806)\n* **reactivity:** release nested effects/scopes on effect scope stop ([#12373](https://github.com/vuejs/core/issues/12373)) ([bee2f5e](https://github.com/vuejs/core/commit/bee2f5ee62dc0cd04123b737779550726374dd0a)), closes [#12370](https://github.com/vuejs/core/issues/12370)\n* **runtime-dom:** set css vars before user onMounted hooks ([2d5c5e2](https://github.com/vuejs/core/commit/2d5c5e25e9b7a56e883674fb434135ac514429b5)), closes [#11533](https://github.com/vuejs/core/issues/11533)\n* **runtime-dom:** set css vars on update to handle child forcing reflow in onMount ([#11561](https://github.com/vuejs/core/issues/11561)) ([c4312f9](https://github.com/vuejs/core/commit/c4312f9c715c131a09e552ba46e9beb4b36d55e6))\n* **ssr:** avoid updating subtree of async component if it is resolved ([#12363](https://github.com/vuejs/core/issues/12363)) ([da7ad5e](https://github.com/vuejs/core/commit/da7ad5e3d24f3e108401188d909d27a4910da095)), closes [#12362](https://github.com/vuejs/core/issues/12362)\n* **ssr:** ensure v-text updates correctly with custom directives in SSR output ([#12311](https://github.com/vuejs/core/issues/12311)) ([1f75d4e](https://github.com/vuejs/core/commit/1f75d4e6dfe18121ebe443cd3e8105d54f727893)), closes [#12309](https://github.com/vuejs/core/issues/12309)\n* **ssr:** handle initial selected state for select with v-model + v-for option ([#12399](https://github.com/vuejs/core/issues/12399)) ([4f8d807](https://github.com/vuejs/core/commit/4f8d8078221ee52deed266677a227ad2a6d8dd22)), closes [#12395](https://github.com/vuejs/core/issues/12395)\n* **teleport:** handle deferred teleport update before mounted ([#12168](https://github.com/vuejs/core/issues/12168)) ([8bff142](https://github.com/vuejs/core/commit/8bff142f99b646e9dd15897ec75368fbf34f1534)), closes [#12161](https://github.com/vuejs/core/issues/12161)\n* **templateRef:** set ref on cached async component which wrapped in KeepAlive ([#12290](https://github.com/vuejs/core/issues/12290)) ([983eb50](https://github.com/vuejs/core/commit/983eb50a17eac76f1bba4394ad0316c62b72191d)), closes [#4999](https://github.com/vuejs/core/issues/4999) [#5004](https://github.com/vuejs/core/issues/5004)\n* **test:** update snapshot ([#12169](https://github.com/vuejs/core/issues/12169)) ([828d4a4](https://github.com/vuejs/core/commit/828d4a443919fa2aa4e2e92fbd03a5f04b258eea))\n* **Transition:** fix transition memory leak edge case ([#12182](https://github.com/vuejs/core/issues/12182)) ([660132d](https://github.com/vuejs/core/commit/660132df6c6a8c14bf75e593dc47d2fdada30322)), closes [#12181](https://github.com/vuejs/core/issues/12181)\n* **transition:** reflow before leave-active class after leave-from ([#12288](https://github.com/vuejs/core/issues/12288)) ([4b479db](https://github.com/vuejs/core/commit/4b479db61d233b054561402ae94ef08550073ea1)), closes [#2593](https://github.com/vuejs/core/issues/2593)\n* **types:** defineEmits w/ interface declaration ([#12343](https://github.com/vuejs/core/issues/12343)) ([1022eab](https://github.com/vuejs/core/commit/1022eabaa1aaf8436876f5ec5573cb1e4b3959a6)), closes [#8457](https://github.com/vuejs/core/issues/8457)\n* **v-once:** setting hasOnce to current block only when in v-once ([#12374](https://github.com/vuejs/core/issues/12374)) ([37300fc](https://github.com/vuejs/core/commit/37300fc26190a7299efddbf98800ffd96d5cad96)), closes [#12371](https://github.com/vuejs/core/issues/12371)\n\n\n### Performance Improvements\n\n* **reactivity:** do not track inner key `__v_skip`` ([#11690](https://github.com/vuejs/core/issues/11690)) ([d637bd6](https://github.com/vuejs/core/commit/d637bd6c0164c2883e6eabd3c2f1f8c258dedfb1))\n* **runtime-core:** use feature flag for call to resolveMergedOptions ([#12163](https://github.com/vuejs/core/issues/12163)) ([1755ac0](https://github.com/vuejs/core/commit/1755ac0a108ba3486bd8397e56d3bdcd69196594))\n\n\n\n## [3.5.12](https://github.com/vuejs/core/compare/v3.5.11...v3.5.12) (2024-10-11)\n\n\n### Bug Fixes\n\n* **compiler-dom:** avoid stringify option with null value ([#12096](https://github.com/vuejs/core/issues/12096)) ([f6d9926](https://github.com/vuejs/core/commit/f6d99262364b7444ebab8742158599e8cdd79eaa)), closes [#12093](https://github.com/vuejs/core/issues/12093)\n* **compiler-sfc:**  do not skip TSInstantiationExpression when transforming props destructure ([#12064](https://github.com/vuejs/core/issues/12064)) ([d3ecde8](https://github.com/vuejs/core/commit/d3ecde8a696ff62c8d0ab067fd1d7ee0565b63c5))\n* **compiler-sfc:** use sass modern api if available and avoid deprecation warning ([#11992](https://github.com/vuejs/core/issues/11992)) ([4474c11](https://github.com/vuejs/core/commit/4474c113d1fb1c26298dd6794275d5b5c7cc4d93))\n* **compiler:** clone loc to `ifNode` ([#12131](https://github.com/vuejs/core/issues/12131)) ([cde2c06](https://github.com/vuejs/core/commit/cde2c0671b00d4f6111fcbd7aa76e45872f20b0c)), closes [vuejs/language-tools#4911](https://github.com/vuejs/language-tools/issues/4911)\n* **custom-element:** properly remove hyphenated attribute ([#12143](https://github.com/vuejs/core/issues/12143)) ([e16e9a7](https://github.com/vuejs/core/commit/e16e9a7341e7cfb3c443da4e5e5b06e8158712c3)), closes [#12139](https://github.com/vuejs/core/issues/12139)\n* **defineModel:** handle kebab-case model correctly ([#12063](https://github.com/vuejs/core/issues/12063)) ([c0418a3](https://github.com/vuejs/core/commit/c0418a3b8fa96a0b108ab71b7aab5d3388f90557)), closes [#12060](https://github.com/vuejs/core/issues/12060)\n* **deps:** update dependency monaco-editor to ^0.52.0 ([#12119](https://github.com/vuejs/core/issues/12119)) ([f7cbea2](https://github.com/vuejs/core/commit/f7cbea2111c7770a180b640f36f6a5d4d6abc698))\n* **hydration:** provide compat fallback for idle callback hydration strategy ([#11935](https://github.com/vuejs/core/issues/11935)) ([1ae545a](https://github.com/vuejs/core/commit/1ae545a3786abef983be1c969726489685569c92))\n* **reactivity:** trigger reactivity for Map key `undefined` ([#12055](https://github.com/vuejs/core/issues/12055)) ([7ad289e](https://github.com/vuejs/core/commit/7ad289e1e7fea654524008ff91e43a8b8a55ef22)), closes [#12054](https://github.com/vuejs/core/issues/12054)\n* **runtime-core:** allow symbol values for slot prop key ([#12069](https://github.com/vuejs/core/issues/12069)) ([d9d4d4e](https://github.com/vuejs/core/commit/d9d4d4e158cd51a9ddda249f29de8467f60b2792)), closes [#12068](https://github.com/vuejs/core/issues/12068)\n* **runtime-core:** fix required prop check false positive for kebab-case edge cases  ([#12034](https://github.com/vuejs/core/issues/12034)) ([9da1ac1](https://github.com/vuejs/core/commit/9da1ac156552ac449754e1373aac7e349841becb)), closes [#12011](https://github.com/vuejs/core/issues/12011)\n* **runtime-dom:** prevent unnecessary updates in v-model checkbox when value is unchanged ([#12146](https://github.com/vuejs/core/issues/12146)) ([ea943af](https://github.com/vuejs/core/commit/ea943afe404c4ca4b729906c5e8daf7aa2ccde9b)), closes [#12144](https://github.com/vuejs/core/issues/12144)\n* **teleport:** handle disabled teleport with updateCssVars ([#12113](https://github.com/vuejs/core/issues/12113)) ([76a8223](https://github.com/vuejs/core/commit/76a8223199c148b79a5c0ea19e235164809760cd)), closes [#12112](https://github.com/vuejs/core/issues/12112)\n* **transition/ssr:** make transition appear work with Suspense in SSR ([#12047](https://github.com/vuejs/core/issues/12047)) ([f1a4f67](https://github.com/vuejs/core/commit/f1a4f67aedfe83e440c54222213f070774faa421)), closes [#12046](https://github.com/vuejs/core/issues/12046)\n* **types:** ensure `this.$props` type does not include `string` ([#12123](https://github.com/vuejs/core/issues/12123)) ([704173e](https://github.com/vuejs/core/commit/704173e24276706de672cca6c9507e4dd9651197)), closes [#12122](https://github.com/vuejs/core/issues/12122)\n* **types:** retain union type narrowing with defaults applied ([#12108](https://github.com/vuejs/core/issues/12108)) ([05685a9](https://github.com/vuejs/core/commit/05685a9d7c42d4cd37169b867833776b91154fed)), closes [#12106](https://github.com/vuejs/core/issues/12106)\n* **useId:** ensure useId consistency when using serverPrefetch ([#12128](https://github.com/vuejs/core/issues/12128)) ([b4d3534](https://github.com/vuejs/core/commit/b4d35349d8bc39aa15bd3f1094d230e5928b177c)), closes [#12102](https://github.com/vuejs/core/issues/12102)\n* **watch:** watchEffect clean-up with SSR ([#12097](https://github.com/vuejs/core/issues/12097)) ([b094c72](https://github.com/vuejs/core/commit/b094c72b3d40c52c7124f145a9db028509a11202)), closes [#11956](https://github.com/vuejs/core/issues/11956)\n\n\n### Performance Improvements\n\n* **reactivity:** avoid unnecessary recursion in removeSub ([#12135](https://github.com/vuejs/core/issues/12135)) ([ec917cf](https://github.com/vuejs/core/commit/ec917cfdb9d0169cd0835d3a0e28244242657dc9))\n\n\n\n## [3.5.11](https://github.com/vuejs/core/compare/v3.5.10...v3.5.11) (2024-10-03)\n\n\n### Bug Fixes\n\n* **compiler-sfc:** do not skip `TSSatisfiesExpression` when transforming props destructure ([#12062](https://github.com/vuejs/core/issues/12062)) ([2328b05](https://github.com/vuejs/core/commit/2328b051f4efa1f1394b7d4e73b7c3f76e430e7c)), closes [#12061](https://github.com/vuejs/core/issues/12061)\n* **reactivity:** prevent overwriting `next` property during batch processing ([#12075](https://github.com/vuejs/core/issues/12075)) ([d3f5e6e](https://github.com/vuejs/core/commit/d3f5e6e5319b4ffaa55ca9a2ea3d95d78e76fa58)), closes [#12072](https://github.com/vuejs/core/issues/12072)\n* **scheduler:** job ordering when the post queue is flushing ([#12090](https://github.com/vuejs/core/issues/12090)) ([577edca](https://github.com/vuejs/core/commit/577edca8e7795436efd710d1c289ea8ea2642b0e))\n* **types:** correctly infer `TypeProps` when it is `any` ([#12073](https://github.com/vuejs/core/issues/12073)) ([57315ab](https://github.com/vuejs/core/commit/57315ab9688c9741a271d1075bbd28cbe5f71e2f)), closes [#12058](https://github.com/vuejs/core/issues/12058)\n* **types:** should not intersect `PublicProps` with `Props` ([#12077](https://github.com/vuejs/core/issues/12077)) ([6f85894](https://github.com/vuejs/core/commit/6f8589437635706f825ccec51800effba1d2bf5f))\n* **types:** infer the first generic type of `Ref` correctly ([#12094](https://github.com/vuejs/core/issues/12094)) ([c97bb84](https://github.com/vuejs/core/commit/c97bb84d0b0a16b012f886b6498e924415ed63e5))\n\n\n\n## [3.5.10](https://github.com/vuejs/core/compare/v3.5.9...v3.5.10) (2024-09-27)\n\n\n### Bug Fixes\n\n* **custom-element:** properly set kebab-case props on Vue custom elements ([ea3efa0](https://github.com/vuejs/core/commit/ea3efa09e008918c1d9ba7226833a8b1a7a57244)), closes [#12030](https://github.com/vuejs/core/issues/12030) [#12032](https://github.com/vuejs/core/issues/12032)\n* **reactivity:** fix nested batch edge case ([93c95dd](https://github.com/vuejs/core/commit/93c95dd4cd416503f43a98a1455f62658d22b0b2))\n* **reactivity:** only clear notified flags for computed in first batch iteration ([aa9ef23](https://github.com/vuejs/core/commit/aa9ef2386a0cd39a174e5a887ec2b1a3525034fc)), closes [#12045](https://github.com/vuejs/core/issues/12045)\n* **types/ref:** handle nested refs in UnwrapRef ([#12049](https://github.com/vuejs/core/issues/12049)) ([e2c19c2](https://github.com/vuejs/core/commit/e2c19c20cfee9788519a80c0e53e216b78505994)), closes [#12044](https://github.com/vuejs/core/issues/12044)\n\n\n\n## [3.5.9](https://github.com/vuejs/core/compare/v3.5.8...v3.5.9) (2024-09-26)\n\n\n### Bug Fixes\n\n* **reactivity:** fix property dep removal regression ([6001e5c](https://github.com/vuejs/core/commit/6001e5c81a05c894586f9287fbd991677bdd0455)), closes [#12020](https://github.com/vuejs/core/issues/12020) [#12021](https://github.com/vuejs/core/issues/12021)\n* **reactivity:** fix recursive sync watcher on computed edge case ([10ff159](https://github.com/vuejs/core/commit/10ff15924053d9bd95ad706f78ce09e288213fcf)), closes [#12033](https://github.com/vuejs/core/issues/12033) [#12037](https://github.com/vuejs/core/issues/12037)\n* **runtime-core:** avoid rendering plain object as VNode ([#12038](https://github.com/vuejs/core/issues/12038)) ([cb34b28](https://github.com/vuejs/core/commit/cb34b28a4a9bf868be4785b001c526163eda342e)), closes [#12035](https://github.com/vuejs/core/issues/12035) [vitejs/vite-plugin-vue#353](https://github.com/vitejs/vite-plugin-vue/issues/353)\n* **runtime-core:** make useId() always return a string ([a177092](https://github.com/vuejs/core/commit/a177092754642af2f98c33a4feffe8f198c3c950))\n* **types:** correct type inference of union event names ([#12022](https://github.com/vuejs/core/issues/12022)) ([4da6881](https://github.com/vuejs/core/commit/4da688141d9e7c15b622c289deaa81b11845b2c7))\n* **vue:** properly cache runtime compilation ([#12019](https://github.com/vuejs/core/issues/12019)) ([fa0ba24](https://github.com/vuejs/core/commit/fa0ba24b3ace02d7ecab65e57c2bea89a2550dcb))\n\n\n\n## [3.5.8](https://github.com/vuejs/core/compare/v3.5.7...v3.5.8) (2024-09-22)\n\n\n### Bug Fixes\n\n* **reactivity:** do not remove dep from depsMap when cleaning up deps of computed ([#11995](https://github.com/vuejs/core/issues/11995)) ([0267a58](https://github.com/vuejs/core/commit/0267a588017eee4951ac2a877fe1ccae84cad905))\n\n\n\n## [3.5.7](https://github.com/vuejs/core/compare/v3.5.6...v3.5.7) (2024-09-20)\n\n\n### Bug Fixes\n\n* **compile-core:** fix v-model with newlines edge case ([#11960](https://github.com/vuejs/core/issues/11960)) ([6224288](https://github.com/vuejs/core/commit/62242886d705ece88dbcad45bb78072ecccad0ca)), closes [#8306](https://github.com/vuejs/core/issues/8306)\n* **compiler-sfc:** initialize scope with null prototype object ([#11963](https://github.com/vuejs/core/issues/11963)) ([215e154](https://github.com/vuejs/core/commit/215e15407294bf667261360218f975b88c99c2e5))\n* **hydration:** avoid observing non-Element node ([#11954](https://github.com/vuejs/core/issues/11954)) ([7257e6a](https://github.com/vuejs/core/commit/7257e6a34200409b3fc347d3bb807e11e2785974)), closes [#11952](https://github.com/vuejs/core/issues/11952)\n* **reactivity:** do not remove dep from depsMap when unsubbed by computed ([960706e](https://github.com/vuejs/core/commit/960706eebf73f08ebc9d5dd853a05def05e2c153))\n* **reactivity:** fix dev-only memory leak by updating dep.subsHead on sub removal ([5c8b76e](https://github.com/vuejs/core/commit/5c8b76ed6cfbbcee4cbaac0b72beab7291044e4f)), closes [#11956](https://github.com/vuejs/core/issues/11956)\n* **reactivity:** fix memory leak from dep instances of garbage collected objects ([235ea47](https://github.com/vuejs/core/commit/235ea4772ed2972914cf142da8b7ac1fb04f7585)), closes [#11979](https://github.com/vuejs/core/issues/11979) [#11971](https://github.com/vuejs/core/issues/11971)\n* **reactivity:** fix triggerRef call on ObjectRefImpl returned by toRef ([#11986](https://github.com/vuejs/core/issues/11986)) ([b030c8b](https://github.com/vuejs/core/commit/b030c8bc7327877efb98aa3d9a58eb287a6ff07a)), closes [#11982](https://github.com/vuejs/core/issues/11982)\n* **scheduler:** ensure recursive jobs can't be queued twice ([#11955](https://github.com/vuejs/core/issues/11955)) ([d18d6aa](https://github.com/vuejs/core/commit/d18d6aa1b20dc57a8103c51ec4d61e8e53ed936d))\n* **ssr:** don't render comments in TransitionGroup ([#11961](https://github.com/vuejs/core/issues/11961)) ([a2f6ede](https://github.com/vuejs/core/commit/a2f6edeb02faedbb673c4bc5c6a59d9a79a37d07)), closes [#11958](https://github.com/vuejs/core/issues/11958)\n* **transition:** respect `duration` setting even when it is `0` ([#11967](https://github.com/vuejs/core/issues/11967)) ([f927a4a](https://github.com/vuejs/core/commit/f927a4ae6f7c453f70ba89498ee0c737dc9866fd))\n* **types:** correct type inference of all-optional props ([#11644](https://github.com/vuejs/core/issues/11644)) ([9eca65e](https://github.com/vuejs/core/commit/9eca65ee9871d1ac878755afa9a3eb1b02030350)), closes [#11733](https://github.com/vuejs/core/issues/11733) [vuejs/language-tools#4704](https://github.com/vuejs/language-tools/issues/4704)\n\n\n### Performance Improvements\n\n* **hydration:** avoid observer if element is in viewport ([#11639](https://github.com/vuejs/core/issues/11639)) ([e075dfa](https://github.com/vuejs/core/commit/e075dfad5c7649c6045e3711687ec888e7aa1a39))\n\n\n\n## [3.5.6](https://github.com/vuejs/core/compare/v3.5.5...v3.5.6) (2024-09-16)\n\n\n### Bug Fixes\n\n* **compile-dom:** should be able to stringify mathML ([#11891](https://github.com/vuejs/core/issues/11891)) ([85c138c](https://github.com/vuejs/core/commit/85c138ced108268f7656b568dfd3036a1e0aae34))\n* **compiler-sfc:** preserve old behavior when using withDefaults with destructure ([8492c3c](https://github.com/vuejs/core/commit/8492c3c49a922363d6c77ef192c133a8fbce6514)), closes [#11930](https://github.com/vuejs/core/issues/11930)\n* **reactivity:** avoid exponential perf cost and reduce call stack depth for deeply chained computeds ([#11944](https://github.com/vuejs/core/issues/11944)) ([c74bb8c](https://github.com/vuejs/core/commit/c74bb8c2dd9e82aaabb0a2a2b368e900929b513b)), closes [#11928](https://github.com/vuejs/core/issues/11928)\n* **reactivity:** rely on dirty check only when computed has deps ([#11931](https://github.com/vuejs/core/issues/11931)) ([aa5dafd](https://github.com/vuejs/core/commit/aa5dafd2b55d42d6a29316a3bc91aea85c676a0b)), closes [#11929](https://github.com/vuejs/core/issues/11929)\n* **watch:** `once` option should be ignored by watchEffect ([#11884](https://github.com/vuejs/core/issues/11884)) ([49fa673](https://github.com/vuejs/core/commit/49fa673493d93b77ddba2165ab6545bae84fd1ae))\n* **watch:** unwatch should be callable during SSR ([#11925](https://github.com/vuejs/core/issues/11925)) ([2d6adf7](https://github.com/vuejs/core/commit/2d6adf78a047eed091db277ffbd9df0822fb0bdd)), closes [#11924](https://github.com/vuejs/core/issues/11924)\n\n\n\n## [3.5.5](https://github.com/vuejs/core/compare/v3.5.4...v3.5.5) (2024-09-13)\n\n\n### Bug Fixes\n\n* **compiler-core:** fix handling of delimiterOpen in VPre ([#11915](https://github.com/vuejs/core/issues/11915)) ([706d4ac](https://github.com/vuejs/core/commit/706d4ac1d0210b2d9134b3228280187fe02fc971)), closes [#11913](https://github.com/vuejs/core/issues/11913)\n* **compiler-dom:** fix stringify static edge for partially eligible chunks in cached parent ([1d99d61](https://github.com/vuejs/core/commit/1d99d61c1bd77f9ea6743f6214a82add8346a121)), closes [#11879](https://github.com/vuejs/core/issues/11879) [#11890](https://github.com/vuejs/core/issues/11890)\n* **compiler-dom:** should ignore leading newline in `<textarea>` per spec ([3c4bf76](https://github.com/vuejs/core/commit/3c4bf7627649ec1e3220f8c4e4163c20d2afb367))\n* **compiler-sfc:** nested css supports atrule and comment ([#11899](https://github.com/vuejs/core/issues/11899)) ([0e7bc71](https://github.com/vuejs/core/commit/0e7bc717e6640644f062957ec5031506f0dab215)), closes [#11896](https://github.com/vuejs/core/issues/11896)\n* **custom-element:** handle nested customElement mount w/ shadowRoot false ([#11861](https://github.com/vuejs/core/issues/11861)) ([f2d8019](https://github.com/vuejs/core/commit/f2d801918841e7673ff3f048d0d895592a2f7e23)), closes [#11851](https://github.com/vuejs/core/issues/11851) [#11871](https://github.com/vuejs/core/issues/11871)\n* **hmr:** reload async child wrapped in Suspense + KeepAlive ([#11907](https://github.com/vuejs/core/issues/11907)) ([10a2c60](https://github.com/vuejs/core/commit/10a2c6053bd30d160d0214bb3566f540187e6874)), closes [#11868](https://github.com/vuejs/core/issues/11868)\n* **hydration:** fix mismatch of leading newline in `<textarea>` and `<pre>` ([a5f3c2e](https://github.com/vuejs/core/commit/a5f3c2eb4d2e7fae93ff93ce865b269f01cc825e)), closes [#11873](https://github.com/vuejs/core/issues/11873) [#11874](https://github.com/vuejs/core/issues/11874)\n* **reactivity:** properly clean up deps, fix memory leak ([8ea5d6d](https://github.com/vuejs/core/commit/8ea5d6d6981ab7febda0be43c3c92b18869c3a2a)), closes [#11901](https://github.com/vuejs/core/issues/11901)\n* **runtime-core:** properly update async component nested in KeepAlive ([#11917](https://github.com/vuejs/core/issues/11917)) ([7fe6c79](https://github.com/vuejs/core/commit/7fe6c795a1fc7ddcea5ad91a56141561192373ac)), closes [#11916](https://github.com/vuejs/core/issues/11916)\n* **TransitionGroup:** not warn unkeyed text children with whitespece preserve ([#11888](https://github.com/vuejs/core/issues/11888)) ([7571f20](https://github.com/vuejs/core/commit/7571f20bc3d1854377a146f41d211e05bb68cd47)), closes [#11885](https://github.com/vuejs/core/issues/11885)\n\n\n\n## [3.5.4](https://github.com/vuejs/core/compare/v3.5.3...v3.5.4) (2024-09-10)\n\n\n### Bug Fixes\n\n* **compiler-sfc:** correct scoped injection for nesting selector ([#11854](https://github.com/vuejs/core/issues/11854)) ([b1de75e](https://github.com/vuejs/core/commit/b1de75ed04626b6423085dfde91fb0cb481a25e8)), closes [#10567](https://github.com/vuejs/core/issues/10567)\n* **reactivity:** fix markRaw error on already marked object ([#11864](https://github.com/vuejs/core/issues/11864)) ([67d6596](https://github.com/vuejs/core/commit/67d6596d40b1807b9cd8eb0d9282932ea77be3c0)), closes [#11862](https://github.com/vuejs/core/issues/11862)\n* Revert \"fix: Revert \"fix(reactivity): self-referencing computed should refresh\"\" ([e596378](https://github.com/vuejs/core/commit/e596378e0be728dad7d60938449f3fa557ca2ec9))\n* **runtime-core:** handle shallow reactive arrays in renderList correctly ([#11870](https://github.com/vuejs/core/issues/11870)) ([ced59ab](https://github.com/vuejs/core/commit/ced59ab8f2f2e89c13119bab3a0c25a1a1f1c3d6)), closes [#11869](https://github.com/vuejs/core/issues/11869)\n* **types:** correctly infer `TypeEmits` with both tuple and function syntax ([#11840](https://github.com/vuejs/core/issues/11840)) ([dad6738](https://github.com/vuejs/core/commit/dad673809929c084dcb8e42640eb7daa675d4ea4)), closes [#11836](https://github.com/vuejs/core/issues/11836)\n\n\n### Performance Improvements\n\n* **reactivity:** trigger deps directly instead of storing in an array first ([#11695](https://github.com/vuejs/core/issues/11695)) ([f80d447](https://github.com/vuejs/core/commit/f80d447c17662556e9e3f99f6d199967f4c8cf3d))\n\n\n\n## [3.5.3](https://github.com/vuejs/core/compare/v3.5.2...v3.5.3) (2024-09-06)\n\n\n### Bug Fixes\n\n* **hydration:** check __asyncHydrate presence for vue3-lazy-hydration compat ([#11825](https://github.com/vuejs/core/issues/11825)) ([8e6c337](https://github.com/vuejs/core/commit/8e6c3378676be05cea7f53664442acdfb86784f9)), closes [#11793](https://github.com/vuejs/core/issues/11793)\n* Revert \"fix(reactivity): self-referencing computed should refresh\" ([35c760f](https://github.com/vuejs/core/commit/35c760f82f749f7c6e3f9bfead8221ce498e892f))\n* **ssr:** respect app.config.warnHandler during ssr ([bf3d9a2](https://github.com/vuejs/core/commit/bf3d9a2af41659a743706306fc798b3d215df5af)), closes [#11830](https://github.com/vuejs/core/issues/11830)\n* **Transition:** handle KeepAlive child unmount in Transition out-in mode ([#11833](https://github.com/vuejs/core/issues/11833)) ([6b7901d](https://github.com/vuejs/core/commit/6b7901d28ed3a6a9242c666cc1b8e3c0b0b0fe62)), closes [#11775](https://github.com/vuejs/core/issues/11775)\n* **useId:** make generated IDs selector compatible ([babfb4c](https://github.com/vuejs/core/commit/babfb4cbcbf98601d76c1d7653eae8d250ce2710)), closes [#11828](https://github.com/vuejs/core/issues/11828)\n\n\n\n## [3.5.2](https://github.com/vuejs/core/compare/v3.5.1...v3.5.2) (2024-09-05)\n\n\n### Bug Fixes\n\n* **reactivity:** make toRaw work on proxies created by proxyRef ([46c3ab1](https://github.com/vuejs/core/commit/46c3ab1d714024894fa1d33e495d5d35c7817d4d))\n* **reactivity:** pass oldValue to computed getter ([#11813](https://github.com/vuejs/core/issues/11813)) ([98864a7](https://github.com/vuejs/core/commit/98864a7ef5c8080c407166c8221488a4eacbbc81)), closes [#11812](https://github.com/vuejs/core/issues/11812)\n* **reactivity:** prevent endless recursion in computed getters ([#11797](https://github.com/vuejs/core/issues/11797)) ([716275d](https://github.com/vuejs/core/commit/716275d1b1d2383d8ef0306fcd94558d4d9170f2))\n* **reactivity:** self-referencing computed should refresh ([e84c4a6](https://github.com/vuejs/core/commit/e84c4a608e9dc96fb2a4a29d538bcc64f26103a2)), closes [/github.com/vuejs/core/pull/11797#issuecomment-2330738633](https://github.com//github.com/vuejs/core/pull/11797/issues/issuecomment-2330738633)\n* **scheduler:** prevent duplicate jobs being queued ([#11826](https://github.com/vuejs/core/issues/11826)) ([df56cc5](https://github.com/vuejs/core/commit/df56cc528793b1d6131a1e64095dd5cb95c56bee)), closes [#11712](https://github.com/vuejs/core/issues/11712) [#11807](https://github.com/vuejs/core/issues/11807)\n* **suspense:** avoid updating anchor if activeBranch has not been rendered to the actual container ([#11818](https://github.com/vuejs/core/issues/11818)) ([3c0d531](https://github.com/vuejs/core/commit/3c0d531fa7fe762bfe46fbe63f318adc95221795)), closes [#11806](https://github.com/vuejs/core/issues/11806)\n* **Transition:** handle KeepAlive child unmount in Transition out-in mode ([#11778](https://github.com/vuejs/core/issues/11778)) ([3116553](https://github.com/vuejs/core/commit/311655352931863dfcf520b8cf29cebc5b7e1e00)), closes [#11775](https://github.com/vuejs/core/issues/11775)\n* **types:** add HTMLDialogElement missing close event ([#11811](https://github.com/vuejs/core/issues/11811)) ([3634f7a](https://github.com/vuejs/core/commit/3634f7a4c1649ad2e7e969eb4512512868c61d01))\n* **types:** added name attribute support to details tag ([#11823](https://github.com/vuejs/core/issues/11823)) ([c74176e](https://github.com/vuejs/core/commit/c74176ec7b4d1d34159ce21d600c04b157ac5549)), closes [#11821](https://github.com/vuejs/core/issues/11821)\n* **types:** fix defineComponent props inference when setup() has explicit annotation ([fca20a3](https://github.com/vuejs/core/commit/fca20a39aa4a6f98c8f972bd435ebb7dc535648a)), closes [#11803](https://github.com/vuejs/core/issues/11803)\n* **useTemplateRef:** properly fix readonly warning in dev and ensure prod behavior consistency ([9b7797d](https://github.com/vuejs/core/commit/9b7797d0d1fc773e979e042673d5b9b3151c40fc)), closes [#11808](https://github.com/vuejs/core/issues/11808) [#11816](https://github.com/vuejs/core/issues/11816) [#11810](https://github.com/vuejs/core/issues/11810)\n\n\n### Features\n\n* **compiler-core:** parse modifiers as expression to provide location data ([#11819](https://github.com/vuejs/core/issues/11819)) ([3f13203](https://github.com/vuejs/core/commit/3f13203564164eeb2945bdc0b9ef755c37477d75))\n\n\n\n## [3.5.1](https://github.com/vuejs/core/compare/v3.5.0...v3.5.1) (2024-09-04)\n\n\n### Bug Fixes\n\n* **build:** improve built-in components treeshakability ([4eee630](https://github.com/vuejs/core/commit/4eee630b3122a10d0baf9b91358cfffa92d6fd81))\n* **reactivity:** handle non-array arguments in reactive `concat` method ([#11794](https://github.com/vuejs/core/issues/11794)) ([475977a](https://github.com/vuejs/core/commit/475977a6f76b77392610e0a3ec2b0e076d1e1d59)), closes [#11792](https://github.com/vuejs/core/issues/11792)\n* **Transition:** avoid applying transition hooks on comment vnode ([#11788](https://github.com/vuejs/core/issues/11788)) ([51912f8](https://github.com/vuejs/core/commit/51912f8a02e35f172f6d30ed7a2f3a92c1407cf9)), closes [#11782](https://github.com/vuejs/core/issues/11782)\n* **types:** avoid using intersection type in `Readonly<...>` to fix JSDoc emit ([#11799](https://github.com/vuejs/core/issues/11799)) ([7518bc1](https://github.com/vuejs/core/commit/7518bc19dc73ba46dcf1eef6e23f9e6e75552675))\n* **useTemplateRef:** fix readonly warning when useTemplateRef has same variable name as template ref ([bc63df0](https://github.com/vuejs/core/commit/bc63df01992fdbf0b6749ad234153725697ed896)), closes [#11795](https://github.com/vuejs/core/issues/11795) [#11802](https://github.com/vuejs/core/issues/11802) [#11804](https://github.com/vuejs/core/issues/11804)\n\n\n\n# [3.5.0](https://github.com/vuejs/core/compare/v3.5.0-rc.1...v3.5.0) (2024-09-03)\n\n## Aggregated Features List for 3.5 (alpha to stable)\n\n### Reactivity\n\n- **reactivity**: Refactor reactivity system to use version counting and doubly-linked list tracking ([#10397](https://github.com/vuejs/core/pull/10397)) ([05eb4e0](https://github.com/vuejs/core/commit/05eb4e0fefd585125dd60b7f8fe9c36928d921aa))\n- **reactivity**: Optimize array tracking ([#9511](https://github.com/vuejs/core/pull/9511)) ([70196a4](https://github.com/vuejs/core/commit/70196a40cc078f50fcc1110c38c06fbcc70b205e))\n- **compiler-sfc:** enable reactive props destructure by default ([d2dac0e](https://github.com/vuejs/core/commit/d2dac0e359c47d1ed0aa77eda488e76fd6466d2d))\n- **reactivity:** `onEffectCleanup` API ([2cc5615](https://github.com/vuejs/core/commit/2cc5615590de77126e8df46136de0240dbde5004)), closes [#10173](https://github.com/vuejs/core/issues/10173)\n- **reactivity:** add `failSilently` argument for `onScopeDispose` ([9a936aa](https://github.com/vuejs/core/commit/9a936aaec489c79433a32791ecf5ddb1739a62bd))\n- **reactivity/watch:** base `watch`, `getCurrentWatcher`, and `onWatcherCleanup` ([#9927](https://github.com/vuejs/core/issues/9927)) ([205e5b5](https://github.com/vuejs/core/commit/205e5b5e277243c3af2c937d9bd46cf671296b72))\n- **reactivity/watch:** add pause/resume for ReactiveEffect, EffectScope, and WatchHandle ([#9651](https://github.com/vuejs/core/issues/9651)) ([267093c](https://github.com/vuejs/core/commit/267093c31490050bfcf3ff2b30a2aefee2dad582))\n- **watch:** support passing number to `deep` option to control the watch depth ([#9572](https://github.com/vuejs/core/issues/9572)) ([22f7d96](https://github.com/vuejs/core/commit/22f7d96757956ebe0baafe52256aa327908cc51c))\n- **types:** export `MultiWatchSources` type ([#9563](https://github.com/vuejs/core/issues/9563)) ([998dca5](https://github.com/vuejs/core/commit/998dca59f140420280803233f41707580688562c))\n- **types:** allow computed getter and setter types to be unrelated ([#11472](https://github.com/vuejs/core/issues/11472)) ([a01675e](https://github.com/vuejs/core/commit/a01675ef8f99b5acd6832c53051f4415b18609f2)), closes [#7271](https://github.com/vuejs/core/issues/7271)\n\n### SSR\n\n- **runtime-core:** `useId()` and `app.config.idPrefix` ([#11404](https://github.com/vuejs/core/issues/11404)) ([73ef156](https://github.com/vuejs/core/commit/73ef1561f6905d69f968c094d0180c61824f1247))\n- **hydration:** lazy hydration strategies for async components ([#11458](https://github.com/vuejs/core/issues/11458)) ([d14a11c](https://github.com/vuejs/core/commit/d14a11c1cdcee88452f17ce97758743c863958f4))\n- **hydration:** support suppressing hydration mismatch via data-allow-mismatch ([94fb2b8](https://github.com/vuejs/core/commit/94fb2b8106a66bcca1a3f922a246a29fdd1274b1))\n\n### Custom Element\n\n- **custom-element:** `useHost()` helper ([775103a](https://github.com/vuejs/core/commit/775103af37df69d34c79f12c4c1776c47d07f0a0))\n- **custom-element:** `useShadowRoot()` helper ([5a1a89b](https://github.com/vuejs/core/commit/5a1a89bd6178cc2f84ba91da7d72aee4c6ec1282)), closes [#6113](https://github.com/vuejs/core/issues/6113) [#8195](https://github.com/vuejs/core/issues/8195)\n- **custom-element:** expose `this.$host` in Options API ([1ef8f46](https://github.com/vuejs/core/commit/1ef8f46af0cfdec2fed66376772409e0aa25ad50))\n- **custom-element:** inject child components styles to custom element shadow root ([#11517](https://github.com/vuejs/core/issues/11517)) ([56c76a8](https://github.com/vuejs/core/commit/56c76a8b05c45f782ed3a16ec77c6292b71a17f1)), closes [#4662](https://github.com/vuejs/core/issues/4662) [#7941](https://github.com/vuejs/core/issues/7941) [#7942](https://github.com/vuejs/core/issues/7942)\n- **custom-element:** support configurable app instance in defineCustomElement ([6758c3c](https://github.com/vuejs/core/commit/6758c3cd0427f97394d95168c655dae3b7fa62cd)), closes [#4356](https://github.com/vuejs/core/issues/4356) [#4635](https://github.com/vuejs/core/issues/4635)\n- **custom-element:** support css `:host` selector by applying css vars on host element ([#8830](https://github.com/vuejs/core/issues/8830)) ([03a9ea2](https://github.com/vuejs/core/commit/03a9ea2b88df0842a820e09f7445c4b9189e3fcb)), closes [#8826](https://github.com/vuejs/core/issues/8826)\n- **custom-element:** support emit with options ([e181bff](https://github.com/vuejs/core/commit/e181bff6dc39d5cef92000c10291243c7d6e4d08)), closes [#7605](https://github.com/vuejs/core/issues/7605)\n- **custom-element:** support expose on customElement ([#6256](https://github.com/vuejs/core/issues/6256)) ([af838c1](https://github.com/vuejs/core/commit/af838c1b5ec23552e52e64ffa7db0eb0246c3624)), closes [#5540](https://github.com/vuejs/core/issues/5540)\n- **custom-element:** support `nonce` option for injected style tags ([bb4a02a](https://github.com/vuejs/core/commit/bb4a02a70c30e739a3c705b3d96d09258d7d7ded)), closes [#6530](https://github.com/vuejs/core/issues/6530)\n- **custom-element:** support passing custom-element-specific options via 2nd argument of defineCustomElement ([60a88a2](https://github.com/vuejs/core/commit/60a88a2b129714186cf6ba66f30f31d733d0311e))\n- **custom-element:** support `shadowRoot: false` in `defineCustomElement()` ([37d2ce5](https://github.com/vuejs/core/commit/37d2ce5d8e0fac4a00064f02b05f91f69b2d5d5e)), closes [#4314](https://github.com/vuejs/core/issues/4314) [#4404](https://github.com/vuejs/core/issues/4404)\n\n### Teleport\n\n- **teleport:** support deferred Teleport ([#11387](https://github.com/vuejs/core/issues/11387)) ([59a3e88](https://github.com/vuejs/core/commit/59a3e88903b10ac2278170a44d5a03f24fef23ef)), closes [#2015](https://github.com/vuejs/core/issues/2015) [#11386](https://github.com/vuejs/core/issues/11386)\n- **teleport/transition:** support directly nesting Teleport inside Transition ([#6548](https://github.com/vuejs/core/issues/6548)) ([0e6e3c7](https://github.com/vuejs/core/commit/0e6e3c7eb0e5320b7c1818e025cb4a490fede9c0)), closes [#5836](https://github.com/vuejs/core/issues/5836)\n\n### Misc\n\n- **runtime-core:** `useTemplateRef()` ([3ba70e4](https://github.com/vuejs/core/commit/3ba70e49b5856c53611c314d4855d679a546a7df))\n- **runtime-core:** add `app.onUnmount()` for registering cleanup functions ([#4619](https://github.com/vuejs/core/issues/4619)) ([582a3a3](https://github.com/vuejs/core/commit/582a3a382b1adda565bac576b913a88d9e8d7a9e)), closes [#4516](https://github.com/vuejs/core/issues/4516)\n- **runtime-core:** add `app.config.throwUnhandledErrorInProduction` ([f476b7f](https://github.com/vuejs/core/commit/f476b7f030f2dd427ca655fcea36f4933a4b4da0)), closes [#7876](https://github.com/vuejs/core/issues/7876)\n- **runtime-dom:** Trusted Types compatibility ([#10844](https://github.com/vuejs/core/issues/10844)) ([6d4eb94](https://github.com/vuejs/core/commit/6d4eb94853ed1b2b1675bdd7d5ba9c75cc6daed5))\n- **compiler-core:** support `Symbol` global in template expressions ([#9069](https://github.com/vuejs/core/issues/9069)) ([a501a85](https://github.com/vuejs/core/commit/a501a85a7c910868e01a5c70a2abea4e9d9e87f3))\n- **types:** export more emit related types ([#11017](https://github.com/vuejs/core/issues/11017)) ([189573d](https://github.com/vuejs/core/commit/189573dcee2a16bd3ed36ff5589d43f535e5e733))\n* **types:** add loading prop to iframe ([#11767](https://github.com/vuejs/core/issues/11767)) ([d86fe0e](https://github.com/vuejs/core/commit/d86fe0ec002901dc359a0e85f3a421b4a8538d68))\n\n### Internals\n\n- **reactivity:** store value cache on CustomRefs impls ([#11539](https://github.com/vuejs/core/issues/11539)) ([e044b6e](https://github.com/vuejs/core/commit/e044b6e737efc9433d1d84590036b82280da6292))\n- **types:** provide internal options for directly using user types in language tools ([#10801](https://github.com/vuejs/core/issues/10801)) ([75c8cf6](https://github.com/vuejs/core/commit/75c8cf63a1ef30ac84f91282d66ad3f57c6612e9))\n- **types:** provide internal options for using refs type in language tools ([#11492](https://github.com/vuejs/core/issues/11492)) ([5ffd1a8](https://github.com/vuejs/core/commit/5ffd1a89455807d5069eb2c28eba0379641dca76))\n\n\n\n## Bug Fixes\n\n* **compiler-sfc:** fix import usage check for kebab-case same name shorthand binding ([0f7c0e5](https://github.com/vuejs/core/commit/0f7c0e5dc0eedada7a5194db87fd0a7dbd1d3354)), closes [#11745](https://github.com/vuejs/core/issues/11745) [#11754](https://github.com/vuejs/core/issues/11754)\n* **cssVars:** correctly escape double quotes in SSR ([#11784](https://github.com/vuejs/core/issues/11784)) ([7b5b6e0](https://github.com/vuejs/core/commit/7b5b6e0275f35748dca6d7eb842f8ab2364c6b9a)), closes [#11779](https://github.com/vuejs/core/issues/11779)\n* **deps:** update dependency postcss to ^8.4.44 ([#11774](https://github.com/vuejs/core/issues/11774)) ([cb843e0](https://github.com/vuejs/core/commit/cb843e0be31f9e563ccfc30eca0c06f2a224b505))\n* **hydration:** escape css var name to avoid mismatch ([#11739](https://github.com/vuejs/core/issues/11739)) ([ca12e77](https://github.com/vuejs/core/commit/ca12e776bc53aaa31f2df6bb6edc6be1b2f10c37)), closes [#11735](https://github.com/vuejs/core/issues/11735)\n* **hydration:** handle text nodes with 0 during hydration ([#11772](https://github.com/vuejs/core/issues/11772)) ([c756da2](https://github.com/vuejs/core/commit/c756da24b2d8635cf52b4c7d3abf5bf938852cc5)), closes [#11771](https://github.com/vuejs/core/issues/11771)\n* **reactivity:** correctly handle method calls on user-extended arrays ([#11760](https://github.com/vuejs/core/issues/11760)) ([9817c80](https://github.com/vuejs/core/commit/9817c80187bec6a3344c74d65fac92262de0fcdd)), closes [#11759](https://github.com/vuejs/core/issues/11759)\n* **runtime-dom:** avoid unnecessary prop patch for checkbox ([#11657](https://github.com/vuejs/core/issues/11657)) ([c3ce9fe](https://github.com/vuejs/core/commit/c3ce9fe3d8fc27d864ce7148cd36da882cfc21ab)), closes [#11647](https://github.com/vuejs/core/issues/11647)\n* **runtime-dom:** prevent unnecessary DOM update from v-model ([#11656](https://github.com/vuejs/core/issues/11656)) ([b1be9bd](https://github.com/vuejs/core/commit/b1be9bd64f2c7c4286fecb25bad5d5edd49efce9)), closes [#11647](https://github.com/vuejs/core/issues/11647)\n* **server-renderer:** Fix call to serverPrefetch in server renderer with an async setup ([#10893](https://github.com/vuejs/core/issues/10893)) ([6039e25](https://github.com/vuejs/core/commit/6039e25e04a8c1db5821955f011d57f1615807ab))\n* **server-renderer:** render `className` during SSR ([#11722](https://github.com/vuejs/core/issues/11722)) ([52cdb0f](https://github.com/vuejs/core/commit/52cdb0f991dc154ae32a2900874d5dbc4e078565))\n* **types/defineModel:** allow getter and setter types to be unrelated ([#11699](https://github.com/vuejs/core/issues/11699)) ([fe07f70](https://github.com/vuejs/core/commit/fe07f7073617df358c2f8cbc3de433359e873c96)), closes [#11697](https://github.com/vuejs/core/issues/11697)\n\n\n\n# [3.5.0-rc.1](https://github.com/vuejs/core/compare/v3.5.0-beta.3...v3.5.0-rc.1) (2024-08-29)\n\n\n### Bug Fixes\n\n* **compiler-sfc:** skip circular tsconfig project reference ([#11680](https://github.com/vuejs/core/issues/11680)) ([9c4c2e5](https://github.com/vuejs/core/commit/9c4c2e51b045218d0c5ca64b4fb58b17d5d580cc)), closes [#11382](https://github.com/vuejs/core/issues/11382)\n* **custom-element:** handle keys set on custom elements ([#11655](https://github.com/vuejs/core/issues/11655)) ([f1d1831](https://github.com/vuejs/core/commit/f1d1831f07fe52d5681a5ec9ec310572463abf26)), closes [#11641](https://github.com/vuejs/core/issues/11641)\n* **deps:** update dependency monaco-editor to ^0.51.0 ([#11713](https://github.com/vuejs/core/issues/11713)) ([434f8a9](https://github.com/vuejs/core/commit/434f8a97c77f68aeae050e9e4e1f54f63bc4bd26))\n* **keep-alive:**  reset keep alive flag when the component is removed from include ([#11718](https://github.com/vuejs/core/issues/11718)) ([29c321b](https://github.com/vuejs/core/commit/29c321bfd33f9197244dec3d027077e63b2cdf2f)), closes [#11717](https://github.com/vuejs/core/issues/11717)\n* **reactivity:** avoid infinite recursion when mutating ref wrapped in reactive ([313e4bf](https://github.com/vuejs/core/commit/313e4bf55214ac1e334a99c329a3ba5daca4f156)), closes [#11696](https://github.com/vuejs/core/issues/11696)\n* **reactivity:** ensure watcher with once: true are properly removed from effect scope  ([#11665](https://github.com/vuejs/core/issues/11665)) ([fbc0c42](https://github.com/vuejs/core/commit/fbc0c42bcf6dea5a6ae664223fa19d4375ca39f0))\n* **runtime-dom:** setting innerHTML when patching props should go through trusted types ([d875de5](https://github.com/vuejs/core/commit/d875de54e9e03e0768fe550aa4c4886a4baf3bd7))\n* **types:** GlobalDirective / GlobalComponents should not be records ([42e8df6](https://github.com/vuejs/core/commit/42e8df62030e7f2c287d9103f045e67b34a63e3b))\n\n\n\n# [3.5.0-beta.3](https://github.com/vuejs/core/compare/v3.5.0-beta.2...v3.5.0-beta.3) (2024-08-20)\n\n\n### Bug Fixes\n\n* **reactivity:** extended methods respect reactive ([#11629](https://github.com/vuejs/core/issues/11629)) ([9de1d10](https://github.com/vuejs/core/commit/9de1d101f98bf6081f41038f6974826f190330a0)), closes [#11628](https://github.com/vuejs/core/issues/11628)\n* **runtime-core:** correct type inference for PascalCase emits ([#11579](https://github.com/vuejs/core/issues/11579)) ([d7d0371](https://github.com/vuejs/core/commit/d7d0371e74707ee601020f67de88e091cdae2673)), closes [vuejs/language-tools#4269](https://github.com/vuejs/language-tools/issues/4269)\n* **runtime-core:** ensure suspense content inherit scopeId ([#10652](https://github.com/vuejs/core/issues/10652)) ([ac2a410](https://github.com/vuejs/core/commit/ac2a410e46392db63ca4ed2db3c0fa71ebe1e855)), closes [#5148](https://github.com/vuejs/core/issues/5148)\n* **runtime-core:** pre jobs without an id should run first ([#7746](https://github.com/vuejs/core/issues/7746)) ([b332f80](https://github.com/vuejs/core/commit/b332f80f0edb018229a23b43b93bb402b6368a3c))\n* **ssr:** apply ssr props to the the fallback vnode-based branch in ssr ([#7247](https://github.com/vuejs/core/issues/7247)) ([98b83e8](https://github.com/vuejs/core/commit/98b83e86d16c635547a1e735e5fb675aea2f0f1b)), closes [#6123](https://github.com/vuejs/core/issues/6123)\n* **types/custom-element:** `defineCustomElement` with required props ([#11578](https://github.com/vuejs/core/issues/11578)) ([5e0f6d5](https://github.com/vuejs/core/commit/5e0f6d5f8fe7c4eb8f247357c3e2e281726f36db))\n* **types:** strip non-prop default values from return type of withDefaults ([#9998](https://github.com/vuejs/core/issues/9998)) ([44973bb](https://github.com/vuejs/core/commit/44973bb3e790db7d8aa7af4eda21c80cac73a8de)), closes [#9899](https://github.com/vuejs/core/issues/9899)\n* **watch:** handle errors in computed used as watch source ([#11626](https://github.com/vuejs/core/issues/11626)) ([8bcaad4](https://github.com/vuejs/core/commit/8bcaad4a32cf0f1f89e0259f6a53036620b7fe9f)), closes [#11624](https://github.com/vuejs/core/issues/11624)\n\n\n### Features\n\n* **reactivity:** base `watch`, `getCurrentWatcher`, and `onWatcherCleanup` ([#9927](https://github.com/vuejs/core/issues/9927)) ([205e5b5](https://github.com/vuejs/core/commit/205e5b5e277243c3af2c937d9bd46cf671296b72))\n\n\n### Performance Improvements\n\n* **runtime-core:** use `apply` to avoid spreading. ([#5985](https://github.com/vuejs/core/issues/5985)) ([bb6babc](https://github.com/vuejs/core/commit/bb6babca8f206615d4e246457cd54d21bb3bc5a4))\n\n\n\n# [3.5.0-beta.2](https://github.com/vuejs/core/compare/v3.5.0-beta.1...v3.5.0-beta.2) (2024-08-15)\n\n\n### Bug Fixes\n\n* **build:** revert entities to 4.5 to avoid runtime resolution errors ([e9e0815](https://github.com/vuejs/core/commit/e9e08155bf8d00c3327ed7371330eb2ae467e560)), closes [#11603](https://github.com/vuejs/core/issues/11603)\n* **compiler-core:** use ast-based check for function expressions when possible ([5861229](https://github.com/vuejs/core/commit/58612294757480974e667652ede5bbcf72b1089d)), closes [#11615](https://github.com/vuejs/core/issues/11615)\n* **compiler-sfc:** fix prefixIdentifier default value ([3d6f015](https://github.com/vuejs/core/commit/3d6f01571b3fb61b32da599d0419eff4e3ebb231))\n* **compiler-sfc:** handle keyof operator with index object ([#11581](https://github.com/vuejs/core/issues/11581)) ([fe00815](https://github.com/vuejs/core/commit/fe008152c0612ff3ecc7ad88e7e66a06b1b2bc3f))\n* **custom-element:** keep instance.isCE for backwards compat ([e19fc27](https://github.com/vuejs/core/commit/e19fc270428b59456fee43224990138c4d6ccb2d))\n* **deps:** update dependency postcss to ^8.4.41 ([#11585](https://github.com/vuejs/core/issues/11585)) ([4c4e12a](https://github.com/vuejs/core/commit/4c4e12ae28d67d616924b0601e68adc551959971))\n* **keep-alive:** ensure include/exclude regexp work with global flag ([#11595](https://github.com/vuejs/core/issues/11595)) ([3653bc0](https://github.com/vuejs/core/commit/3653bc0f45d6fedf84e29b64ca52584359c383c0))\n* **reactivity:** ensure extended method arguments are not lost ([#11574](https://github.com/vuejs/core/issues/11574)) ([4085def](https://github.com/vuejs/core/commit/4085def1bae42d01ee3c22c731cc4a02096464ee)), closes [#11570](https://github.com/vuejs/core/issues/11570)\n* **reactivity:** sync watch should be executed correctly ([#11589](https://github.com/vuejs/core/issues/11589)) ([3bda3e8](https://github.com/vuejs/core/commit/3bda3e83fd9e2fbe451a1c79dae82ff6a7467683)), closes [#11577](https://github.com/vuejs/core/issues/11577)\n* **types/computed:** ensure type safety for `WritableComputedRef` ([#11608](https://github.com/vuejs/core/issues/11608)) ([5cf5a16](https://github.com/vuejs/core/commit/5cf5a1620d9a97382d386c277265d9dd051fe484))\n* **types:** add fallback stub for DOM types when DOM lib is absent ([#11598](https://github.com/vuejs/core/issues/11598)) ([fee6697](https://github.com/vuejs/core/commit/fee669764fbf475adce9e47a7a73b4937ab31ffc))\n\n\n### Features\n\n* **deprecated:** remove deprecated parseExpressions option ([#11597](https://github.com/vuejs/core/issues/11597)) ([4e7d5db](https://github.com/vuejs/core/commit/4e7d5db4d276a5d4aaf3af7d43cfd28c171db307))\n\n\n\n# [3.5.0-beta.1](https://github.com/vuejs/core/compare/v3.4.37...v3.5.0-beta.1) (2024-08-08)\n\n\n### Bug Fixes\n\n* **custom-element:** delay mounting of custom elements with async parent ([37ccb9b](https://github.com/vuejs/core/commit/37ccb9b9a0e4381f9465e0fc6459609003030da4)), closes [#8127](https://github.com/vuejs/core/issues/8127) [#9341](https://github.com/vuejs/core/issues/9341) [#9351](https://github.com/vuejs/core/issues/9351) [#9351](https://github.com/vuejs/core/issues/9351)\n* **custom-element:** delete prop on attribute removal ([506c4c5](https://github.com/vuejs/core/commit/506c4c53fdf9766c2ce9517ad58d501ef6b1b9de)), closes [#11276](https://github.com/vuejs/core/issues/11276)\n* **custom-element:** ignore scoped id ([7f2c505](https://github.com/vuejs/core/commit/7f2c505f92026408a8262ba9b5104a465be19446))\n* **custom-element:** reflect prop default value on custom element ([63689ed](https://github.com/vuejs/core/commit/63689ed77601d5f9b78540f810612806c3a5de15)), closes [#9006](https://github.com/vuejs/core/issues/9006) [#10537](https://github.com/vuejs/core/issues/10537)\n* **custom-element:** support early-set domProps for async custom elements ([a07e7bf](https://github.com/vuejs/core/commit/a07e7bf5536a6b3db70ba9bb1c3f366dac1bf5a0)), closes [#11081](https://github.com/vuejs/core/issues/11081) [#11082](https://github.com/vuejs/core/issues/11082)\n* **types/custome-element:** `defineCustomElement` props inference with array emits ([#11384](https://github.com/vuejs/core/issues/11384)) ([e94b01b](https://github.com/vuejs/core/commit/e94b01bd8a1ec740eddc823839ab2627b307c1b0)), closes [#11353](https://github.com/vuejs/core/issues/11353)\n* **types:** allow using InjectionKey as valid property key ([321d807](https://github.com/vuejs/core/commit/321d80758c42fccbd39ecbb63f1a4f6632a1580a)), closes [#5089](https://github.com/vuejs/core/issues/5089)\n\n\n### Features\n\n* **custom-element:** expose this.$host in Options API ([1ef8f46](https://github.com/vuejs/core/commit/1ef8f46af0cfdec2fed66376772409e0aa25ad50))\n* **custom-element:** inject child components styles to custom element shadow root ([#11517](https://github.com/vuejs/core/issues/11517)) ([56c76a8](https://github.com/vuejs/core/commit/56c76a8b05c45f782ed3a16ec77c6292b71a17f1)), closes [#4662](https://github.com/vuejs/core/issues/4662) [#7941](https://github.com/vuejs/core/issues/7941) [#7942](https://github.com/vuejs/core/issues/7942)\n* **custom-element:** support configurable app instance in defineCustomElement ([6758c3c](https://github.com/vuejs/core/commit/6758c3cd0427f97394d95168c655dae3b7fa62cd)), closes [#4356](https://github.com/vuejs/core/issues/4356) [#4635](https://github.com/vuejs/core/issues/4635)\n* **custom-element:** support css `:host` selector by applying css vars on host element ([#8830](https://github.com/vuejs/core/issues/8830)) ([03a9ea2](https://github.com/vuejs/core/commit/03a9ea2b88df0842a820e09f7445c4b9189e3fcb)), closes [#8826](https://github.com/vuejs/core/issues/8826)\n* **custom-element:** support emit with options ([e181bff](https://github.com/vuejs/core/commit/e181bff6dc39d5cef92000c10291243c7d6e4d08)), closes [#7605](https://github.com/vuejs/core/issues/7605)\n* **custom-element:** support for expose on customElement ([#6256](https://github.com/vuejs/core/issues/6256)) ([af838c1](https://github.com/vuejs/core/commit/af838c1b5ec23552e52e64ffa7db0eb0246c3624)), closes [#5540](https://github.com/vuejs/core/issues/5540)\n* **custom-element:** support nonce option for injected style tags ([bb4a02a](https://github.com/vuejs/core/commit/bb4a02a70c30e739a3c705b3d96d09258d7d7ded)), closes [#6530](https://github.com/vuejs/core/issues/6530)\n* **custom-element:** support passing custom-element-specific options via 2nd argument of defineCustomElement ([60a88a2](https://github.com/vuejs/core/commit/60a88a2b129714186cf6ba66f30f31d733d0311e))\n* **custom-element:** support shadowRoot: false in defineCustomElement() ([37d2ce5](https://github.com/vuejs/core/commit/37d2ce5d8e0fac4a00064f02b05f91f69b2d5d5e)), closes [#4314](https://github.com/vuejs/core/issues/4314) [#4404](https://github.com/vuejs/core/issues/4404)\n* **custom-element:** useHost() helper ([775103a](https://github.com/vuejs/core/commit/775103af37df69d34c79f12c4c1776c47d07f0a0))\n* **custom-element:** useShadowRoot() helper ([5a1a89b](https://github.com/vuejs/core/commit/5a1a89bd6178cc2f84ba91da7d72aee4c6ec1282)), closes [#6113](https://github.com/vuejs/core/issues/6113) [#8195](https://github.com/vuejs/core/issues/8195)\n* **hydration:** allow fine tuning of lazy hydration strategy triggers ([#11530](https://github.com/vuejs/core/issues/11530)) ([261c8b1](https://github.com/vuejs/core/commit/261c8b111d046204bd22392a8b920e3c3d4def48))\n* **reactivity/watch:** add pause/resume for ReactiveEffect, EffectScope, and WatchHandle ([#9651](https://github.com/vuejs/core/issues/9651)) ([267093c](https://github.com/vuejs/core/commit/267093c31490050bfcf3ff2b30a2aefee2dad582))\n* **reactivity:** store value cache on CustomRefs impls ([#11539](https://github.com/vuejs/core/issues/11539)) ([e044b6e](https://github.com/vuejs/core/commit/e044b6e737efc9433d1d84590036b82280da6292))\n* **runtime-dom:** Trusted Types compatibility ([#10844](https://github.com/vuejs/core/issues/10844)) ([6d4eb94](https://github.com/vuejs/core/commit/6d4eb94853ed1b2b1675bdd7d5ba9c75cc6daed5))\n* support specifying allowed keys via generic argument in useTemplateRef() ([1fbfa69](https://github.com/vuejs/core/commit/1fbfa6962b48634ff60837084b82dd57f215c109))\n* **types:** allow computed getter and setter types to be unrelated ([#11472](https://github.com/vuejs/core/issues/11472)) ([a01675e](https://github.com/vuejs/core/commit/a01675ef8f99b5acd6832c53051f4415b18609f2)), closes [#7271](https://github.com/vuejs/core/issues/7271)\n* **types:** export `MultiWatchSources` type ([#9563](https://github.com/vuejs/core/issues/9563)) ([998dca5](https://github.com/vuejs/core/commit/998dca59f140420280803233f41707580688562c))\n* **types:** provide internal options for using refs type in language tools ([#11492](https://github.com/vuejs/core/issues/11492)) ([5ffd1a8](https://github.com/vuejs/core/commit/5ffd1a89455807d5069eb2c28eba0379641dca76))\n* **watch:** support passing number to `deep` option to control the watch depth ([#9572](https://github.com/vuejs/core/issues/9572)) ([22f7d96](https://github.com/vuejs/core/commit/22f7d96757956ebe0baafe52256aa327908cc51c))\n\n\n\n# [3.5.0-alpha.5](https://github.com/vuejs/core/compare/v3.4.35...v3.5.0-alpha.5) (2024-07-31)\n\n\n### Features\n\n* **hydration:** support suppressing hydration mismatch via data-allow-mismatch ([94fb2b8](https://github.com/vuejs/core/commit/94fb2b8106a66bcca1a3f922a246a29fdd1274b1))\n* lazy hydration strategies for async components ([#11458](https://github.com/vuejs/core/issues/11458)) ([d14a11c](https://github.com/vuejs/core/commit/d14a11c1cdcee88452f17ce97758743c863958f4))\n\n\n\n# [3.5.0-alpha.4](https://github.com/vuejs/core/compare/v3.4.34...v3.5.0-alpha.4) (2024-07-24)\n\n### Bug Fixes\n\n* **suspense/hydration:** fix hydration timing of async component inside suspense ([1b8e197](https://github.com/vuejs/core/commit/1b8e197a5b65d67a9703b8511786fb81df9aa7cc)), closes [#6638](https://github.com/vuejs/core/issues/6638)\n* **useId:** properly mark async boundary for already resolved async component ([cd28172](https://github.com/vuejs/core/commit/cd281725781ada2ab279e919031ae307e146a9d9))\n\n\n\n# [3.5.0-alpha.3](https://github.com/vuejs/core/compare/v3.4.33...v3.5.0-alpha.3) (2024-07-19)\n\n\n### Bug Fixes\n\n* **build:** enable SSR branches in esm-browser builds ([b14cd9a](https://github.com/vuejs/core/commit/b14cd9a68bab082332b0169be075be357be076ca))\n* **compiler-core:** change node hoisting to caching per instance ([#11067](https://github.com/vuejs/core/issues/11067)) ([cd0ea0d](https://github.com/vuejs/core/commit/cd0ea0d479a276583fa181d8ecbc97fb0e4a9dce)), closes [#5256](https://github.com/vuejs/core/issues/5256) [#9219](https://github.com/vuejs/core/issues/9219) [#10959](https://github.com/vuejs/core/issues/10959)\n* **compiler-sfc:** should properly walk destructured props when reactive destructure is not enabled ([0fd6193](https://github.com/vuejs/core/commit/0fd6193def2380916eb51a118f37f2d9ec2ace23)), closes [#11325](https://github.com/vuejs/core/issues/11325)\n* **types:** respect props with default on instance type when using __typeProps ([96e4738](https://github.com/vuejs/core/commit/96e473833422342c5ca371ae1aeb186dec9a55e3))\n\n\n### Features\n\n* **runtime-core:** useTemplateRef() ([3ba70e4](https://github.com/vuejs/core/commit/3ba70e49b5856c53611c314d4855d679a546a7df))\n* **runtime-core:** useId() and app.config.idPrefix ([#11404](https://github.com/vuejs/core/issues/11404)) ([73ef156](https://github.com/vuejs/core/commit/73ef1561f6905d69f968c094d0180c61824f1247))\n* **runtime-core:** add app.config.throwUnhandledErrorInProduction ([f476b7f](https://github.com/vuejs/core/commit/f476b7f030f2dd427ca655fcea36f4933a4b4da0)), closes [#7876](https://github.com/vuejs/core/issues/7876)\n* **teleport:** support deferred Teleport ([#11387](https://github.com/vuejs/core/issues/11387)) ([59a3e88](https://github.com/vuejs/core/commit/59a3e88903b10ac2278170a44d5a03f24fef23ef)), closes [#2015](https://github.com/vuejs/core/issues/2015) [#11386](https://github.com/vuejs/core/issues/11386)\n* **compiler-core:** support `Symbol` global in template expressions ([#9069](https://github.com/vuejs/core/issues/9069)) ([a501a85](https://github.com/vuejs/core/commit/a501a85a7c910868e01a5c70a2abea4e9d9e87f3))\n* **types:** export more emit related types ([#11017](https://github.com/vuejs/core/issues/11017)) ([189573d](https://github.com/vuejs/core/commit/189573dcee2a16bd3ed36ff5589d43f535e5e733))\n\n\n\n# [3.5.0-alpha.2](https://github.com/vuejs/core/compare/v3.4.26...v3.5.0-alpha.2) (2024-05-04)\n\n\n### Bug Fixes\n\n* **types:** fix app.component() typing with inline defineComponent ([908f70a](https://github.com/vuejs/core/commit/908f70adc06038d1ea253d96f4024367f4a7545d)), closes [#10843](https://github.com/vuejs/core/issues/10843)\n* **types:** fix compat with generated types that rely on CreateComponentPublicInstance ([c146186](https://github.com/vuejs/core/commit/c146186396d0c1a65423b8c9a21251c5a6467336)), closes [#10842](https://github.com/vuejs/core/issues/10842)\n* **types:** props in defineOptions type should be optional ([124c4ca](https://github.com/vuejs/core/commit/124c4cac833a28ae9bc8edc576c1d0c7c41f5985)), closes [#10841](https://github.com/vuejs/core/issues/10841)\n\n\n### Features\n\n* **runtime-core:** add app.onUnmount() for registering cleanup functions ([#4619](https://github.com/vuejs/core/issues/4619)) ([582a3a3](https://github.com/vuejs/core/commit/582a3a382b1adda565bac576b913a88d9e8d7a9e)), closes [#4516](https://github.com/vuejs/core/issues/4516)\n\n\n\n# [3.5.0-alpha.1](https://github.com/vuejs/core/compare/v3.4.25...v3.5.0-alpha.1) (2024-04-29)\n\n\n### Bug Fixes\n\n* **reactivity:** fix call sequence of ontrigger in effect ([#10501](https://github.com/vuejs/core/issues/10501)) ([28841fe](https://github.com/vuejs/core/commit/28841fee43a45c37905c2c1ed9ace23067539045))\n\n\n### Features\n\n* **compiler-sfc:** enable reactive props destructure by default ([d2dac0e](https://github.com/vuejs/core/commit/d2dac0e359c47d1ed0aa77eda488e76fd6466d2d))\n* **reactivity:** `onEffectCleanup` API ([2cc5615](https://github.com/vuejs/core/commit/2cc5615590de77126e8df46136de0240dbde5004)), closes [#10173](https://github.com/vuejs/core/issues/10173)\n* **reactivity:** add failSilently argument for onScopeDispose ([9a936aa](https://github.com/vuejs/core/commit/9a936aaec489c79433a32791ecf5ddb1739a62bd))\n* **transition:** support directly nesting Teleport inside Transition ([#6548](https://github.com/vuejs/core/issues/6548)) ([0e6e3c7](https://github.com/vuejs/core/commit/0e6e3c7eb0e5320b7c1818e025cb4a490fede9c0)), closes [#5836](https://github.com/vuejs/core/issues/5836)\n* **types:** provide internal options for directly using user types in language tools ([#10801](https://github.com/vuejs/core/issues/10801)) ([75c8cf6](https://github.com/vuejs/core/commit/75c8cf63a1ef30ac84f91282d66ad3f57c6612e9))\n\n\n### Performance Improvements\n\n* **reactivity:** optimize array tracking ([#9511](https://github.com/vuejs/core/issues/9511)) ([70196a4](https://github.com/vuejs/core/commit/70196a40cc078f50fcc1110c38c06fbcc70b205e)), closes [#4318](https://github.com/vuejs/core/issues/4318)\n\n\n\n## Previous Changelogs\n\n### 3.4.x (2023-10-28 - 2024-08-15)\n\nSee [3.4 changelog](./changelogs/CHANGELOG-3.4.md)\n\n### 3.3.x (2023-02-05 - 2023-12-29)\n\nSee [3.3 changelog](./changelogs/CHANGELOG-3.3.md)\n\n### 3.2.x (2021-07-16 - 2023-02-02)\n\nSee [3.2 changelog](./changelogs/CHANGELOG-3.2.md)\n\n### 3.1.x (2021-05-08 - 2021-07-16)\n\nSee [3.1 changelog](./changelogs/CHANGELOG-3.1.md)\n\n### 3.0.x (2019-12-20 - 2021-04-01)\n\nSee [3.0 changelog](./changelogs/CHANGELOG-3.0.md)\n"
  },
  {
    "path": "FUNDING.json",
    "content": "{\n  \"drips\": {\n    \"ethereum\": {\n      \"ownedBy\": \"0x5393BdeA2a020769256d9f337B0fc81a2F64850A\"\n    }\n  }\n}\n"
  },
  {
    "path": "LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2018-present, Yuxi (Evan) You and Vue 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"
  },
  {
    "path": "README.md",
    "content": "# vuejs/core [![npm](https://img.shields.io/npm/v/vue.svg)](https://www.npmjs.com/package/vue) [![build status](https://github.com/vuejs/core/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/vuejs/core/actions/workflows/ci.yml) [![Download](https://img.shields.io/npm/dm/vue)](https://www.npmjs.com/package/vue)\n\n## Getting Started\n\nPlease follow the documentation at [vuejs.org](https://vuejs.org/)!\n\n## Sponsors\n\nVue.js is an MIT-licensed open source project with its ongoing development made possible entirely by the support of these awesome [backers](https://github.com/vuejs/core/blob/main/BACKERS.md). If you'd like to join them, please consider [sponsoring Vue's development](https://vuejs.org/sponsor/).\n\n<p align=\"center\">\n  <h3 align=\"center\">Special Sponsor</h3>\n</p>\n\n<p align=\"center\">\n  <a target=\"_blank\" href=\"https://betterstack.com/\">\n  <img alt=\"special sponsor\" src=\"https://automation.vuejs.org/images/better_stack.png\" width=\"300\">\n  </a>\n</p>\n\n<p align=\"center\">\n  <a target=\"_blank\" href=\"https://vuejs.org/sponsor/#current-sponsors\">\n    <img alt=\"sponsors\" src=\"https://sponsors.vuejs.org/sponsors.svg?v3\">\n  </a>\n</p>\n\n## Questions\n\nFor questions and support please use [the official forum](https://forum.vuejs.org) or [community chat](https://chat.vuejs.org/). The issue list of this repo is **exclusively** for bug reports and feature requests.\n\n## Issues\n\nPlease make sure to respect issue requirements and use [the new issue helper](https://new-issue.vuejs.org/) when opening an issue. Issues not conforming to the guidelines may be closed immediately.\n\n## Stay In Touch\n\n- [X](https://x.com/vuejs)\n- [Bluesky](https://bsky.app/profile/vuejs.org)\n- [Blog](https://blog.vuejs.org/)\n- [Job Board](https://vuejobs.com/?ref=vuejs)\n\n## Contribution\n\nPlease make sure to read the [Contributing Guide](https://github.com/vuejs/core/blob/main/.github/contributing.md) before making a pull request. If you have a Vue-related project/component/tool, add it with a pull request to [this curated list](https://github.com/vuejs/awesome-vue)!\n\nThank you to all the people who already contributed to Vue!\n\n<a href=\"https://github.com/vuejs/core/graphs/contributors\"><img src=\"https://opencollective.com/vuejs/contributors.svg?width=890&limit=500\" /></a>\n\n<sub>_Note: Showing the first 500 contributors only due to GitHub image size limitations_</sub>\n\n## License\n\n[MIT](https://opensource.org/licenses/MIT)\n\nCopyright (c) 2013-present, Yuxi (Evan) You\n"
  },
  {
    "path": "SECURITY.md",
    "content": "# Reporting a Vulnerability\n\nTo report a vulnerability, please email security@vuejs.org.\n\nWhile the discovery of new vulnerabilities is rare, we also recommend always using the latest versions of Vue and its official companion libraries to ensure your application remains as secure as possible.\n\nPlease note that we do not consider XSS via template expressions a valid attack vector, because it can only happen if the user intentionally uses untrusted content as template compilation source. This is similar to knowingly pasting untrusted scripts into a browser console. We explicitly warn users against using untrusted content as template compilation source in our documentation.\n\n## Security Hall of Fame\n\nWe would like to thank the following security researchers for responsibly disclosing security issues to us.\n\n- Jeet Pal - [@jeetpal2007](https://github.com/jeetpal2007) | [Email](mailto:jeetpal2007@gmail.com) | [LinkedIn](https://in.linkedin.com/in/jeet-pal-22601a290)\n- Mix - [@mnixry](https://github.com/mnixry)\n- Aviv Keller - [@RedYetiDev](https://github.com/redyetidev) | [LinkedIn](https://www.linkedin.com/in/redyetidev) <redyetidev@gmail.com>\n- Ben Zimmermann - [@bzzimmy](https://github.com/bzzimmy) | [Email](mailto:kernelrocks@proton.me)\n"
  },
  {
    "path": "changelogs/CHANGELOG-3.0.md",
    "content": "## [3.0.11](https://github.com/vuejs/core/compare/v3.0.10...v3.0.11) (2021-04-01)\n\n### Bug Fixes\n\n- **compiler-sfc:** fix wrong scopeId for nested `<script setup>` components ([7f7dcc9](https://github.com/vuejs/core/commit/7f7dcc9f7d9a036df366453e2bf228f29c0bef82))\n- **runtime-core:** fix render function + optimized slot edge case ([#3523](https://github.com/vuejs/core/issues/3523)) ([995d76b](https://github.com/vuejs/core/commit/995d76bd128c3f4d264f10212f2a8e8946f58a62)), closes [#2893](https://github.com/vuejs/core/issues/2893)\n- **runtime-core:** fix v-on object kebab-case event emit matching ([c1cd42e](https://github.com/vuejs/core/commit/c1cd42e627bdeb561d54e64ea5fea87ccbbae637)), closes [#3527](https://github.com/vuejs/core/issues/3527)\n\n## [3.0.10](https://github.com/vuejs/core/compare/v3.0.9...v3.0.10) (2021-03-31)\n\n### Bug Fixes\n\n- **compiler-core:** allow PascalCase dynamic component tag usage ([#3508](https://github.com/vuejs/core/issues/3508)) ([555b016](https://github.com/vuejs/core/commit/555b016dcb3b347a1d8b3d14df74c175115adb0b)), closes [#3507](https://github.com/vuejs/core/issues/3507)\n- **compiler-core:** properly transform replaced nodes ([#2927](https://github.com/vuejs/core/issues/2927)) ([0fe567a](https://github.com/vuejs/core/commit/0fe567abfcb7c685954231995033d04c86b6ef8a))\n- **compiler-sfc:** do not resolve assets from setup bindings ([f5827fd](https://github.com/vuejs/core/commit/f5827fdf781c97234e9f82095e5e0cdadd404338)), closes [#3270](https://github.com/vuejs/core/issues/3270) [#3275](https://github.com/vuejs/core/issues/3275)\n- **compiler-sfc:** fix function scope variable declaration marking ([69b4727](https://github.com/vuejs/core/commit/69b4727204256795d37a29930be33ab4f864af38))\n- **compiler-sfc:** fix missing whitespace issue in srcsets ([#3132](https://github.com/vuejs/core/issues/3132)) ([42b68c7](https://github.com/vuejs/core/commit/42b68c773d1e1a04af223eb241329df50bac1d15)), closes [#3069](https://github.com/vuejs/core/issues/3069)\n- **compiler-sfc:** support proper type arguments for defineEmit helper ([bb8cdca](https://github.com/vuejs/core/commit/bb8cdcad9f91f099c12ad78afacfc909e6269a7c)), closes [#2874](https://github.com/vuejs/core/issues/2874)\n- **reactivity:** should not trigger when setting value to same proxy ([#2904](https://github.com/vuejs/core/issues/2904)) ([c61e767](https://github.com/vuejs/core/commit/c61e7674221cd51df87aafc92367273c8815af6c))\n- **runtime-core:** avoid unmount teleport's children multiple times ([#3499](https://github.com/vuejs/core/issues/3499)) ([3736496](https://github.com/vuejs/core/commit/3736496006485e61614bef285ea89ea2a33134c4)), closes [#3497](https://github.com/vuejs/core/issues/3497)\n- **runtime-core:** fix dev fragment root flag check ([9cf7525](https://github.com/vuejs/core/commit/9cf75258c866bbdb2023c066cc3579fb86f15f40))\n- **runtime-dom:** fix event listeners call in firefox <= 53 ([#3501](https://github.com/vuejs/core/issues/3501)) ([33ba0e3](https://github.com/vuejs/core/commit/33ba0e3229de02b7f4dda9465e4df16e177ea8cc)), closes [#3485](https://github.com/vuejs/core/issues/3485)\n- **ssr:** fix scopeId inheritance across mixed parent chain ([5e54081](https://github.com/vuejs/core/commit/5e54081d5bfd0412fe4946c80b5c538f2afd7fb8)), closes [#3513](https://github.com/vuejs/core/issues/3513)\n- **types:** add a type-only differentiator to assist Mixin's type infer ([#3481](https://github.com/vuejs/core/issues/3481)) ([5db2b14](https://github.com/vuejs/core/commit/5db2b141dcf20af5c762f7e40580904c43298764)), closes [#3468](https://github.com/vuejs/core/issues/3468)\n- **types/tsx:** make JSX.Element extend VNode ([#3171](https://github.com/vuejs/core/issues/3171)) ([4f26835](https://github.com/vuejs/core/commit/4f26835dac5c345e6ccb2e2c2844f3560daa1de3))\n\n### Performance Improvements\n\n- **compiler-sfc:** skip srcset transform if all candidates are external ([b39208c](https://github.com/vuejs/core/commit/b39208cf06a56b115016be18d5ee368a8f9dff74))\n- **runtime-core:** optimize the performance of getTypeIndex ([#3206](https://github.com/vuejs/core/issues/3206)) ([2e50acf](https://github.com/vuejs/core/commit/2e50acfbb89c29a071765d7f3967d2ccaf14f375))\n\n## [3.0.9](https://github.com/vuejs/core/compare/v3.0.8...v3.0.9) (2021-03-27)\n\n### Bug Fixes\n\n- **compiler-core:** fix slot source location ([#3494](https://github.com/vuejs/core/issues/3494)) ([e752bdd](https://github.com/vuejs/core/commit/e752bddb33b8d150e9f071f15b91a39d326522a3))\n- **runtime-core:** fix kebab-case prop required warning ([2121c32](https://github.com/vuejs/core/commit/2121c32e228376c01de4335e2fcc645b7581cd4b)), closes [#3495](https://github.com/vuejs/core/issues/3495) [#3363](https://github.com/vuejs/core/issues/3363)\n- **runtime-core:** remove dev-only props property from setup context for consistency ([#3492](https://github.com/vuejs/core/issues/3492)) ([4549e65](https://github.com/vuejs/core/commit/4549e65baea54bfd10116241a6a5eba91ec3f632))\n- ensure backwards compat for pre-compiled sfc components ([37c1709](https://github.com/vuejs/core/commit/37c17091fddb26d54e080d2867102d017f09171f)), closes [#3493](https://github.com/vuejs/core/issues/3493)\n\n## [3.0.8](https://github.com/vuejs/core/compare/v3.0.7...v3.0.8) (2021-03-26)\n\n### Bug Fixes\n\n- **compiler:** properly bail stringfication for nested slot elements ([f74b16c](https://github.com/vuejs/core/commit/f74b16ccfe42abddf6abfa6105900ad9b8124a96))\n- **compiler-core:** allow unicode to appear in identifiers ([#3443](https://github.com/vuejs/core/issues/3443)) ([ebedccc](https://github.com/vuejs/core/commit/ebedcccdc04d8cda40f7a3b69354acfdda265c74)), closes [#3440](https://github.com/vuejs/core/issues/3440)\n- **compiler-core:** avoid generating useless createVNode helper ([#2938](https://github.com/vuejs/core/issues/2938)) ([7715c49](https://github.com/vuejs/core/commit/7715c49af92f5db0e4eef52d983850c08439d87c)), closes [#2739](https://github.com/vuejs/core/issues/2739)\n- **compiler-core:** detect v-if branch root with comment as dev fragment ([#2785](https://github.com/vuejs/core/issues/2785)) ([4bf7ba1](https://github.com/vuejs/core/commit/4bf7ba19bf6b1a6c242090d512c91e1bf8c7c8cc)), closes [#2780](https://github.com/vuejs/core/issues/2780)\n- **compiler-core:** fix the detection of forwarded slots with v-if or v-for ([#3353](https://github.com/vuejs/core/issues/3353)) ([602b58e](https://github.com/vuejs/core/commit/602b58ebd1923dd48669755d5f5b67c5478cc625)), closes [#3347](https://github.com/vuejs/core/issues/3347)\n- **compiler-core:** should not condense whitespace in RCDATA text mode ([#3482](https://github.com/vuejs/core/issues/3482)) ([b4b8215](https://github.com/vuejs/core/commit/b4b82159e2175d27f7d1f2641d262269f981fc86)), closes [#3479](https://github.com/vuejs/core/issues/3479)\n- **compiler-dom:** stringifyStatic should remove attribute bindings with `null` value ([#3477](https://github.com/vuejs/core/issues/3477)) ([ca6aa01](https://github.com/vuejs/core/commit/ca6aa01181dd15e2ab76d89538cf898221f927cd)), closes [#3475](https://github.com/vuejs/core/issues/3475)\n- **compiler-sfc:** scope Id should not be attached to [@keyframe](https://github.com/keyframe) breakpoint rules ([#3308](https://github.com/vuejs/core/issues/3308)) ([6cb9475](https://github.com/vuejs/core/commit/6cb94752b0354117669de94f81c5195ec8c7f40c)), closes [#3304](https://github.com/vuejs/core/issues/3304)\n- **compiler-sfc:** should not rewrite scope variable ([#3449](https://github.com/vuejs/core/issues/3449)) ([bbc5fe6](https://github.com/vuejs/core/commit/bbc5fe6a9716efe87fdb4c4ac51fcdc3bd541904)), closes [#3445](https://github.com/vuejs/core/issues/3445)\n- **compiler-ssr:** keep the order of imports expression for the fallback branch of SSR ([#3448](https://github.com/vuejs/core/issues/3448)) ([49f4072](https://github.com/vuejs/core/commit/49f4072c83c06a66e2b7a334d8dedabd1b433ca9)), closes [#3447](https://github.com/vuejs/core/issues/3447)\n- **component:** prioritize registered component over implicit self-reference via filename ([abd129d](https://github.com/vuejs/core/commit/abd129d845951737c335a80a8af6cf7b0df2f74d)), closes [#2827](https://github.com/vuejs/core/issues/2827)\n- **hydration:** handle camel-case tag name when performing match assertion ([#3247](https://github.com/vuejs/core/issues/3247)) ([9036f88](https://github.com/vuejs/core/commit/9036f88d8304a3455265f1ecd86ec8f4a5ea4715)), closes [#3243](https://github.com/vuejs/core/issues/3243)\n- **KeepAlive:** adapt keepalive for ssr ([#3259](https://github.com/vuejs/core/issues/3259)) ([e8e9b00](https://github.com/vuejs/core/commit/e8e9b00f81ed42434afd92f84101e7a14d70a23c)), closes [#3255](https://github.com/vuejs/core/issues/3255)\n- **reactivity:** ensure computed can be wrapped by readonly ([41e02f0](https://github.com/vuejs/core/commit/41e02f0fac069c93c94438741517e713f3c94215)), closes [#3376](https://github.com/vuejs/core/issues/3376)\n- **reactivity:** ensure that shallow and normal proxies are tracked separately (close [#2843](https://github.com/vuejs/core/issues/2843)) ([#2851](https://github.com/vuejs/core/issues/2851)) ([22cc4a7](https://github.com/vuejs/core/commit/22cc4a76592cfe336e75e2fa0c05232ae1f0f149))\n- **reactivity:** fix shallow readonly behavior for collections ([#3003](https://github.com/vuejs/core/issues/3003)) ([68de9f4](https://github.com/vuejs/core/commit/68de9f408a2e61a5726a4a0d03b026cba451c5bd)), closes [#3007](https://github.com/vuejs/core/issues/3007)\n- **rumtime-core:** custom dom props should be cloned when cloning a hoisted DOM ([#3080](https://github.com/vuejs/core/issues/3080)) ([5dbe834](https://github.com/vuejs/core/commit/5dbe8348581dacd7a3594a9b0055ce350ce8e5bf)), closes [#3072](https://github.com/vuejs/core/issues/3072)\n- **runtime-core:** cache props default values to avoid unnecessary watcher trigger ([#3474](https://github.com/vuejs/core/issues/3474)) ([44166b4](https://github.com/vuejs/core/commit/44166b43d9be1062f79612880f71284049bcab0b)), closes [#3471](https://github.com/vuejs/core/issues/3471)\n- **runtime-core:** ensure only skip unflushed job ([#3406](https://github.com/vuejs/core/issues/3406)) ([bf34e33](https://github.com/vuejs/core/commit/bf34e33c909da89681b9c5004cdf04ab198ec5a7))\n- **runtime-core:** fix async component ref handling ([#3191](https://github.com/vuejs/core/issues/3191)) ([7562e72](https://github.com/vuejs/core/commit/7562e72c2b58a5646bd4fbd9adea11eb884fe140)), closes [#3188](https://github.com/vuejs/core/issues/3188)\n- **runtime-core:** fix erroneous emits warnings w/ mixins ([60d777d](https://github.com/vuejs/core/commit/60d777d228414515cc32526ad72a53ef070501be)), closes [#2651](https://github.com/vuejs/core/issues/2651)\n- **runtime-core:** fix warning for absent props ([#3363](https://github.com/vuejs/core/issues/3363)) ([86ceef4](https://github.com/vuejs/core/commit/86ceef43523bfbbb0a24731d3802ca6849cbefd6)), closes [#3362](https://github.com/vuejs/core/issues/3362)\n- **runtime-core:** handle error in async setup ([#2881](https://github.com/vuejs/core/issues/2881)) ([d668d48](https://github.com/vuejs/core/commit/d668d48e9e5211a49ee53361ea5b4d67ba16e0a3))\n- **runtime-core:** handle error in async watchEffect ([#3129](https://github.com/vuejs/core/issues/3129)) ([eb1fae6](https://github.com/vuejs/core/commit/eb1fae63f926435fb0eef890663d24e09d4c79e1))\n- **runtime-core:** should call chained mixins and extends ([#3040](https://github.com/vuejs/core/issues/3040)) ([b58bb16](https://github.com/vuejs/core/commit/b58bb169590297daf9df0433b413fab118f18486)), closes [#3038](https://github.com/vuejs/core/issues/3038)\n- **runtime-core:** should not cache property access during data() invocation ([#3299](https://github.com/vuejs/core/issues/3299)) ([6e88156](https://github.com/vuejs/core/commit/6e88156934a88c891fa1014c46c04a3fa1a5eaeb)), closes [#3297](https://github.com/vuejs/core/issues/3297)\n- **runtime-core:** should not track deps in pre flush watcher callbacks ([d5824b9](https://github.com/vuejs/core/commit/d5824b97c570eb9e3d689b840f098e401e458d05)), closes [#2728](https://github.com/vuejs/core/issues/2728)\n- **runtime-core:** the select tag's multiple prop should be set before the children mounting ([#3202](https://github.com/vuejs/core/issues/3202)) ([2451dd8](https://github.com/vuejs/core/commit/2451dd8ae63cc0667a234f9896b1a4f241d4cb44)), closes [#3199](https://github.com/vuejs/core/issues/3199)\n- **runtime-dom:** support mounting app to svg container ([#2929](https://github.com/vuejs/core/issues/2929)) ([8ffcde2](https://github.com/vuejs/core/commit/8ffcde2836baa41d279d9cc079f139a2e31cf6be)), closes [#2926](https://github.com/vuejs/core/issues/2926)\n- **ssr:** ensure async setup error handling work with suspense during ssr ([2e71f07](https://github.com/vuejs/core/commit/2e71f07bc1bab09ca6970b8992d05aeea9b5e9e4))\n- **ssr:** fix memory leak when vnode component render throws error ([da944cb](https://github.com/vuejs/core/commit/da944cb37987212d1b1a860b79f43a7c85814225)), closes [#3100](https://github.com/vuejs/core/issues/3100)\n- **ssr:** properly update currentRenderingInstance state during ssr ([8c3c14a](https://github.com/vuejs/core/commit/8c3c14a0ff02bffbc37e1b069d4ff3c7e086a1d5)), closes [#2863](https://github.com/vuejs/core/issues/2863)\n- **ssr:** respect render function from extends/mixins in ssr ([#3006](https://github.com/vuejs/core/issues/3006)) ([0a583d5](https://github.com/vuejs/core/commit/0a583d5ca224d2cba878dc6b0fb8d468e658f1ef)), closes [#3004](https://github.com/vuejs/core/issues/3004)\n- **ssr:** watchEffect onInvalidate runner initialization ([#3323](https://github.com/vuejs/core/issues/3323)) ([e4b5fcc](https://github.com/vuejs/core/commit/e4b5fccd0c54a1109737ae75b3ca2bc603cb05b3)), closes [#3322](https://github.com/vuejs/core/issues/3322)\n- **ssr/hydration:** handle ending empty text node ([#3246](https://github.com/vuejs/core/issues/3246)) ([420c8f4](https://github.com/vuejs/core/commit/420c8f4580dddea9a724cfadc4cc2c272181c24d)), closes [#3245](https://github.com/vuejs/core/issues/3245)\n- **teleport:** targetAnchor should also be removed when unmounted ([#2870](https://github.com/vuejs/core/issues/2870)) ([21d1288](https://github.com/vuejs/core/commit/21d128813353fd5d5a5304f8fb885265f5163cd8))\n- **Teleport:** component with multi roots should be removed when unmounted ([#3157](https://github.com/vuejs/core/issues/3157)) ([7769513](https://github.com/vuejs/core/commit/776951315d38fb93b75892bd60a69177b4480f67)), closes [#3156](https://github.com/vuejs/core/issues/3156)\n- **Teleport:** fallback to non-optimized mode when HRM performing updates ([#3311](https://github.com/vuejs/core/issues/3311)) ([9cb21d0](https://github.com/vuejs/core/commit/9cb21d088edd097b75a038f2c11d1c921406686f)), closes [#3302](https://github.com/vuejs/core/issues/3302)\n- **transition:** toggling branches with in-out mode should be transitioned correctly ([#3109](https://github.com/vuejs/core/issues/3109)) ([67a0290](https://github.com/vuejs/core/commit/67a0290c0aa5626dbc71b66b00e7ca7755e339cb)), closes [#3104](https://github.com/vuejs/core/issues/3104)\n- **types:** allow style to be an array in JSX ([#2947](https://github.com/vuejs/core/issues/2947)) ([13c9d2c](https://github.com/vuejs/core/commit/13c9d2ca82d60652ef19fe055ecbe0d05134007b))\n- **types:** union function prop ([#3119](https://github.com/vuejs/core/issues/3119)) ([3755e60](https://github.com/vuejs/core/commit/3755e60c52adcd83e569f32c3d31d8854b4fdd8d)), closes [#3357](https://github.com/vuejs/core/issues/3357)\n- **types:** unwrap refs on public instance data ([#3319](https://github.com/vuejs/core/issues/3319)) ([2b588cf](https://github.com/vuejs/core/commit/2b588cf1bc03329576b8759c9072e3e551b739f1)), closes [#3315](https://github.com/vuejs/core/issues/3315)\n- **types/jsx:** llow tabindex to be a string ([#3476](https://github.com/vuejs/core/issues/3476)) ([e4a5712](https://github.com/vuejs/core/commit/e4a5712a33d10d3087f1c3cff0ecdf5569a84d94))\n- add display name for suspense component ([#3312](https://github.com/vuejs/core/issues/3312)) ([3b3a9a1](https://github.com/vuejs/core/commit/3b3a9a1f5225fb734d16ffe2d596f457e9c47cec))\n\n### Performance Improvements\n\n- support only attaching slot scope ids when necessary ([02cbbb7](https://github.com/vuejs/core/commit/02cbbb718ca226b087c42e6f132120931307c2a6))\n\n## [3.0.7](https://github.com/vuejs/core/compare/v3.0.6...v3.0.7) (2021-03-01)\n\n### Bug Fixes\n\n- **compiler-sfc:** handle more edge cases in default rewrite ([1dedc19](https://github.com/vuejs/core/commit/1dedc19e1f0a2039d2ab8f55af6e27034b8dcde5))\n- **deps:** pin Rollup to 2.38 ([34f354b](https://github.com/vuejs/core/commit/34f354b2a0eeb6c148ca485ae3558842814ea4d2)), closes [#3332](https://github.com/vuejs/core/issues/3332)\n- **runtime-core:** properties in methods should be writable and enumerable in DEV ([#3301](https://github.com/vuejs/core/issues/3301)) ([e3568ba](https://github.com/vuejs/core/commit/e3568bae276889cee60f4e84321a287125014e86)), closes [#3300](https://github.com/vuejs/core/issues/3300)\n- **scheduler:** ensure updates are always inserted in ascending id order ([#3184](https://github.com/vuejs/core/issues/3184)) ([45fae9d](https://github.com/vuejs/core/commit/45fae9d308e8cb9fe3304d4ca03c373ce63b2e62)), closes [#2768](https://github.com/vuejs/core/issues/2768) [#2829](https://github.com/vuejs/core/issues/2829)\n- **v-show:** v-show takes higher priority than style attribute ([#3230](https://github.com/vuejs/core/issues/3230)) ([5ad4036](https://github.com/vuejs/core/commit/5ad4036e29f75dc907e95b99a63325b855332566)), closes [#2757](https://github.com/vuejs/core/issues/2757)\n- init devtools after feature flag checks ([d0ea745](https://github.com/vuejs/core/commit/d0ea74556f74d8c503ffb7b70f41cbe2ce14db98))\n\n### Performance Improvements\n\n- **reactivity:** only call Set.add if doesn't already have value ([#3307](https://github.com/vuejs/core/issues/3307)) ([9cd9883](https://github.com/vuejs/core/commit/9cd988342cfa32ddd9479585244eb317d74c9712))\n\n## [3.0.6](https://github.com/vuejs/core/compare/v3.0.5...v3.0.6) (2021-02-24)\n\n### Bug Fixes\n\n- **compiler-core:** do not mark v-for as stable on const bindings ([734c65b](https://github.com/vuejs/core/commit/734c65badd8395a78d7beee1fc960aee418361a0)), closes [vitejs/vite#1956](https://github.com/vitejs/vite/issues/1956)\n- **compiler-dom:** ensure global build filename matches the one defined in package.json (close [#3181](https://github.com/vuejs/core/issues/3181)) ([#3185](https://github.com/vuejs/core/issues/3185)) ([96b6433](https://github.com/vuejs/core/commit/96b64335242a99432080aeb879e5c0787207a0de))\n- **compiler-dom:** fix cdn entries ([fcb6c89](https://github.com/vuejs/core/commit/fcb6c8920c6ee76f57325a178eb9280d7bae4d7c)), closes [#3181](https://github.com/vuejs/core/issues/3181) [#3185](https://github.com/vuejs/core/issues/3185)\n- **compiler-sfc:** compiler blank srcset ([#3005](https://github.com/vuejs/core/issues/3005)) ([9dc816d](https://github.com/vuejs/core/commit/9dc816d63468b0a2fa2b6123959310014e121b58))\n- **compiler-sfc:** removeSpecifier issue when removing initial imports (script-setup) ([#2729](https://github.com/vuejs/core/issues/2729)) ([6d762a8](https://github.com/vuejs/core/commit/6d762a84ca0ac9a43eb3d0ab0c7b7b17c35c9836))\n- **compiler-sfc:** the empty lang attribute should be treated as no lang specified ([#3051](https://github.com/vuejs/core/issues/3051)) ([6d5b623](https://github.com/vuejs/core/commit/6d5b62351248780663d2612a1f483f7ea9f5e5a2))\n- **compiler-sfc:** transformAssetUrls.base should not affect known module requests ([2ea9867](https://github.com/vuejs/core/commit/2ea9867398d19148b32643fa0e6523c95b9ca956))\n- **compiler-sfc:** treat const reactive() bindings as mutable ([03360ce](https://github.com/vuejs/core/commit/03360cefa1b7038174fa3c1fc3a04400b4cdbbce))\n- **compiler-ssr:** avoid duplicated asset imports merged from component slot client branch ([c69f4ea](https://github.com/vuejs/core/commit/c69f4ea857b7db8d26bbde2f80786c8212d16770)), closes [vitejs/vite#2034](https://github.com/vitejs/vite/issues/2034)\n- **devtools:** init devtools in production ([#2906](https://github.com/vuejs/core/issues/2906)) ([4d9bcb7](https://github.com/vuejs/core/commit/4d9bcb768ddc294430aedcf27155aaca292c47bd))\n- **devtools:** send instance to devtools when it's mounted instead of created ([4fecb27](https://github.com/vuejs/core/commit/4fecb27f8696fdb8f681948543ea81ea62fe43bf))\n- **docs:** change reference to passed deadline ([#2930](https://github.com/vuejs/core/issues/2930)) ([de7f9d1](https://github.com/vuejs/core/commit/de7f9d1efd7fa19a908357d3f3a706c52694d8bd))\n- **hmr:** deep clone reused hoisted trees during dev ([5a7a1b8](https://github.com/vuejs/core/commit/5a7a1b8293822219283d6e267496bec02234b0bc)), closes [vitejs/vite#2022](https://github.com/vitejs/vite/issues/2022)\n- **runtime-core:** align $parent/$root with the template ref when using expose ([#3158](https://github.com/vuejs/core/issues/3158)) ([f43a3b0](https://github.com/vuejs/core/commit/f43a3b0bebf0837223e7b8f046dad63e34cd323b))\n- **runtime-core:** allow overriding properties other than props ([#3105](https://github.com/vuejs/core/issues/3105)) ([73117f6](https://github.com/vuejs/core/commit/73117f6b5b1e36c9400248ed9e815839c49a12c8))\n- **runtime-core:** check the DEV_ROOT_FRAGMENT flag correctly in the dev environment ([#2750](https://github.com/vuejs/core/issues/2750)) ([347a879](https://github.com/vuejs/core/commit/347a8798a4c5f0b426f3ac84a01d752d823fb51b))\n- **runtime-core:** component methods should override global properties in DEV ([#3074](https://github.com/vuejs/core/issues/3074)) ([2587f36](https://github.com/vuejs/core/commit/2587f36fe311359e2e34f40e8e47d2eebfab7f42))\n- **runtime-core:** ensure app instance can be garbage collected after unmount (close [#2907](https://github.com/vuejs/core/issues/2907)) ([#2909](https://github.com/vuejs/core/issues/2909)) ([60e05ef](https://github.com/vuejs/core/commit/60e05eff232c3ddfca1c20e52f72aa36165d8a22))\n- **runtime-core:** instanceWatch should pass `this.proxy` to source as the first argument ([#2753](https://github.com/vuejs/core/issues/2753)) ([ec8fd10](https://github.com/vuejs/core/commit/ec8fd10cec61c33c7c8056413a1c609ac90e1215))\n- **runtime-dom:** ensure readonly type prop on textarea is handled patched as attribute ([#2888](https://github.com/vuejs/core/issues/2888)) ([c5d147c](https://github.com/vuejs/core/commit/c5d147c57f75ca38cc334bb27b61a8bc153494bd)), closes [#2766](https://github.com/vuejs/core/issues/2766)\n- kebab-case events are attached correctly on web components, see [#2841](https://github.com/vuejs/core/issues/2841) ([#2847](https://github.com/vuejs/core/issues/2847)) ([b302cbb](https://github.com/vuejs/core/commit/b302cbbbd3fd512f2b8afbd9c873060a40bf8e62))\n- **types:** extract the correct props type for the DateConstructor ([#2676](https://github.com/vuejs/core/issues/2676)) ([48f0d29](https://github.com/vuejs/core/commit/48f0d2944f0f9d2f556e62782fc61985897b2ed4))\n- ensure all published packages contan a LICENCE file (close [#2650](https://github.com/vuejs/core/issues/2650)) ([#2857](https://github.com/vuejs/core/issues/2857)) ([6a48d23](https://github.com/vuejs/core/commit/6a48d23749e418b44ba17cd3e85f478484fd7ffe))\n- remove superfluous spaces when normalizing class ([#3083](https://github.com/vuejs/core/issues/3083)) ([4b55142](https://github.com/vuejs/core/commit/4b551420fc058c4683219db5d75893f9fc69aa04))\n- **runtime-dom:** enable set form attr to null on form-elements ([#2840](https://github.com/vuejs/core/issues/2840)) ([#2849](https://github.com/vuejs/core/issues/2849)) ([f262438](https://github.com/vuejs/core/commit/f2624380731cc32e71523e8c2c98037e98e09319))\n- **toRef:** ref created from union typed prop can't be used in watch ([#3048](https://github.com/vuejs/core/issues/3048)) ([4ca4666](https://github.com/vuejs/core/commit/4ca4666d58ee8025570dc14f1c163bdeac9c6012))\n- should prefix `ShadowRoot` with `window.` ([#2943](https://github.com/vuejs/core/issues/2943)) ([97d6f1a](https://github.com/vuejs/core/commit/97d6f1a716045123d0e05600e64f11f92f504747))\n\n### Features\n\n- remove useless option in KeepAlive ([#3170](https://github.com/vuejs/core/issues/3170)) ([bd1240c](https://github.com/vuejs/core/commit/bd1240c1270b610c4ffcf6c32e2bbe2c9265020f))\n- **compiler-core:** support `BigInt` in template ([#2900](https://github.com/vuejs/core/issues/2900)) ([c9f94fa](https://github.com/vuejs/core/commit/c9f94fa3cfbe8fcd9ea3d49d523dfb282c468369))\n- **compiler-sfc:** upgrade to postcss 8 ([#2710](https://github.com/vuejs/core/issues/2710)) ([49bc2e4](https://github.com/vuejs/core/commit/49bc2e4db568d4f9fa2ccfe4e22c792cfc02651a))\n- **runtime-core:** improve render context warning ([#2496](https://github.com/vuejs/core/issues/2496)) ([288ae0a](https://github.com/vuejs/core/commit/288ae0a8d9444365ad7438462e072c425150cbf1))\n- **runtime-core:** props type support `BigInt` ([#2891](https://github.com/vuejs/core/issues/2891)) ([ffd5288](https://github.com/vuejs/core/commit/ffd52885453d1621e45dff645ff1101e74ea40b2))\n\n### Performance Improvements\n\n- **reactivity:** should not track `__isVue` ([#2940](https://github.com/vuejs/core/issues/2940)) ([dd02cf3](https://github.com/vuejs/core/commit/dd02cf37d5f5a6946bcae01ee70568e38a82c177))\n\n## [3.0.5](https://github.com/vuejs/core/compare/v3.0.4...v3.0.5) (2020-12-30)\n\n**Note:** this release contains a type-only change that requires TypeScript 4.0+, which\nmay cause build issues in projects still using TS 3.x.\n\n### Bug Fixes\n\n- **compiler-core:** fix missing createVNode import on nested v-for ([ad4d391](https://github.com/vuejs/core/commit/ad4d3915d39515a3e9ff2de691f82cb922a314b9)), closes [#2718](https://github.com/vuejs/core/issues/2718)\n- **compiler-sfc:** should keep template nodes with no content ([#2468](https://github.com/vuejs/core/issues/2468)) ([5b9b37f](https://github.com/vuejs/core/commit/5b9b37fc9b363be2989c1e9d76ab6e950cdfe2ad)), closes [#2463](https://github.com/vuejs/core/issues/2463)\n- **compiler-sfc:** support transforming asset urls with full base url. ([#2477](https://github.com/vuejs/core/issues/2477)) ([db786b1](https://github.com/vuejs/core/commit/db786b1afe41c26611a215e6d6599d50312b9c2f))\n- **runtime-core:** component mount anchor memory leak ([#2459](https://github.com/vuejs/core/issues/2459)) ([3867bb4](https://github.com/vuejs/core/commit/3867bb4c14131ef94098a62bffba97a5b7d1fe66)), closes [#2458](https://github.com/vuejs/core/issues/2458)\n- **runtime-core:** skip patchBlockChildren if n1.dynamicChildren is null ([#2717](https://github.com/vuejs/core/issues/2717)) ([c59897c](https://github.com/vuejs/core/commit/c59897c7b0dbd82b5bbf3fbca945c0639ac37fb8)), closes [#2715](https://github.com/vuejs/core/issues/2715) [#2485](https://github.com/vuejs/core/issues/2485)\n- **runtime-dom:** support mounting app on ShadowRoot ([#2447](https://github.com/vuejs/core/issues/2447)) ([b2189ba](https://github.com/vuejs/core/commit/b2189ba2f3400ab6bf9ee75b56ac11e65f7bd061)), closes [#2399](https://github.com/vuejs/core/issues/2399)\n- **ssr:** properly handle ssr empty slot and fallback ([88f6b33](https://github.com/vuejs/core/commit/88f6b33d054c18802375ec99c4a57e4acc649a02))\n- **transition:** ensure manual style manipulation in transition leave hooks work ([cbaa380](https://github.com/vuejs/core/commit/cbaa3805064cb581fc2007cf63774c91d39844fe)), closes [#2720](https://github.com/vuejs/core/issues/2720)\n- **transition:** ensure styles from \\*-leave-active trigger transition ([#2716](https://github.com/vuejs/core/issues/2716)) ([3f8f9b6](https://github.com/vuejs/core/commit/3f8f9b67b3b54a7ae8405baf6d28be7ec074509d)), closes [#2712](https://github.com/vuejs/core/issues/2712)\n\n### Features\n\n- **devtools:** send instance ([3626ff0](https://github.com/vuejs/core/commit/3626ff07fe5107080c52e85018070562c84b796e))\n\n## [3.0.4](https://github.com/vuejs/core/compare/v3.0.3...v3.0.4) (2020-12-02)\n\n### Bug Fixes\n\n- **async-component:** forward refs on async component wrapper ([64d4681](https://github.com/vuejs/core/commit/64d4681e4b9d88e17cd1515014866d43d0424d14)), closes [#2671](https://github.com/vuejs/core/issues/2671)\n- **attr-fallthrough:** ensure consistent attr fallthrough for root fragments with comments ([3bc2914](https://github.com/vuejs/core/commit/3bc2914e32b030b1247659f871f6055827154087)), closes [#2549](https://github.com/vuejs/core/issues/2549)\n- **build:** enable safari10 option for terser ([#2472](https://github.com/vuejs/core/issues/2472)) ([20a704f](https://github.com/vuejs/core/commit/20a704fc043b29c3c9baac602211c595ede728cf)), closes [#2470](https://github.com/vuejs/core/issues/2470)\n- **compiler-core:** fix scope var reference check for v-on expressions ([9db7095](https://github.com/vuejs/core/commit/9db70959621c7df44807324a3b1a41caa2b261eb)), closes [#2564](https://github.com/vuejs/core/issues/2564)\n- **compiler-core:** fix unintended imports in esm-bundler builds ([55d99d7](https://github.com/vuejs/core/commit/55d99d729e147fae515c12148590f0100508c49d)), closes [#2258](https://github.com/vuejs/core/issues/2258) [#2515](https://github.com/vuejs/core/issues/2515)\n- **compiler-core:** transform kebab case props to camelcase on slots ([#2490](https://github.com/vuejs/core/issues/2490)) ([ef59a30](https://github.com/vuejs/core/commit/ef59a30cabd12f6f14fee210a7fe49bccd3fd86c)), closes [#2488](https://github.com/vuejs/core/issues/2488)\n- **compiler-core/v-on:** handle falsy values when caching v-on handlers ([e4f09c1](https://github.com/vuejs/core/commit/e4f09c1419352c18a60a5930d9526d916d1323d3)), closes [#2605](https://github.com/vuejs/core/issues/2605)\n- **compiler-sfc:** fix parsing error when `lang=\"\"` is used on plain element ([#2569](https://github.com/vuejs/core/issues/2569)) ([5f2a853](https://github.com/vuejs/core/commit/5f2a8533acc332528faedb2d1b6ecdae104087a4)), closes [#2566](https://github.com/vuejs/core/issues/2566)\n- **compiler-sfc:** named imports from .vue file should not be treated as constant ([085bbd5](https://github.com/vuejs/core/commit/085bbd5fe07c52056e9f7151fbaed8f6a2e442b3)), closes [#2699](https://github.com/vuejs/core/issues/2699)\n- **compiler-sfc:** should not remove import statements with no specifier when compiling script setup ([43eab92](https://github.com/vuejs/core/commit/43eab923ea651079181490d191966ff28988e9c8))\n- **compiler-ssr:** generate correct children for transition-group ([a5d6f80](https://github.com/vuejs/core/commit/a5d6f8091e3761447b7fec0e3d1346eb83402a0a)), closes [#2510](https://github.com/vuejs/core/issues/2510)\n- **compiler-ssr:** handle v-model checkbox with true-value binding ([fe5428d](https://github.com/vuejs/core/commit/fe5428db1207747886957b831d46d71ecb6fadaa))\n- **compiler-ssr:** should not render key/ref bindings in ssr ([5b62662](https://github.com/vuejs/core/commit/5b6266284da01008e2f68ed353a622adc5704261))\n- **provide:** support symbols in applyOptions ([#2616](https://github.com/vuejs/core/issues/2616)) ([7a1a782](https://github.com/vuejs/core/commit/7a1a782642a13d5fcc6b8c738a5ce8f8c657e1b5)), closes [#2615](https://github.com/vuejs/core/issues/2615)\n- **reactivity:** ensure readonly on plain arrays doesn't track array methods. ([#2506](https://github.com/vuejs/core/issues/2506)) ([3470308](https://github.com/vuejs/core/commit/34703082fd5afacee774ee92c11753119032ed1a)), closes [#2493](https://github.com/vuejs/core/issues/2493)\n- **reactivity:** ensure add/set on reactive collections return the proxy ([#2534](https://github.com/vuejs/core/issues/2534)) ([6e46a57](https://github.com/vuejs/core/commit/6e46a574eddb5fa43c8a4ce10c620ecdf1caf3b8)), closes [#2530](https://github.com/vuejs/core/issues/2530)\n- **runtime-core:** ensure keep-alive deep-watches include/explude props ([#2551](https://github.com/vuejs/core/issues/2551)) ([421205d](https://github.com/vuejs/core/commit/421205d0ad1ab187ff72be754e38c7228230eb60)), closes [#2550](https://github.com/vuejs/core/issues/2550)\n- **runtime-core:** ensure watchers are always registered to correct instance owner ([#2495](https://github.com/vuejs/core/issues/2495)) ([735af1c](https://github.com/vuejs/core/commit/735af1c7b7e764c410b8dd671eaaa9a72f09ea3f)), closes [#2381](https://github.com/vuejs/core/issues/2381)\n- **runtime-core:** fix emit listener check on kebab-case events ([#2542](https://github.com/vuejs/core/issues/2542)) ([3532b2b](https://github.com/vuejs/core/commit/3532b2b0213268a285cacce9b38f806e6af29a61)), closes [#2540](https://github.com/vuejs/core/issues/2540)\n- **runtime-core:** handle static node move in production ([bf16a57](https://github.com/vuejs/core/commit/bf16a57fc3d23118c670918348f02457cfcc44d6))\n- **runtime-core:** remove static node in production mode ([#2556](https://github.com/vuejs/core/issues/2556)) ([2a9ba0c](https://github.com/vuejs/core/commit/2a9ba0c8e961ed6c68a8008ccbef85ff2cabeeb2)), closes [#2553](https://github.com/vuejs/core/issues/2553)\n- **runtime-core:** should pause tracking when initializing legacy options ([#2524](https://github.com/vuejs/core/issues/2524)) ([0ff2a4f](https://github.com/vuejs/core/commit/0ff2a4f1c1847a4e173dcab810e6438143a4272c)), closes [#2521](https://github.com/vuejs/core/issues/2521)\n- **runtime-core:** skip functional components in public $parent chain traversal ([53f4885](https://github.com/vuejs/core/commit/53f4885d9e06f1b1b0b33abc8f1c20766cbb2d1a)), closes [#2437](https://github.com/vuejs/core/issues/2437)\n- **runtime-dom:** attribute should be removed with nullish values ([#2679](https://github.com/vuejs/core/issues/2679)) ([fb6b9f8](https://github.com/vuejs/core/commit/fb6b9f8e8ff35ca4d8723a9f96e36266de0dd947)), closes [#2677](https://github.com/vuejs/core/issues/2677)\n- **script-setup:** ensure useContext() return valid context ([73cdb9d](https://github.com/vuejs/core/commit/73cdb9d4208f887fe08349657122e39175d7166c))\n- **slots:** dynamically named slots should be keyed by name ([2ab8c41](https://github.com/vuejs/core/commit/2ab8c41a1a43952fb229587a9da48d9a1214ab9e)), closes [#2535](https://github.com/vuejs/core/issues/2535)\n- **slots:** should render fallback content when slot content contains no valid nodes ([#2485](https://github.com/vuejs/core/issues/2485)) ([ce4915d](https://github.com/vuejs/core/commit/ce4915d8bed12f4cdb5fa8ca39bda98d0d3aabb7)), closes [#2347](https://github.com/vuejs/core/issues/2347) [#2461](https://github.com/vuejs/core/issues/2461)\n- **suspense:** fix nested async child toggle inside already resolved suspense ([cf7f1db](https://github.com/vuejs/core/commit/cf7f1dbc9be8d50ad220e3630c38f5a9a217d693)), closes [#2215](https://github.com/vuejs/core/issues/2215)\n- **teleport:** Teleport into SVG elements ([#2648](https://github.com/vuejs/core/issues/2648)) ([cd92836](https://github.com/vuejs/core/commit/cd928362232747a51d1fd4790bb20adcdd59d187)), closes [#2652](https://github.com/vuejs/core/issues/2652)\n- **transition:** avoid invoking stale transition end callbacks ([eaf8a67](https://github.com/vuejs/core/commit/eaf8a67c7219e1b79d6abca44a1d7f1b341b58b0)), closes [#2482](https://github.com/vuejs/core/issues/2482)\n- **transition:** respect rules in \\*-leave-from transition class ([#2597](https://github.com/vuejs/core/issues/2597)) ([e2618a6](https://github.com/vuejs/core/commit/e2618a632d4add2819ffb8b575af0da189dc3204)), closes [#2593](https://github.com/vuejs/core/issues/2593)\n- **types:** fix ToRefs type on union value types ([e315d84](https://github.com/vuejs/core/commit/e315d84936c82bee8f2cf2369c61b5aaec38f328)), closes [#2687](https://github.com/vuejs/core/issues/2687)\n- **v-model:** avoid mutation when using Set models + fix multi select Set model update ([f2b0a8e](https://github.com/vuejs/core/commit/f2b0a8e81d15eb8017c7fca5c1dff0e5f6a5573e))\n- **v-model:** respect checkbox true-value/false-value on initial render ([48f00c0](https://github.com/vuejs/core/commit/48f00c0f1b574a235be40c560d2cf373be97615e)), closes [#2694](https://github.com/vuejs/core/issues/2694)\n- **v-show:** ensure v-show conflict with inline string style binding ([3cd30c5](https://github.com/vuejs/core/commit/3cd30c5245da0733f9eb6f29d220f39c46518162)), closes [#2583](https://github.com/vuejs/core/issues/2583)\n- allow hmr in all builds ([46d80f4](https://github.com/vuejs/core/commit/46d80f4d585195446e7f8cf4ba42d00a98e9ee5d)), closes [#2571](https://github.com/vuejs/core/issues/2571)\n\n### Features\n\n- **sfc:** allow sfcs to recursively self-reference in template via name inferred from filename ([67d1aac](https://github.com/vuejs/core/commit/67d1aac6ae683a3a7291dff15071d1eeacb7d22a))\n\n## [3.0.3](https://github.com/vuejs/core/compare/v3.0.2...v3.0.3) (2020-11-25)\n\n### Bug Fixes\n\n- **compiler-core/compiler-sfc:** handle destructure assignment expressions ([4c6078c](https://github.com/vuejs/core/commit/4c6078ce25226ab9e10ec4eba5c745058f670b3d))\n- **compiler-sfc:** fix script setup ts helpers ([6e3abc8](https://github.com/vuejs/core/commit/6e3abc86058f967bcf6fad94c62572989d4dbcbc))\n- **hmr:** fix updates for imported but not yet rendered components ([9c23ddf](https://github.com/vuejs/core/commit/9c23ddf9c593dcf6d20bc911ec95d9b674f23dc8))\n- **runtime-core:** components with static props and slots should not be force updated ([51e43e0](https://github.com/vuejs/core/commit/51e43e07998eeade153c42a9a9b3eda8fe885c88))\n- **runtime-core:** ensure scheduler queue is always non-null ([#2567](https://github.com/vuejs/core/issues/2567)) ([af95604](https://github.com/vuejs/core/commit/af9560455d9719a4c5f0d6588d04bfb4c06c8654))\n- **runtime-dom:** use correct import source ([f28ca55](https://github.com/vuejs/core/commit/f28ca556925147bb109d5ba77c5dafaf17d57322))\n- **style-vars:** apply css vars in post flush effect ([3a6b120](https://github.com/vuejs/core/commit/3a6b1207fa39cb35eed5bae0b5fdcdb465926bca))\n- handle case of ref declaration without initial value ([8485cd4](https://github.com/vuejs/core/commit/8485cd48437bf47880a61b03c57090e8bfdf527b))\n- **types:** ensure correct type for toRef and toRefs on existing refs ([8e20375](https://github.com/vuejs/core/commit/8e2037537219219d5ab6456e8a29bd0235eac311))\n\n### Experimental Features\n\n> Note: support for experimental features in SFCs have been updated according to changes in ongoing RFCs. This release may break existing usage of such experimental features.\n\n- **compiler-sfc:** compileScript inline render function mode ([886ed76](https://github.com/vuejs/core/commit/886ed7681dd203c07ff3b504538328f43e14d9b0))\n- **compiler-sfc:** new script setup implementation ([556560f](https://github.com/vuejs/core/commit/556560fae31d9e406cfae656089657b6332686c1))\n- **compiler-sfc:** new SFC css variable injection implementation ([41bb7fa](https://github.com/vuejs/core/commit/41bb7fa330e78c4a354a2e67742bd13bee2f4293))\n- **compiler-sfc:** support kebab-case components in `<script setup>` sfc template ([3f99e23](https://github.com/vuejs/core/commit/3f99e239e03a8861c462d4ee91feb82066ab3e28))\n- **runtime-core:** explicit expose API ([0e59770](https://github.com/vuejs/core/commit/0e59770b9282992f6a5af4d8fef33dafb948fc8b))\n\n### Reverts\n\n- Revert \"wip: allow scriptCompiled to be cached on sfc descriptor\" ([9db4288](https://github.com/vuejs/core/commit/9db42889e65a0e80cdbae5c19d76dab4f9fadb6d))\n\n## [3.0.2](https://github.com/vuejs/core/compare/v3.0.1...v3.0.2) (2020-10-20)\n\n### Bug Fixes\n\n- **compiler:** stringify values on v-text ([#2432](https://github.com/vuejs/core/issues/2432)) ([314ab2c](https://github.com/vuejs/core/commit/314ab2c7c5dec56d9b117ac3bb988f19d92cf126)), closes [#2430](https://github.com/vuejs/core/issues/2430)\n- **compiler-core:** fix multiline member expression check ([#2436](https://github.com/vuejs/core/issues/2436)) ([6d2a1cb](https://github.com/vuejs/core/commit/6d2a1cb64d090c482ed2cde7311f81b33e0f8d90)), closes [#2426](https://github.com/vuejs/core/issues/2426)\n- **reactivity:** track length on for in iteration on Array ([0e5a3c4](https://github.com/vuejs/core/commit/0e5a3c47a7398dfd0107fccf9b615772dd01aa74)), closes [#2427](https://github.com/vuejs/core/issues/2427)\n- **runtime-core:** avoid mutating EMPTY_ARR when setting dev root ([#2419](https://github.com/vuejs/core/issues/2419)) ([edd49dc](https://github.com/vuejs/core/commit/edd49dcab40eb3faa44248772b176d5eebfd30fe)), closes [#2413](https://github.com/vuejs/core/issues/2413)\n- **runtime-core:** avoid object prototype keys in property access cache ([#2416](https://github.com/vuejs/core/issues/2416)) ([ba881f9](https://github.com/vuejs/core/commit/ba881f9190510c613f04950b69d78f6af1a90e06))\n- **runtime-core:** fix component .once listener logic ([4bbb2b2](https://github.com/vuejs/core/commit/4bbb2b2ee6866ed80cb542c2ff24207b4bd09bda))\n- **runtime-core:** non-stable Fragment should always unmount its children ([#2445](https://github.com/vuejs/core/issues/2445)) ([fff62e2](https://github.com/vuejs/core/commit/fff62e2ee8accf31bb5ac5abdb4c0636216cfd0e)), closes [#2444](https://github.com/vuejs/core/issues/2444)\n- **runtime-core:** prevent self-injection ([#2424](https://github.com/vuejs/core/issues/2424)) ([111d04f](https://github.com/vuejs/core/commit/111d04f119a2b2d0b1a1790a063b152c17787943)), closes [#2400](https://github.com/vuejs/core/issues/2400)\n- **suspense:** fix suspense nested child updates in template mode ([0227b4a](https://github.com/vuejs/core/commit/0227b4a697afd598f6fa279a1a7ce84242e68f43)), closes [#2214](https://github.com/vuejs/core/issues/2214)\n- **types:** h support for resolveComponent ([#2402](https://github.com/vuejs/core/issues/2402)) ([1f2a652](https://github.com/vuejs/core/commit/1f2a652a9d2e3bec472fb1786a4c16d6ccfa1fb1)), closes [#2357](https://github.com/vuejs/core/issues/2357)\n- **v-model:** built in modifiers support on component ([#2348](https://github.com/vuejs/core/issues/2348)) ([128ec46](https://github.com/vuejs/core/commit/128ec460ec00ca8672352d019b264c80dfd0c3b0)), closes [#2326](https://github.com/vuejs/core/issues/2326)\n\n### Features\n\n- **compile-core:** handle falsy dynamic args for v-on and v-bind ([#2393](https://github.com/vuejs/core/issues/2393)) ([052a621](https://github.com/vuejs/core/commit/052a621762c5f7c420464747ebbbed27c7350593)), closes [#2388](https://github.com/vuejs/core/issues/2388)\n\n## [3.0.1](https://github.com/vuejs/core/compare/v3.0.0...v3.0.1) (2020-10-15)\n\n### Bug Fixes\n\n- **compiler-core:** allow spaces between if-else branches ([#2305](https://github.com/vuejs/core/issues/2305)) ([89c5909](https://github.com/vuejs/core/commit/89c5909a6f063dddcdf61650a6ed08f8be138521)), closes [#2299](https://github.com/vuejs/core/issues/2299)\n- **compiler-core:** consistently remove comment nodes for pre tags in production ([f411924](https://github.com/vuejs/core/commit/f4119249f2d3f394469028ad9664f61830540ff9)), closes [#2217](https://github.com/vuejs/core/issues/2217)\n- **compiler-core:** fix v-if key injection with v-on object syntax ([#2368](https://github.com/vuejs/core/issues/2368)) ([692197b](https://github.com/vuejs/core/commit/692197be33de8f73a605e3a7f71389be42613ee3)), closes [#2366](https://github.com/vuejs/core/issues/2366)\n- **compiler-core:** make v-once work with v-if/else-if/else ([#2182](https://github.com/vuejs/core/issues/2182)) ([9499871](https://github.com/vuejs/core/commit/94998715822589f6f10443b6dba75f193467845d)), closes [#2035](https://github.com/vuejs/core/issues/2035)\n- **compiler-ssr:** fix SSR issue when dynamic and static class co-exist ([#2354](https://github.com/vuejs/core/issues/2354)) ([8539c0b](https://github.com/vuejs/core/commit/8539c0bf32e86fb16349a210f878681579fb7976))\n- **hmr:** full diff props for non-sfc component ([#2359](https://github.com/vuejs/core/issues/2359)) ([e78915a](https://github.com/vuejs/core/commit/e78915a74045ebcf34e8e99064fff48cd044632c))\n- **reactivity:** should add allowRecurse to the effect ([#2213](https://github.com/vuejs/core/issues/2213)) ([ea1f87e](https://github.com/vuejs/core/commit/ea1f87eabf2deab2e586af7ebd2d74bb58f72b87)), closes [#2200](https://github.com/vuejs/core/issues/2200)\n- **reactivity:** should not trigger watch on computed ref when value is unchanged ([390589e](https://github.com/vuejs/core/commit/390589ec6d977675c5cef2807fbf3e930a25eef0)), closes [#2231](https://github.com/vuejs/core/issues/2231)\n- **reactivity:** use resetTracking instead of enableTracking ([#2174](https://github.com/vuejs/core/issues/2174)) ([7cc09ca](https://github.com/vuejs/core/commit/7cc09ca8a581783c2391824885206348e5e99934))\n- **runtime-core:** ensure this context for $nextTick callback ([5c3e8e9](https://github.com/vuejs/core/commit/5c3e8e984029711c97ca671fa098cf66483dd571)), closes [#2282](https://github.com/vuejs/core/issues/2282)\n- **runtime-core:** error handling for created/beforeCreate hooks ([b392fe4](https://github.com/vuejs/core/commit/b392fe419c7486de62fac8f25640fe0836bef02e)), closes [#2268](https://github.com/vuejs/core/issues/2268)\n- **runtime-core:** fix directive merging on component root ([4d1ebb5](https://github.com/vuejs/core/commit/4d1ebb5deb4c1cb2a02e8482bf8f9cc87197b088)), closes [#2298](https://github.com/vuejs/core/issues/2298)\n- **runtime-core:** fix duplicated unmount traversal in optimized mode ([376883d](https://github.com/vuejs/core/commit/376883d1cfea6ed92807cce1f1209f943a04b625)), closes [#2169](https://github.com/vuejs/core/issues/2169)\n- **runtime-core:** fix provide function data access in extends/mixins ([f06518a](https://github.com/vuejs/core/commit/f06518a8c9201b4fa2a956595aa9d89a192fcd20)), closes [#2300](https://github.com/vuejs/core/issues/2300)\n- **runtime-core:** fix SSR memory leak due to props normalization cache ([a66e53a](https://github.com/vuejs/core/commit/a66e53a24f445b688eef6812ecb872dc53cf2702)), closes [#2225](https://github.com/vuejs/core/issues/2225)\n- **runtime-core:** make errorCaptured return value handling consistent with Vue 2 ([#2289](https://github.com/vuejs/core/issues/2289)) ([4d20ac8](https://github.com/vuejs/core/commit/4d20ac8173f84c87288255dcc03c62a6ee862a23)), closes [#2267](https://github.com/vuejs/core/issues/2267)\n- **runtime-core:** use consistent camelCase event casing for render functions ([#2278](https://github.com/vuejs/core/issues/2278)) ([62f2617](https://github.com/vuejs/core/commit/62f26173ba715fd8bf2b131e19d94275106e830d)), closes [#2249](https://github.com/vuejs/core/issues/2249)\n- **runtime-core:** vnode.el is null in watcher after rerendering ([#2295](https://github.com/vuejs/core/issues/2295)) ([28d5fd7](https://github.com/vuejs/core/commit/28d5fd7a2871c10df3427dfbbe0e203c2a976cb4)), closes [#2170](https://github.com/vuejs/core/issues/2170)\n- **runtime-core/template-refs:** do not reset refs object before updates ([25d53f0](https://github.com/vuejs/core/commit/25d53f09bbf55412a003eabb7a390dc8434f8987)), closes [#2283](https://github.com/vuejs/core/issues/2283)\n- **runtime-dom:** v-model should support number modifier with select tag ([#2308](https://github.com/vuejs/core/issues/2308)) ([d744b8a](https://github.com/vuejs/core/commit/d744b8a2dc7653c3e5e43e5379dbf72cf4c9ff2c)), closes [#2252](https://github.com/vuejs/core/issues/2252)\n- **sfc/style-vars:** should attach css vars while `subtree` changed ([#2178](https://github.com/vuejs/core/issues/2178)) ([408a8ca](https://github.com/vuejs/core/commit/408a8cad48f5fe0854c83a979ff98f03738fbfba)), closes [#2177](https://github.com/vuejs/core/issues/2177)\n- **teleport:** proper children traversal when teleport is block root ([2ae3b26](https://github.com/vuejs/core/commit/2ae3b26679faf2d5393998ba806b99748679195a)), closes [#2324](https://github.com/vuejs/core/issues/2324)\n- **teleport:** should only force remove teleport when not disabled ([b0931dc](https://github.com/vuejs/core/commit/b0931dcabaa2858ba76102f49878771ec14fb2e8)), closes [#2323](https://github.com/vuejs/core/issues/2323)\n- **types:** avoid DefineComponent defaulting to any ([6aa2256](https://github.com/vuejs/core/commit/6aa2256913bfd097500aba83b78482b87107c101)), closes [#2192](https://github.com/vuejs/core/issues/2192)\n- **types:** fix using tuple type as EmitsOptions ([#2160](https://github.com/vuejs/core/issues/2160)) ([5dbd6b3](https://github.com/vuejs/core/commit/5dbd6b36a0666fc6c993115ee5281ef253ba8a68)), closes [#2159](https://github.com/vuejs/core/issues/2159)\n- **v-for:** handle and warn when `v-for` receives non-integer range number ([#2247](https://github.com/vuejs/core/issues/2247)) ([02f355e](https://github.com/vuejs/core/commit/02f355eb69df32a03e942e01ac1de654d26916a1)), closes [#2245](https://github.com/vuejs/core/issues/2245)\n- **v-model:** avoid clearing IME compose state on updates ([#2304](https://github.com/vuejs/core/issues/2304)) ([fbd198f](https://github.com/vuejs/core/commit/fbd198fbfe2f87c3c15a63d9770d00bf3fc9c142)), closes [#2302](https://github.com/vuejs/core/issues/2302)\n- **v-model:** ensure initial value is set after other attributes ([54ed759](https://github.com/vuejs/core/commit/54ed7592e416fc411196e9b767aebcc4f2ca20d8)), closes [#2325](https://github.com/vuejs/core/issues/2325)\n\n### Features\n\n- custom formatters ([6ba7ba4](https://github.com/vuejs/core/commit/6ba7ba47d59288b8cd39c985a2163ebd220607bc))\n\n### Performance Improvements\n\n- **runtime-dom/vModel:** remove looseHas if model is Set ([#2236](https://github.com/vuejs/core/issues/2236)) ([6a554fe](https://github.com/vuejs/core/commit/6a554feb13487132ed7631f80a1efe8c41991346))\n- do not enable hmr in non-browser envs ([cf2c9f6](https://github.com/vuejs/core/commit/cf2c9f6faa95add4c23b20c4b8a6e477d05ff0ed))\n\n# [3.0.0](https://github.com/vuejs/core/compare/v3.0.0-rc.13...v3.0.0) (2020-09-18)\n\n# [3.0.0-rc.13](https://github.com/vuejs/core/compare/v3.0.0-rc.12...v3.0.0-rc.13) (2020-09-18)\n\n### Bug Fixes\n\n- **hmr:** make hmr working with class components ([#2144](https://github.com/vuejs/core/issues/2144)) ([422f05e](https://github.com/vuejs/core/commit/422f05e085036e23ea3632c2ce75d86181a087b8))\n- **reactivity:** avoid length mutating array methods causing infinite updates ([#2138](https://github.com/vuejs/core/issues/2138)) ([f316a33](https://github.com/vuejs/core/commit/f316a332b055d3f448dc735365551d89041f1098)), closes [#2137](https://github.com/vuejs/core/issues/2137)\n- **suspense:** should discard unmount effects of invalidated pending branch ([5bfcad1](https://github.com/vuejs/core/commit/5bfcad155b444b2f7ffaac171c1f61bc23909287))\n- **types:** component instance inference without props ([#2145](https://github.com/vuejs/core/issues/2145)) ([57bdaa2](https://github.com/vuejs/core/commit/57bdaa2220afefbde21118659c1ce2377d6b86d6))\n\n### Code Refactoring\n\n- watch APIs default to trigger pre-flush ([49bb447](https://github.com/vuejs/core/commit/49bb44756fda0a7019c69f2fa6b880d9e41125aa)), closes [/github.com/vuejs/core/issues/1706#issuecomment-666258948](https://github.com//github.com/vuejs/core/issues/1706/issues/issuecomment-666258948)\n\n### Features\n\n- **runtime-core:** support using inject() inside props default functions ([58c31e3](https://github.com/vuejs/core/commit/58c31e36992d2647e5247de4904246fb2d6112ed))\n- **watch:** support dot-delimited path in watch option ([1c9a0b3](https://github.com/vuejs/core/commit/1c9a0b3e195d144ac90d22d2cc2cef6a3fd8276d))\n\n### BREAKING CHANGES\n\n- watch APIs now default to use `flush: 'pre'` instead of\n  `flush: 'post'`. This change affects `watch`, `watchEffect`, the `watch` component option, and `this.$watch`. See ([49bb447](https://github.com/vuejs/core/commit/49bb44756fda0a7019c69f2fa6b880d9e41125aa)) for more details.\n\n# [3.0.0-rc.12](https://github.com/vuejs/core/compare/v3.0.0-rc.11...v3.0.0-rc.12) (2020-09-16)\n\n### Bug Fixes\n\n- **reactivity:** effect should only recursively self trigger with explicit options ([3810de7](https://github.com/vuejs/core/commit/3810de7d6bd0044177f043285228c2e988093883)), closes [#2125](https://github.com/vuejs/core/issues/2125)\n- **runtime-core:** ensure root stable fragments inherit elements for moving ([bebd44f](https://github.com/vuejs/core/commit/bebd44f793ccd13bfdf90c7e45eac320a340650c)), closes [#2134](https://github.com/vuejs/core/issues/2134)\n- **runtime-core:** should still do full traverse of stable fragment children in dev + hmr ([dd40ad8](https://github.com/vuejs/core/commit/dd40ad8fca47af0e1f0a963be2f48c23f7457952))\n- **runtime-core/async-component:** fix error component when there are no error handlers ([c7b4a37](https://github.com/vuejs/core/commit/c7b4a379cf8627c79a01d61039d3e3b283477dc1)), closes [#2129](https://github.com/vuejs/core/issues/2129)\n- **types/tsx:** optional props from Mixin/Extends are treated as required ([#2048](https://github.com/vuejs/core/issues/2048)) ([89e9ab8](https://github.com/vuejs/core/commit/89e9ab8a2a387f26a370848db0b1ffb1d0ab9549))\n\n### Features\n\n- **compiler-sfc:** `additionalData` support for css preprocessors ([#2126](https://github.com/vuejs/core/issues/2126)) ([066d514](https://github.com/vuejs/core/commit/066d514d757fb7e8844104210d7d04cc11598fef))\n\n# [3.0.0-rc.11](https://github.com/vuejs/core/compare/v3.0.0-rc.10...v3.0.0-rc.11) (2020-09-15)\n\n### Bug Fixes\n\n- **compiler-core:** fix prefixing for `<template v-for>` key expressions ([be946ea](https://github.com/vuejs/core/commit/be946ea549d5073274813ed15348bdbfabcaa30c)), closes [#2085](https://github.com/vuejs/core/issues/2085)\n- **compiler-core:** fix v-if block handling for components that fail to resolve ([a096a58](https://github.com/vuejs/core/commit/a096a58e412dc37ae618a3b4702f591c580d376a)), closes [#2058](https://github.com/vuejs/core/issues/2058)\n- **compiler-sfc:** should extract comment for import or type declarations ([#2107](https://github.com/vuejs/core/issues/2107)) ([05df696](https://github.com/vuejs/core/commit/05df696a2b846a249f2569f4d6183c16e4be88e7)), closes [#2102](https://github.com/vuejs/core/issues/2102)\n- **compiler-ssr:** correct the variable name generated by the generator ([#2065](https://github.com/vuejs/core/issues/2065)) ([aa8dc9a](https://github.com/vuejs/core/commit/aa8dc9a50706e6407978da3c43d7e4d2eb292d56))\n- **compiler-ssr/teleport:** correct the target prop of teleport ([#2053](https://github.com/vuejs/core/issues/2053)) ([7455dca](https://github.com/vuejs/core/commit/7455dca11cea22f26a7c72628f6b61ad02856bfc))\n- **inject:** fix support for inject option default function ([d472461](https://github.com/vuejs/core/commit/d4724619fc3d005311f27c1ac7cab0a0e735c4d2)), closes [#2050](https://github.com/vuejs/core/issues/2050)\n- **keep-alive:** should use onMounted and onUpdated to invoke cacheSubtree ([#1984](https://github.com/vuejs/core/issues/1984)) ([890ca8a](https://github.com/vuejs/core/commit/890ca8aa346e77002e0ffbc497018bdc5a6f8125))\n- **KeepAlive:** when exclude prop change, it should prune cache that not matched ([#2111](https://github.com/vuejs/core/issues/2111)) ([98cc1f9](https://github.com/vuejs/core/commit/98cc1f9d848edf9a58315018d57885f983bb5baa))\n- **reactivity:** `toRef` should not wrap a `ref` ([#2103](https://github.com/vuejs/core/issues/2103)) ([d4bf9bc](https://github.com/vuejs/core/commit/d4bf9bcbb430fa0168ca48039579d59e6789c6f5))\n- should be able to parse decorators in script lang=\"ts\" & jsx ([#2088](https://github.com/vuejs/core/issues/2088)) ([273d19a](https://github.com/vuejs/core/commit/273d19ad461a46d5b8753be2d2886249947494a6))\n- **reactivity:** add NaN prop on Array should not trigger length dependency. ([#1998](https://github.com/vuejs/core/issues/1998)) ([0d4910a](https://github.com/vuejs/core/commit/0d4910a211f6debd8ea5ca414d6308f1028679a3))\n- **reactivity:** revert ac81dcf ([5f40539](https://github.com/vuejs/core/commit/5f4053967cb61620d3dd27518f571166d7b5ec8f)), closes [#2043](https://github.com/vuejs/core/issues/2043)\n- **reactivity:** should trigger collection's write-function correctly on non-reactive keys ([#1992](https://github.com/vuejs/core/issues/1992)) ([fcf9b2c](https://github.com/vuejs/core/commit/fcf9b2cf194512b35dcad05d79206b1077abb929))\n- inherit `el` for static nodes inside keyed `template` fragment ([#2089](https://github.com/vuejs/core/issues/2089)) ([a32870a](https://github.com/vuejs/core/commit/a32870a8f611dd1146bb17d5605b168a7805c73f)), closes [#2080](https://github.com/vuejs/core/issues/2080)\n- **runtime-core:** fix priority of option merging ([#2041](https://github.com/vuejs/core/issues/2041)) ([95c07d8](https://github.com/vuejs/core/commit/95c07d8c36a69bfc29e661fbbfb92735c4fe5d3e))\n- **runtime-core:** warn reserved prefix for setup return properties and ensure consistent dev/prod behavior ([fa7ab0a](https://github.com/vuejs/core/commit/fa7ab0a7f7a939dc7724930a548805219e6a86c5)), closes [#2042](https://github.com/vuejs/core/issues/2042)\n- **runtime-core/inject:** handle optional `from` option in inject object config ([#2073](https://github.com/vuejs/core/issues/2073)) ([313dd06](https://github.com/vuejs/core/commit/313dd06065b1782d67f6881fbd42ae92a7f9cade))\n- **runtime-core/refs:** handle multiple merged refs for dynamic component with vnode ([612eb67](https://github.com/vuejs/core/commit/612eb6712a3858e4280946d98153b6f35792c652)), closes [#2078](https://github.com/vuejs/core/issues/2078)\n- **sfc:** fix scoped style regression for child component with single root + comment ([6dbc6c4](https://github.com/vuejs/core/commit/6dbc6c4cd0d298d3c6faa6d6aeb318be7a963700)), closes [#2046](https://github.com/vuejs/core/issues/2046)\n- **types:** properly infer return type from async setup ([#2051](https://github.com/vuejs/core/issues/2051)) ([24fcf6a](https://github.com/vuejs/core/commit/24fcf6ae7cd75c782a5aa2771aca259542e2a680)), closes [#2049](https://github.com/vuejs/core/issues/2049)\n\n### Features\n\n- update Suspense usage ([#2099](https://github.com/vuejs/core/issues/2099)) ([5ae7380](https://github.com/vuejs/core/commit/5ae7380b4a9144c6a2873d0181a0f21a9a090018))\n- **compiler-sfc:** support `additionalData` option in `compileStyle` when processing sass ([#1952](https://github.com/vuejs/core/issues/1952)) ([9377352](https://github.com/vuejs/core/commit/937735251ce2539ce9a087359eb270ce5b260ffe))\n- **runtime-dom:** allow native Set as v-model checkbox source ([#1957](https://github.com/vuejs/core/issues/1957)) ([cf1b6c6](https://github.com/vuejs/core/commit/cf1b6c666f45a284494f80981522a3dc4804a683))\n\n### Performance Improvements\n\n- should not trigger child update if changed prop is declared emit listener ([124c385](https://github.com/vuejs/core/commit/124c385bafb40f8df7ec61b612765706015ff0fa)), closes [#2072](https://github.com/vuejs/core/issues/2072)\n\n### Reverts\n\n- Revert \"refactor(runtime-core): add @internal for instance.proxy (#1849)\" (#2024) ([09a939d](https://github.com/vuejs/core/commit/09a939d37cbfc4e3276c99a741fc6801eea48405)), closes [#1849](https://github.com/vuejs/core/issues/1849) [#2024](https://github.com/vuejs/core/issues/2024)\n\n# [3.0.0-rc.10](https://github.com/vuejs/core/compare/v3.0.0-rc.9...v3.0.0-rc.10) (2020-09-02)\n\n### Bug Fixes\n\n- **devtools:** make el extra properties non-enumerable ([7fd3436](https://github.com/vuejs/core/commit/7fd3436290f3777f77cf4a05268e51353c91b297))\n- **runtime-core:** enable block tracking when normalizing plain element with slot children ([#1987](https://github.com/vuejs/core/issues/1987)) ([5b82c48](https://github.com/vuejs/core/commit/5b82c48c7b9ac9debaed3a14792d5d84752f1ca6)), closes [#1980](https://github.com/vuejs/core/issues/1980)\n- **runtime-core:** ensure consistent $options merge behavior with 2.x ([#1986](https://github.com/vuejs/core/issues/1986)) ([706b52a](https://github.com/vuejs/core/commit/706b52aadd3f06e644070c9e21f161a806bc38ab)), closes [#1978](https://github.com/vuejs/core/issues/1978) [#1979](https://github.com/vuejs/core/issues/1979)\n- **runtime-core:** fix props/emits resolving with global mixins ([8ed0b34](https://github.com/vuejs/core/commit/8ed0b342d49d6a5cf353d17c8426ae9f3c312405)), closes [#1975](https://github.com/vuejs/core/issues/1975)\n- **runtime-core:** openBlock() should not be tracked when block tracking is disabled ([ad93fa4](https://github.com/vuejs/core/commit/ad93fa42fc8c32d121c0121083d2f0bb40672737))\n- **runtime-core:** v-model listeners that already exists on the component should not be merged ([#2011](https://github.com/vuejs/core/issues/2011)) ([63f1f18](https://github.com/vuejs/core/commit/63f1f18064f809ebfa2c76f9f645ac74b6d412f3)), closes [#1989](https://github.com/vuejs/core/issues/1989)\n- **sfc/scoped-style:** inherit scopeId through nested HOCs with inheritAttrs: false ([c0427b4](https://github.com/vuejs/core/commit/c0427b45ffebb4cda24de16fa6365a65e185d2d7)), closes [#1988](https://github.com/vuejs/core/issues/1988)\n- **types:** fix `this` type of `this.$watch` ([#2022](https://github.com/vuejs/core/issues/2022)) ([aa757e8](https://github.com/vuejs/core/commit/aa757e8e6d5f8f9ad60b1ec12c4ac9479be73c80))\n- **v-once:** fix v-once usage with v-if and v-for ([52e45a9](https://github.com/vuejs/core/commit/52e45a9850b97daccfdb26830047d9529ceba667)), closes [#2035](https://github.com/vuejs/core/issues/2035)\n\n### Features\n\n- **compiler-sfc:** analyze script bindings ([#1962](https://github.com/vuejs/core/issues/1962)) ([4421c00](https://github.com/vuejs/core/commit/4421c009038db9aeeea7f69c90a21243860697e3))\n- **devtools:** expose vnode and component on elements ([38ca7e8](https://github.com/vuejs/core/commit/38ca7e8e4ebe46e53c3c4050ce2bb8161aeed633))\n- **ssr:** serverPrefetch ([c73b4a0](https://github.com/vuejs/core/commit/c73b4a0e10b7627d2d0d851e9abfeac9b6317e45))\n\n### Performance Improvements\n\n- **reactivity:** no need to proxy has/ownKeys for readonly objects ([691a4b9](https://github.com/vuejs/core/commit/691a4b95305dd506c03725805d603c6824a66aff))\n\n# [3.0.0-rc.9](https://github.com/vuejs/core/compare/v3.0.0-rc.8...v3.0.0-rc.9) (2020-08-26)\n\n### Bug Fixes\n\n- **runtime-core:** class and style should be properly normalized in cloneVNode ([#1967](https://github.com/vuejs/core/issues/1967)) ([9153fc2](https://github.com/vuejs/core/commit/9153fc2d8a5c9d24d79161586c70840ae7b84b8b)), closes [#1964](https://github.com/vuejs/core/issues/1964)\n- **runtime-core:** fix resolving assets from mixins and extends ([0cb7f7f](https://github.com/vuejs/core/commit/0cb7f7f880961162a6ca0b51bf308fbf83160eb5)), closes [#1963](https://github.com/vuejs/core/issues/1963)\n- **runtime-core:** properly call lifecycle hooks in chained mixins & extends ([#1974](https://github.com/vuejs/core/issues/1974)) ([6df0e73](https://github.com/vuejs/core/commit/6df0e738cb9ae6db0c0e9c3c70d81147521bfe7f)), closes [#1973](https://github.com/vuejs/core/issues/1973)\n\n### Performance Improvements\n\n- **reactivity:** add existing index or non-integer prop on Array should not trigger length dependency ([#1969](https://github.com/vuejs/core/issues/1969)) ([d5c4f6e](https://github.com/vuejs/core/commit/d5c4f6ed4d6feea9be56dcc0859592f03b6a5d9a))\n- **reactivity:** avoid triggering Map.has twice on non-reactive keys ([#1972](https://github.com/vuejs/core/issues/1972)) ([97bc30e](https://github.com/vuejs/core/commit/97bc30edadb52e57e29b3c6e36c04ec71916103c))\n\n# [3.0.0-rc.8](https://github.com/vuejs/core/compare/v3.0.0-rc.7...v3.0.0-rc.8) (2020-08-25)\n\n### Bug Fixes\n\n- **devtools:** unmountApp not behind compile flag ([6eb7fd8](https://github.com/vuejs/core/commit/6eb7fd83333d97186d570029e4fdca060fdb328d))\n- **hmr:** properly force hmr full component props update ([499bc0b](https://github.com/vuejs/core/commit/499bc0bfc4aedcb6ee4ec55ba823838b5496eba8)), closes [#1942](https://github.com/vuejs/core/issues/1942)\n- **keep-alive:** should remove wrapped version of injected keep alive hooks ([#1959](https://github.com/vuejs/core/issues/1959)) ([1ea2400](https://github.com/vuejs/core/commit/1ea24000c8f062f3cdc773e8e254892a05ba0702))\n- **reactivity:** fix iOS 12 JSON.stringify error on reactive objects ([016ba11](https://github.com/vuejs/core/commit/016ba116a8715d90858de4244073198958d735ff)), closes [#1916](https://github.com/vuejs/core/issues/1916)\n- **runtime-core:** fix data merge order for mixins/extends ([c15311c](https://github.com/vuejs/core/commit/c15311cfe879aa98c06585d731d996fca7633421)), closes [#1953](https://github.com/vuejs/core/issues/1953)\n- **runtime-core/scheduler:** handle nested flushPostFlushCbs calls ([36fa42a](https://github.com/vuejs/core/commit/36fa42a88cf3a72b58e507b82b35c56a42e43f09)), closes [#1947](https://github.com/vuejs/core/issues/1947)\n- **runtime-dom:** avoid setting unchanged input value ([#1937](https://github.com/vuejs/core/issues/1937)) ([1d55454](https://github.com/vuejs/core/commit/1d55454e61bf18cc2d6fe948c4528a680f67efe5)), closes [#1935](https://github.com/vuejs/core/issues/1935)\n- **ssr:** invoke directive created hook during hydration ([57642fa](https://github.com/vuejs/core/commit/57642fac8f33b9ea530cc997f8f7465a0573e123))\n- **types:** relax ComponentPublicInstanceConstructor type for class components ([#1943](https://github.com/vuejs/core/issues/1943)) ([67b6e0f](https://github.com/vuejs/core/commit/67b6e0f894400f527fc5b20772ed124738df9446))\n- **watch:** traverse refs in deep watch ([#1939](https://github.com/vuejs/core/issues/1939)) ([10293c7](https://github.com/vuejs/core/commit/10293c7a188021db9bb4386e12c490f1daf28126)), closes [#1900](https://github.com/vuejs/core/issues/1900)\n\n### Features\n\n- **devtools:** catch events ([23233dc](https://github.com/vuejs/core/commit/23233dc8b850bf9c6bf24c11d4586865884ddb5f))\n- **devtools:** expose setupState target object ([31b99a9](https://github.com/vuejs/core/commit/31b99a9139a32590187a2e4a50ad0654de0034a9))\n- **directives:** introduce `created` custom directive hook and ensure ([11804fe](https://github.com/vuejs/core/commit/11804fe93f66d43320498bfea564af1c9f7a9eb7)), closes [#1931](https://github.com/vuejs/core/issues/1931)\n- **runtime-core:** support variadic children in `h` for simple JSX compat ([54d06ec](https://github.com/vuejs/core/commit/54d06ec495a1743415de9426962024ffb764e4fe)), closes [#1917](https://github.com/vuejs/core/issues/1917)\n\n# [3.0.0-rc.7](https://github.com/vuejs/core/compare/v3.0.0-rc.6...v3.0.0-rc.7) (2020-08-21)\n\n### Bug Fixes\n\n- **compiler-core:** should attach key to single element child of `<template v-for>` ([#1910](https://github.com/vuejs/core/issues/1910)) ([69cfed6](https://github.com/vuejs/core/commit/69cfed6b313821d1ae7ecb02b63b0aaccb5599c6))\n- **reactivity:** unwrap non-index accessed refs on reactive arrays ([#1859](https://github.com/vuejs/core/issues/1859)) ([3c05f8b](https://github.com/vuejs/core/commit/3c05f8bbd6cd0e01bbc5830730852f9a93d8de8a)), closes [#1846](https://github.com/vuejs/core/issues/1846)\n- **runtime-core:** correctly track dynamic nodes in renderSlot ([#1911](https://github.com/vuejs/core/issues/1911)) ([7ffb79c](https://github.com/vuejs/core/commit/7ffb79c56318861075a47bd2357e34cde8a6dad9))\n- **runtime-core:** disable block tracking when calling compiled slot function in template expressions ([f02e2f9](https://github.com/vuejs/core/commit/f02e2f99d9c2ca95f4fd984d7bd62178eceaa214)), closes [#1745](https://github.com/vuejs/core/issues/1745) [#1918](https://github.com/vuejs/core/issues/1918)\n- **teleport:** only inherit el for non-patched nodes ([d4cc7b2](https://github.com/vuejs/core/commit/d4cc7b2496f9ed21ef6cac426697eac058da76bb)), closes [#1903](https://github.com/vuejs/core/issues/1903)\n\n### Performance Improvements\n\n- **reactivity:** improve ref performance by using class-based implementation ([#1900](https://github.com/vuejs/core/issues/1900)) ([07919e0](https://github.com/vuejs/core/commit/07919e00658592ebdb42f0c6f004f631c4bf4d34))\n\n# [3.0.0-rc.6](https://github.com/vuejs/core/compare/v3.0.0-rc.5...v3.0.0-rc.6) (2020-08-19)\n\n### Bug Fixes\n\n- **codeframe:** Added Math.max to prevent RangeError ([#1807](https://github.com/vuejs/core/issues/1807)) ([b14f4a5](https://github.com/vuejs/core/commit/b14f4a505b343b12be846f2455d461027a51641c)), closes [#1806](https://github.com/vuejs/core/issues/1806)\n- **compiler-core:** generate NEED_PATCH flag for element with vnode hooks ([24041b7](https://github.com/vuejs/core/commit/24041b7ac1a22ca6c10bf2af81c9250af26bda34))\n- **compiler-core:** v-if key error should only be checking same key on different branches ([de0c8a7](https://github.com/vuejs/core/commit/de0c8a7e3e8d2adfae4c4ef992cd5ac6262ca534))\n- **compiler-sfc:** custom blocks sourcemap ([#1812](https://github.com/vuejs/core/issues/1812)) ([619efd9](https://github.com/vuejs/core/commit/619efd9ac5a0d38651b7282722e7b347a013411a))\n- **keep-alive:** fix activated hook invocation on nested components ([#1743](https://github.com/vuejs/core/issues/1743)) ([233d191](https://github.com/vuejs/core/commit/233d191d0d33802cdf7e2996569372a6442e236a)), closes [#1742](https://github.com/vuejs/core/issues/1742)\n- **reactivity:** accept subtypes of collections ([#1864](https://github.com/vuejs/core/issues/1864)) ([d005b57](https://github.com/vuejs/core/commit/d005b578b183f165929e1f921584ce599178cad6))\n- **reactivity:** effect should still check sync self-trigger ([ac81dcf](https://github.com/vuejs/core/commit/ac81dcf0cc7f5fc722a0c14d1cc92ece5cc0db07))\n- **reactivity:** readonly+reactive collection should also expose readonly+reactive values ([ed43810](https://github.com/vuejs/core/commit/ed4381020fcea0494f19f11bebabd9108f2dafd7)), closes [#1772](https://github.com/vuejs/core/issues/1772)\n- **reactivity:** use isExtensible instead of isFrozen ([#1753](https://github.com/vuejs/core/issues/1753)) ([2787c34](https://github.com/vuejs/core/commit/2787c34cd436e3ec4656b6986d9d14d57911a7b5)), closes [#1784](https://github.com/vuejs/core/issues/1784)\n- **runtime-core:** avoid manual slot invocation in template expressions interfering with block tracking ([791eff3](https://github.com/vuejs/core/commit/791eff3dfbd6be9ba8d597ecf8d943cd197f9807)), closes [#1745](https://github.com/vuejs/core/issues/1745)\n- **runtime-core:** check if the key is string on undefined property warning ([#1731](https://github.com/vuejs/core/issues/1731)) ([ce78eac](https://github.com/vuejs/core/commit/ce78eac8e9cfa75a1409ce09ce9f02d4899188d3))\n- **runtime-core:** fix beforeUpdate call timing to allow state mutation ([1eb6067](https://github.com/vuejs/core/commit/1eb6067a8598730c67b3b3a4ac459d2723aa858c)), closes [#1899](https://github.com/vuejs/core/issues/1899)\n- **runtime-core:** fix Object props validation for objects with custom toStringTag ([6ccd9ac](https://github.com/vuejs/core/commit/6ccd9ac2bc8ea09978fbb99c272bff6614387e90)), closes [#1872](https://github.com/vuejs/core/issues/1872)\n- **runtime-core:** separate null vs. non-null ref value updates ([#1835](https://github.com/vuejs/core/issues/1835)) ([3991ff0](https://github.com/vuejs/core/commit/3991ff03ceea89bbc149e864f754196d20c81f90)), closes [#1789](https://github.com/vuejs/core/issues/1789) [#1834](https://github.com/vuejs/core/issues/1834)\n- **runtime-core:** should correctly call `beforeEnter` inside `Suspense` ([#1805](https://github.com/vuejs/core/issues/1805)) ([bc6f252](https://github.com/vuejs/core/commit/bc6f252c4abc72bee29aa4766fc6c5ed0a81d7cd)), closes [#1795](https://github.com/vuejs/core/issues/1795)\n- **runtime-core/scheduler:** allow component render functions to trigger itself ([611437a](https://github.com/vuejs/core/commit/611437a3fe5e50a5a6f79e2f8a0ed59e74539626)), closes [#1801](https://github.com/vuejs/core/issues/1801)\n- **runtime-core/scheduler:** only allow watch callbacks to be self-triggering ([09702e9](https://github.com/vuejs/core/commit/09702e95b9a3f68fc1952ef74555dffa92d50032)), closes [#1740](https://github.com/vuejs/core/issues/1740) [#1727](https://github.com/vuejs/core/issues/1727)\n- **runtime-core/scheduler:** prevent duplicate queue ([#1767](https://github.com/vuejs/core/issues/1767)) ([b2a9142](https://github.com/vuejs/core/commit/b2a91429ede9ea49e4808de2748da19deeb7f335))\n- **runtime-core/scheduler:** sort postFlushCbs to ensure refs are set before lifecycle hooks ([#1854](https://github.com/vuejs/core/issues/1854)) ([caccec3](https://github.com/vuejs/core/commit/caccec3f78414ae294f1a813ffd16791d56da3a6)), closes [#1852](https://github.com/vuejs/core/issues/1852)\n- **runtime-dom:** fix v-on same computed handler on multiple elements ([1c967fc](https://github.com/vuejs/core/commit/1c967fc44b971686d5a0e2811deb2362ec84979f)), closes [#1747](https://github.com/vuejs/core/issues/1747)\n- **runtime-dom:** patch `form` as an attribute ([#1788](https://github.com/vuejs/core/issues/1788)) ([00683fc](https://github.com/vuejs/core/commit/00683fce9a1c6856be23b35ff0226d8ac5c96791)), closes [#1787](https://github.com/vuejs/core/issues/1787)\n- **runtime-dom:** style binding multi value support ([0cd98c3](https://github.com/vuejs/core/commit/0cd98c3040a64df4577d188b9f2221224549a132)), closes [#1759](https://github.com/vuejs/core/issues/1759)\n- **runtome-core:** do not cache property access in beforeCreate hook ([f6afe70](https://github.com/vuejs/core/commit/f6afe7000efb964355c439b7963087ab8e42d6b1)), closes [#1756](https://github.com/vuejs/core/issues/1756)\n- **teleport:** always inherit root DOM nodes on patch ([#1836](https://github.com/vuejs/core/issues/1836)) ([517c2b8](https://github.com/vuejs/core/commit/517c2b8bdb9ffa53717c10d604ff6db84d50d4f2)), closes [#1813](https://github.com/vuejs/core/issues/1813)\n- **transition:** transition should accept multiple handlers on same event ([48576e5](https://github.com/vuejs/core/commit/48576e582c4177572c2fd1764fbca53a6a30abe2)), closes [#1746](https://github.com/vuejs/core/issues/1746)\n- **types:** handling PropType<Function> with default value ([#1896](https://github.com/vuejs/core/issues/1896)) ([c2913d5](https://github.com/vuejs/core/commit/c2913d57d14449775faf1f2e5647e6d1f3d3f920)), closes [#1891](https://github.com/vuejs/core/issues/1891)\n- **types/jsx:** update innerHTML property in jsx typing ([#1814](https://github.com/vuejs/core/issues/1814)) ([b984d47](https://github.com/vuejs/core/commit/b984d47ac43a0aae2db5556a138a256fb5533ced))\n- **watch:** allow handler to be a string ([#1775](https://github.com/vuejs/core/issues/1775)) ([b5f91ff](https://github.com/vuejs/core/commit/b5f91ff570244436aa8f579ec3a6fec781d198a7)), closes [#1774](https://github.com/vuejs/core/issues/1774)\n- **watch:** exhaust pre-flush watchers + avoid duplicate render by pre-flush watchers ([a0e34ce](https://github.com/vuejs/core/commit/a0e34cee4a09a14548bf1e78f4a82702e9d40717)), closes [#1777](https://github.com/vuejs/core/issues/1777)\n- **watch:** pre-flush watcher watching props should trigger before component update ([d4c17fb](https://github.com/vuejs/core/commit/d4c17fb48b7880a4e3db6d48f8ab76540a3f59a2)), closes [#1763](https://github.com/vuejs/core/issues/1763)\n- **watch:** should trigger watcher callback on triggerRef when watching ref source ([fce2689](https://github.com/vuejs/core/commit/fce2689ff1af0b632a2034403a6dfbcbff91aa60)), closes [#1736](https://github.com/vuejs/core/issues/1736)\n\n### Features\n\n- **compiler-core:** add `comments` parser option ([#1858](https://github.com/vuejs/core/issues/1858)) ([62b9d02](https://github.com/vuejs/core/commit/62b9d02f6fbb08d51bed73f33435c1ed83d5b2ea))\n- **reactivity:** return array when calling `toRefs` on array ([#1768](https://github.com/vuejs/core/issues/1768)) ([4172fdb](https://github.com/vuejs/core/commit/4172fdb90cd75d5741f843a227cfe9b5f5b22b35)), closes [#1764](https://github.com/vuejs/core/issues/1764)\n- **runtime-core:** pass current props to prop default value functions ([0d508e9](https://github.com/vuejs/core/commit/0d508e9f51734409ac1aa57ba0ea98808be0a3a3)), closes [#1886](https://github.com/vuejs/core/issues/1886)\n\n# [3.0.0-rc.5](https://github.com/vuejs/core/compare/v3.0.0-rc.4...v3.0.0-rc.5) (2020-07-28)\n\n### Bug Fixes\n\n- **build:** fix component resolution when disabling options API ([a75b8a2](https://github.com/vuejs/core/commit/a75b8a268fca800a49c7d772b4a290b4435e85b9)), closes [#1688](https://github.com/vuejs/core/issues/1688)\n- **compiler-core:** always compile Teleport and Suspense as blocks ([fbf865d](https://github.com/vuejs/core/commit/fbf865d9d4744a0233db1ed6e5543b8f3ef51e8d))\n- **compiler-core:** prevent generating invalid code for v-bind with empty expression ([#1720](https://github.com/vuejs/core/issues/1720)) ([d452723](https://github.com/vuejs/core/commit/d4527230e40c4728e5becdd35c3e039f0992ae4c))\n- **compiler-core/v-on:** only cache empty handler when the option is used ([5fbd1f4](https://github.com/vuejs/core/commit/5fbd1f4ccb22bf62bdf749460f8c6dadee3b6b89)), closes [#1716](https://github.com/vuejs/core/issues/1716)\n- **compiler-sfc:** `less` and `stylus` output deps path is absolute p… ([#1685](https://github.com/vuejs/core/issues/1685)) ([578f25c](https://github.com/vuejs/core/commit/578f25c34efab0a71a7afd8bff278bd147a16a64))\n- **compiler-sfc:** fix rewrite named export default ([#1675](https://github.com/vuejs/core/issues/1675)) ([452edb7](https://github.com/vuejs/core/commit/452edb73cb02c4aecb518a45df9b01aaa1516b19))\n- **hmr:** should update el for `HYDRATE_EVENTS` patchFlags node ([#1707](https://github.com/vuejs/core/issues/1707)) ([de62cc0](https://github.com/vuejs/core/commit/de62cc040c22e3bd93222a9cc84b6564a4b08b51))\n- **reactivity:** avoid tracking internal symbols in has trap ([7edfdf7](https://github.com/vuejs/core/commit/7edfdf7e239ef8f58a343f9802d675d84ed51d64)), closes [#1683](https://github.com/vuejs/core/issues/1683)\n- **reactivity:** fix ref mutation debugger event values ([b7ef38b](https://github.com/vuejs/core/commit/b7ef38b7731a16b6fa4391978132ee379a1bbdc2))\n- **runtime-core:** dev root resolution should differentiate user comments vs v-if comments ([355c052](https://github.com/vuejs/core/commit/355c05262252b247ec29ed4c4fd6ab69143dd6b7)), closes [#1704](https://github.com/vuejs/core/issues/1704)\n- **runtime-core:** fix scheduler dedupe when not flushing ([4ef5c8d](https://github.com/vuejs/core/commit/4ef5c8d42408fd444114604292106c0027600fa4))\n- **runtime-core:** respect render function from mixins ([354d79c](https://github.com/vuejs/core/commit/354d79c42bf152643b77d83520757818d913de4f)), closes [#1630](https://github.com/vuejs/core/issues/1630)\n- **runtime-core:** scheduler should allow intentional self triggering effects ([c27dfe1](https://github.com/vuejs/core/commit/c27dfe1d0994c65de601760d082cf4668dc3fad0)), closes [#1727](https://github.com/vuejs/core/issues/1727)\n- **runtime-core:** use correct container for moving `Teleport` content ([#1703](https://github.com/vuejs/core/issues/1703)) ([04a4eba](https://github.com/vuejs/core/commit/04a4ebaaeb4418d211293fc7b92c19c42a425cbd))\n- **style-vars:** fix css vars on component with suspense as root ([#1718](https://github.com/vuejs/core/issues/1718)) ([07ece2e](https://github.com/vuejs/core/commit/07ece2e9260fe30a50e7cf317d2ff69f113ecad1))\n- **v-model:** enable v-model type detection on custom elements ([0b3b1cf](https://github.com/vuejs/core/commit/0b3b1cfa487a359c8762794cfd74726d55b9ef8f))\n- runtime compilation marker should be applied in exposed compile function ([b3b65b4](https://github.com/vuejs/core/commit/b3b65b40582d7fbdc776bfe8a1542b80aebe0aac))\n- **transition:** should call transition hooks inside already resolved suspense ([#1698](https://github.com/vuejs/core/issues/1698)) ([2a633c8](https://github.com/vuejs/core/commit/2a633c84ff0e522a7562d3194a8f4e4012eb8281)), closes [#1689](https://github.com/vuejs/core/issues/1689)\n- **v-model:** allow v-model usage on declared custom elements ([71c3c6e](https://github.com/vuejs/core/commit/71c3c6e2a03095ddd4c2a1e15957afd3ec8d4120)), closes [#1699](https://github.com/vuejs/core/issues/1699)\n\n### Features\n\n- **reactivity:** `proxyRefs` method and `ShallowUnwrapRefs` type ([#1682](https://github.com/vuejs/core/issues/1682)) ([aa06b10](https://github.com/vuejs/core/commit/aa06b1034d8268fa15cb6b4b6916440701238b2d))\n- **sfc:** support resolving template components from `<script setup>` exports ([6f5d840](https://github.com/vuejs/core/commit/6f5d840612dbced2dbb4584c979a8f0cfc1f72f0))\n- support delimiters option for runtime compilation ([ba17c87](https://github.com/vuejs/core/commit/ba17c871d80f833e064a51900d07efa358eafb89)), closes [#1679](https://github.com/vuejs/core/issues/1679)\n\n### BREAKING CHANGES\n\n- **reactivity:** template auto ref unwrapping are now applied shallowly,\n  i.e. only at the root level. See https://github.com/vuejs/core/pull/1682 for\n  more details.\n\n# [3.0.0-rc.4](https://github.com/vuejs/core/compare/v3.0.0-rc.3...v3.0.0-rc.4) (2020-07-21)\n\n### Bug Fixes\n\n- **deps:** move @babel/types back to dependencies ([11c2ad4](https://github.com/vuejs/core/commit/11c2ad4a04c000ea828a0f5017e41fc7e0816868))\n\n# [3.0.0-rc.3](https://github.com/vuejs/core/compare/v3.0.0-rc.2...v3.0.0-rc.3) (2020-07-21)\n\n### Bug Fixes\n\n- **build:** make transition tree-shakeable again ([ad199e1](https://github.com/vuejs/core/commit/ad199e1a252f80c85a8e40a4b4539ad27c39505c))\n- **compiler-sfc:** `<style vars scoped>` prefixing should only apply to pre-transform source ([4951d43](https://github.com/vuejs/core/commit/4951d4352605eb9f4bcbea40ecc68fc6cbc3dce2)), closes [#1623](https://github.com/vuejs/core/issues/1623)\n- **compiler-sfc:** use correct importer with `useCssVars` ([#1658](https://github.com/vuejs/core/issues/1658)) ([6f148d0](https://github.com/vuejs/core/commit/6f148d0b9a0630dc87c741ed951c82b639e776b2))\n- **runtime-core:** do not use bail patchFlag on cloned vnodes ([6390ddf](https://github.com/vuejs/core/commit/6390ddfb7d0ed83ac4bae15d0497cba4de3e1972)), closes [#1665](https://github.com/vuejs/core/issues/1665)\n- **runtime-core:** fix attr fallthrough on compiled framgent w/ single static element + comments ([1af3531](https://github.com/vuejs/core/commit/1af35317195772ea8f2728abc8f5ac159a5b7b75))\n- **v-model:** v-model listeners should not fallthrough to plain element root ([c852bf1](https://github.com/vuejs/core/commit/c852bf18d7a51be0c3255357f0c30f39ae9bb540)), closes [#1643](https://github.com/vuejs/core/issues/1643)\n- **watch:** fix watching reactive array ([#1656](https://github.com/vuejs/core/issues/1656)) ([288b4ea](https://github.com/vuejs/core/commit/288b4eab9e10187eb14d4d6d54dc9f077343a2a5)), closes [#1655](https://github.com/vuejs/core/issues/1655)\n\n### Features\n\n- **compiler-core/internal:** add `onContextCreated` option to `generate` ([#1672](https://github.com/vuejs/core/issues/1672)) ([615dccd](https://github.com/vuejs/core/commit/615dccd00e7d85a3f4b82e62d6cb6c41f167d8c6))\n- **runtime-core:** respect function name when using `defineComponent` function shorthand ([#1661](https://github.com/vuejs/core/issues/1661)) ([304830a](https://github.com/vuejs/core/commit/304830a764cd9f28098cfb0ac0e520e1bb2f57c7))\n- provide ability to overwrite feature flags in esm-bundler builds ([54727f9](https://github.com/vuejs/core/commit/54727f9874abe8d0c99ee153d252269ae519b45d))\n- **computed:** add readonly flag if no setter is provided ([#1654](https://github.com/vuejs/core/issues/1654)) ([dabdc5e](https://github.com/vuejs/core/commit/dabdc5e115514f98b5f8559a3819e96416939f43))\n\n# [3.0.0-rc.2](https://github.com/vuejs/core/compare/v3.0.0-rc.1...v3.0.0-rc.2) (2020-07-19)\n\n### Bug Fixes\n\n- **compiler-core:** fix v-if + v-for on `<template>` ([af7e100](https://github.com/vuejs/core/commit/af7e100ef229e1088abfd270a71c5a7da44e760e)), closes [#1637](https://github.com/vuejs/core/issues/1637)\n- **compiler-core/v-on:** fix codegen for event handler with newlines ([#1640](https://github.com/vuejs/core/issues/1640)) ([f9826fa](https://github.com/vuejs/core/commit/f9826fa963e67c495b8c44efb22b09b87df381de))\n- **compiler-sfc:** use `filename` from options when compile styl preprocessor ([#1635](https://github.com/vuejs/core/issues/1635)) ([0526e5d](https://github.com/vuejs/core/commit/0526e5d7faa9ba69f76e7ff71fe96d93a4e99684))\n- **keep-alive:** handle \"0\" as cache key ([#1622](https://github.com/vuejs/core/issues/1622)) ([2deb0c7](https://github.com/vuejs/core/commit/2deb0c7a74d20e334bb1458bc2f28d65aeea704b)), closes [#1621](https://github.com/vuejs/core/issues/1621)\n- **runtime-core/hmr:** only use cloneNode mount optimization in prod ([4655d69](https://github.com/vuejs/core/commit/4655d699831b3356bb8be5b41c45da830dac9eb2)), closes [#1626](https://github.com/vuejs/core/issues/1626)\n- **watch:** callback not called when using `flush:sync` ([#1633](https://github.com/vuejs/core/issues/1633)) ([8facaef](https://github.com/vuejs/core/commit/8facaefcc3eff1ca1fa19832172495e4272979e5))\n\n# [3.0.0-rc.1](https://github.com/vuejs/core/compare/v3.0.0-beta.24...v3.0.0-rc.1) (2020-07-17)\n\n### Bug Fixes\n\n- **watch:** post flush watchers should not fire when component is unmounted ([341b30c](https://github.com/vuejs/core/commit/341b30c961aa065fc59f0c2b592a11229cb6bd14)), closes [#1603](https://github.com/vuejs/core/issues/1603)\n\n### Features\n\n- **types:** deny unknown attributes on component by default ([#1614](https://github.com/vuejs/core/issues/1614)) ([5d8a64d](https://github.com/vuejs/core/commit/5d8a64d53a27ad57fe9940dd0d4d745dfbaf3c9e)), closes [#1519](https://github.com/vuejs/core/issues/1519)\n- **types:** expose `DeepReadonly` type ([#1606](https://github.com/vuejs/core/issues/1606)) ([527c2c8](https://github.com/vuejs/core/commit/527c2c8bbb5c8fcfdf827dd985a09d7e7388cdad))\n- Initial devtools support ([#1125](https://github.com/vuejs/core/issues/1125)) ([568b6db](https://github.com/vuejs/core/commit/568b6db12b9fa167569809dc0da7e0e3c026f204))\n\n# [3.0.0-beta.24](https://github.com/vuejs/core/compare/v3.0.0-beta.23...v3.0.0-beta.24) (2020-07-16)\n\n### Bug Fixes\n\n- **compiler-sfc:** fix preprocessor filename access ([9cb29ee](https://github.com/vuejs/core/commit/9cb29eea3a61f7f4a6730fed56f2e3e9a13dbcc9))\n\n# [3.0.0-beta.23](https://github.com/vuejs/core/compare/v3.0.0-beta.22...v3.0.0-beta.23) (2020-07-16)\n\n### Bug Fixes\n\n- **compiler-sfc:** fix `useCssVars` codegen ([9b5ff2b](https://github.com/vuejs/core/commit/9b5ff2b567f5e29cc59e23e106f2278c3feaad21))\n- **compiler-sfc:** prohibit src usage for `<script setup>` + do not ([af4b0c2](https://github.com/vuejs/core/commit/af4b0c2cf18b63990bc266eb0871a50ba2004fc0))\n- **runtime-dom:** unref when setting `useCssVars` ([44e6da1](https://github.com/vuejs/core/commit/44e6da1402fa2b6f5a0a0c692cd693a8ff1a40a3))\n- **slots:** properly force update on forwarded slots ([aab99ab](https://github.com/vuejs/core/commit/aab99abd28a5d17f2d1966678b0d334975d21877)), closes [#1594](https://github.com/vuejs/core/issues/1594)\n\n### Features\n\n- **compiler-sfc:** export dependencies for css and css preprocessors ([#1278](https://github.com/vuejs/core/issues/1278)) ([e41d831](https://github.com/vuejs/core/commit/e41d8310de0d9299fce2bccd57af4e30b74e3795))\n\n### Performance Improvements\n\n- **runtime-core:** avoid duplicate `postFlushCb` invocation ([165068d](https://github.com/vuejs/core/commit/165068dbc295bb70fdec9ae56dfcaac17d2f977c)), closes [#1595](https://github.com/vuejs/core/issues/1595)\n\n# [3.0.0-beta.22](https://github.com/vuejs/core/compare/v3.0.0-beta.21...v3.0.0-beta.22) (2020-07-15)\n\n### Bug Fixes\n\n- **compiler-core:** generate incremental keys for `v-if/else-if/else` chains ([#1589](https://github.com/vuejs/core/issues/1589)) ([64c7b2f](https://github.com/vuejs/core/commit/64c7b2f9cedae676ec26a7a8da4c109bc88b48f1)), closes [#1587](https://github.com/vuejs/core/issues/1587)\n- **compiler-sfc:** `<script setup>` warning ([9146cc4](https://github.com/vuejs/core/commit/9146cc485e317ff29192796f9366471144ed3ad2))\n- **hmr:** fix hmr updates for reused hoisted trees ([5f61aa0](https://github.com/vuejs/core/commit/5f61aa0f719cbd90182af1e27fad37b91c2c351e))\n- **runtime-core:** do not call transition enter hooks when mounting in suspense ([#1588](https://github.com/vuejs/core/issues/1588)) ([246ec5c](https://github.com/vuejs/core/commit/246ec5c594650f3fcccd0de94aa3f97b4d705e42)), closes [#1583](https://github.com/vuejs/core/issues/1583)\n- **v-model:** handle more edge cases in `looseEqual()` ([#379](https://github.com/vuejs/core/issues/379)) ([fe1b27b](https://github.com/vuejs/core/commit/fe1b27b7f875e1c8aece12b04531e7fa3184be27))\n\n### Features\n\n- **types/reactivity:** use `DeepReadonly` type for `readonly` return type ([#1462](https://github.com/vuejs/core/issues/1462)) ([b772bba](https://github.com/vuejs/core/commit/b772bba5587726e78b20ccb9b61374120bd4b0ae)), closes [#1452](https://github.com/vuejs/core/issues/1452)\n\n# [3.0.0-beta.21](https://github.com/vuejs/core/compare/v3.0.0-beta.20...v3.0.0-beta.21) (2020-07-14)\n\n### Bug Fixes\n\n- **compiler-dom:** fix v-on `.left` `.right` modifier handling ([6b63ba2](https://github.com/vuejs/core/commit/6b63ba2f453b3f9bbf9e9e2167030de42f76b5ac))\n- **runtime-core:** avoid `scopeId` as attr for slot nodes with same `scopeId` ([#1561](https://github.com/vuejs/core/issues/1561)) ([583a1c7](https://github.com/vuejs/core/commit/583a1c7b45e67e9cd57e411853c20509248def89)), closes [vitejs/vite#536](https://github.com/vitejs/vite/issues/536)\n- **runtime-core/emits:** merge emits options from mixins/extends ([ba3b3cd](https://github.com/vuejs/core/commit/ba3b3cdda98f6efb5d4c4fafc579b8f568a19bde)), closes [#1562](https://github.com/vuejs/core/issues/1562)\n- **runtime-dom:** remove attrs with nullish values ([cb6a091](https://github.com/vuejs/core/commit/cb6a0915c540af94f5d79c311022b99bc17f2965)), closes [#1576](https://github.com/vuejs/core/issues/1576)\n- **runtime-dom/v-on:** only block event handlers based on attach timestamp ([8b320cc](https://github.com/vuejs/core/commit/8b320cc12f74aafea9ec69f7ce70231d4f0d08fd)), closes [#1565](https://github.com/vuejs/core/issues/1565)\n- **slots:** differentiate dynamic/static compiled slots ([65beba9](https://github.com/vuejs/core/commit/65beba98fe5793133d3218945218b9e3f8d136eb)), closes [#1557](https://github.com/vuejs/core/issues/1557)\n- **v-on:** capitalize dynamic event names ([9152a89](https://github.com/vuejs/core/commit/9152a8901653d7cef864a52a3c618afcc70d827d))\n- **v-on:** refactor DOM event options modifier handling ([380c679](https://github.com/vuejs/core/commit/380c6792d8899f1a43a9e6400c5df483c63290b6)), closes [#1567](https://github.com/vuejs/core/issues/1567)\n\n### Features\n\n- ssr support for `<style vars>` ([b9595e6](https://github.com/vuejs/core/commit/b9595e64cfdfc2607d3d3e6232b4a7ea199dd553))\n- **compiler-sfc:** `<script setup>` support (experimental) ([4c43d4e](https://github.com/vuejs/core/commit/4c43d4e5b9df8732b601a269bf4030f9721d466f))\n- **compiler-sfc:** `<style vars>` CSS variable injection ([bd5c3b9](https://github.com/vuejs/core/commit/bd5c3b96be2c6c4a0b84b096c3baa3c30feb95d6))\n- **compiler-sfc:** allow using :deep, :global & :slotted for short in `<style scoped>` ([f3cc41f](https://github.com/vuejs/core/commit/f3cc41f0c8713475f2aa592bae3d82ffbc6b1300))\n- **runtime-dom:** useCssVars ([9f706a9](https://github.com/vuejs/core/commit/9f706a9f5ee52c8256c52111da4271bf43b811ab))\n\n# [3.0.0-beta.20](https://github.com/vuejs/core/compare/v3.0.0-beta.19...v3.0.0-beta.20) (2020-07-08)\n\n### Bug Fixes\n\n- **compiler-core/v-on:** bail caching for member expression handlers on components ([87c2a1e](https://github.com/vuejs/core/commit/87c2a1e50f5317a0c47051b06f419e60e5644a1a)), closes [#1541](https://github.com/vuejs/core/issues/1541)\n- **compiler-dom:** should ignore and warn side effect tags like script and style ([5e52f4e](https://github.com/vuejs/core/commit/5e52f4e4d7c92ee8ec9c0d644735e23342965096))\n- **runtime-core:** should allow v-model listeners to fallthrough, but ignore for warning ([903e8f6](https://github.com/vuejs/core/commit/903e8f697e4377e0ae92e1a6b58777438fba3610)), closes [#1543](https://github.com/vuejs/core/issues/1543)\n\n### Features\n\n- **types:** expose `WritableComputedRef` ([#1500](https://github.com/vuejs/core/issues/1500)) ([220db9b](https://github.com/vuejs/core/commit/220db9bcda17a56bb4e5222d2634800672513983))\n\n# [3.0.0-beta.19](https://github.com/vuejs/core/compare/v3.0.0-beta.18...v3.0.0-beta.19) (2020-07-07)\n\n### Bug Fixes\n\n- **compiler-core:** add `\\r` to accepted chars after end tag name ([#1515](https://github.com/vuejs/core/issues/1515)) ([64e2f46](https://github.com/vuejs/core/commit/64e2f4643602c5980361e66674141e61ba60ef70)), closes [#1476](https://github.com/vuejs/core/issues/1476)\n- **keep-alive:** fix keep-alive with scopeId/fallthrough attrs ([d86b01b](https://github.com/vuejs/core/commit/d86b01ba3a29e2e04c13597a1b9123ca35beaf57)), closes [#1511](https://github.com/vuejs/core/issues/1511)\n- **runtime-core/template-ref:** template ref used in the same template should trigger update ([36b6b4f](https://github.com/vuejs/core/commit/36b6b4f0228c4adf679c232bf4d1e8cff7fb6474)), closes [#1505](https://github.com/vuejs/core/issues/1505)\n- **runtime-dom:** should set `<input list=\"...\">` as attribute ([441c236](https://github.com/vuejs/core/commit/441c23602f57d00b00fa3a590b30487003efe210)), closes [#1526](https://github.com/vuejs/core/issues/1526)\n- **runtime-dom/style:** fix `patchStyle` on falsy next value ([#1504](https://github.com/vuejs/core/issues/1504)) ([77538ec](https://github.com/vuejs/core/commit/77538ec6d90fee66d229d6d3a4f977c6b548a9bd)), closes [#1506](https://github.com/vuejs/core/issues/1506)\n- **ssr:** support dynamic components that resolve to element or vnode ([41db49d](https://github.com/vuejs/core/commit/41db49dfb7c520c4f743e522a03f06b33259a2eb)), closes [#1508](https://github.com/vuejs/core/issues/1508)\n- **types/tsx:** add `JSX.IntrinsicAttributes` definition ([#1517](https://github.com/vuejs/core/issues/1517)) ([a5b4332](https://github.com/vuejs/core/commit/a5b4332c69146de569ad328cac9224c3cded15c9)), closes [#1516](https://github.com/vuejs/core/issues/1516)\n- **v-model:** consistent nullish value handling with 2.x ([#1530](https://github.com/vuejs/core/issues/1530)) ([425335c](https://github.com/vuejs/core/commit/425335c28bdb48f2f48f97021fc0a77eaa89ec34)), closes [#1528](https://github.com/vuejs/core/issues/1528)\n- **v-model:** should ignore compiled v-model listeners in attr fallthrough ([6dd59ee](https://github.com/vuejs/core/commit/6dd59ee301d8d93e7ca14447243d07a653e69159)), closes [#1510](https://github.com/vuejs/core/issues/1510)\n- **watch:** stop instance-bound watchers in post render queue ([58b0706](https://github.com/vuejs/core/commit/58b07069ad33c8a8e44cb47b81084a452dda2846)), closes [#1525](https://github.com/vuejs/core/issues/1525)\n\n# [3.0.0-beta.18](https://github.com/vuejs/core/compare/v3.0.0-beta.16...v3.0.0-beta.18) (2020-07-02)\n\n### Bug Fixes\n\n- **runtime-core:** avoid accidental access of `Object.prototype` properties ([f3e9c1b](https://github.com/vuejs/core/commit/f3e9c1b59d5d3999ac6180ed75c84d88b29c41e6))\n- ensure vnode hooks are called consistently regardless of keep-alive ([4e8e689](https://github.com/vuejs/core/commit/4e8e689572dcae0cb468989c5e0c531a837a900b))\n- **runtime-core:** pass unmount into initial mount patch prop ([2bdb5c1](https://github.com/vuejs/core/commit/2bdb5c146449092623f06e20fb71ebaca7e5588f))\n- **runtime-dom:** allow force updating value bindings for controlled inputs ([b3536d8](https://github.com/vuejs/core/commit/b3536d87a587dc1e78c8712cb29ca61ca0931ac9)), closes [#1471](https://github.com/vuejs/core/issues/1471)\n- **slots:** make compiled slot marker non-enumerable ([062835d](https://github.com/vuejs/core/commit/062835d45aaf4168ddf2e39a5c7e162b3a18ccae)), closes [#1470](https://github.com/vuejs/core/issues/1470)\n\n### Features\n\n- **runtime-core:** support creating vnode from existing vnode ([c9629f2](https://github.com/vuejs/core/commit/c9629f26924fcb3c51994549a3013ccc05c1030a))\n\n# [3.0.0-beta.17](https://github.com/vuejs/core/compare/v3.0.0-beta.16...v3.0.0-beta.17) (2020-06-30)\n\n### Bug Fixes\n\n- **runtime-dom:** allow force updating value bindings for controlled inputs ([b3536d8](https://github.com/vuejs/core/commit/b3536d87a587dc1e78c8712cb29ca61ca0931ac9)), closes [#1471](https://github.com/vuejs/core/issues/1471)\n- **slots:** make compiled slot marker non-enumerable ([062835d](https://github.com/vuejs/core/commit/062835d45aaf4168ddf2e39a5c7e162b3a18ccae)), closes [#1470](https://github.com/vuejs/core/issues/1470)\n\n# [3.0.0-beta.16](https://github.com/vuejs/core/compare/v3.0.0-beta.15...v3.0.0-beta.16) (2020-06-29)\n\n### Bug Fixes\n\n- **BaseTransition:** collect correct children with slot passthrough in `Transition` ([#1456](https://github.com/vuejs/core/issues/1456)) ([d4cd128](https://github.com/vuejs/core/commit/d4cd12887eba18c4aff02b85834679bfe679f878)), closes [#1455](https://github.com/vuejs/core/issues/1455)\n- **BaseTransition:** fix `BaseTransition` delayed leave with mode `in-out` ([#1404](https://github.com/vuejs/core/issues/1404)) ([2ff8dca](https://github.com/vuejs/core/commit/2ff8dcab0a51cc3634a0a739641fb4cfe459b731)), closes [#1400](https://github.com/vuejs/core/issues/1400)\n- **compiler-core:** ignore comment nodes in transition children ([e52b7cd](https://github.com/vuejs/core/commit/e52b7cd7e7c10d8dbad92000ab3d5f2e02533e39)), closes [#1352](https://github.com/vuejs/core/issues/1352)\n- **compiler-core:** should not prefix object method ([#1375](https://github.com/vuejs/core/issues/1375)) ([35dbef2](https://github.com/vuejs/core/commit/35dbef268ca43234aa8544a62dfa4240dcc2974e))\n- **compiler-core:** skip empty expressions when validating expressions in browser mode ([afb231e](https://github.com/vuejs/core/commit/afb231ec5ce5ac77ff6260bea4d866ec2d5bbd85))\n- **compiler-core/v-on:** pass noninitial arguments in cached event handlers ([#1265](https://github.com/vuejs/core/issues/1265)) ([7e28173](https://github.com/vuejs/core/commit/7e281733120fe003552b915f97713a3d26f4dc8a))\n- **compiler-sfc:** `transformAssetUrl` should ignore inline data url ([#1431](https://github.com/vuejs/core/issues/1431)) ([90c285c](https://github.com/vuejs/core/commit/90c285c5c8ac13afb4932974c1f9aede15e81337))\n- **runtime-core:** always check props presence in public instance proxy ([e0d19a6](https://github.com/vuejs/core/commit/e0d19a695316a8a459274874d304872fea384851)), closes [#1236](https://github.com/vuejs/core/issues/1236)\n- **runtime-core:** `cloneVNode` should preserve correct ctx instance when normalizing ref ([be69bee](https://github.com/vuejs/core/commit/be69beed5ed05067006c297589598b33e7108b1b)), closes [#1311](https://github.com/vuejs/core/issues/1311)\n- **runtime-core:** component root should inherit `scopeId` from `VNode` ([f3f94e4](https://github.com/vuejs/core/commit/f3f94e4deb40d3a0d83804454874833b194f83da)), closes [#1399](https://github.com/vuejs/core/issues/1399)\n- **runtime-core:** fix component name inference in warnings ([e765d81](https://github.com/vuejs/core/commit/e765d814048c2cdc3cc32bdffb73c6e59b0d747d)), closes [#1418](https://github.com/vuejs/core/issues/1418)\n- **runtime-core:** fix parent el update on nested HOC self-update ([#1360](https://github.com/vuejs/core/issues/1360)) ([6c8bfa1](https://github.com/vuejs/core/commit/6c8bfa10189d1a5a6837d2e25a9451889a0e19d6)), closes [#1357](https://github.com/vuejs/core/issues/1357)\n- **runtime-core:** fix `scopeId` inheritance for component inside slots ([978d952](https://github.com/vuejs/core/commit/978d9522e80cb19257ee2f4c8ba5da6f8aa6b3d2))\n- **runtime-core:** handle patch flag de-op from cloned vnode ([0dd5cde](https://github.com/vuejs/core/commit/0dd5cde861735e80cfe21537380e52789cc865f8)), closes [#1426](https://github.com/vuejs/core/issues/1426)\n- **runtime-core:** properly capitalize v-on object keys ([#1358](https://github.com/vuejs/core/issues/1358)) ([250eb4a](https://github.com/vuejs/core/commit/250eb4a5bc121d303aa109c20251c95616049f05))\n- **runtime-core:** should remove no longer present camelCase props ([#1413](https://github.com/vuejs/core/issues/1413)) ([1c4e1b6](https://github.com/vuejs/core/commit/1c4e1b679261ad151c4ed04b11279a3768a1c9e2)), closes [#1412](https://github.com/vuejs/core/issues/1412)\n- **slots:** filter out compiler marker from resolved slots ([70ea76a](https://github.com/vuejs/core/commit/70ea76ae0c16a55154e785f8ca42ed13e0d15170)), closes [#1451](https://github.com/vuejs/core/issues/1451)\n- **ssr:** fix ssr scopeId on component root ([afe13e0](https://github.com/vuejs/core/commit/afe13e0584afb70a2682763dda148c35f9a97f95))\n- **ssr:** handle fallthrough attrs in ssr compile output ([d5dbd27](https://github.com/vuejs/core/commit/d5dbd27193eee5fe401d3b85b6c5ddef5cd42b9d))\n- **transition:** enter/leave hook timing consistency with v2 ([bf84ac8](https://github.com/vuejs/core/commit/bf84ac8396666194cd386b8a66040b19131983e0)), closes [#1145](https://github.com/vuejs/core/issues/1145)\n- **transition:** fix appear hooks handling ([7ae70ea](https://github.com/vuejs/core/commit/7ae70ea44cf66be134c6ec3b060d9872fa0774e0))\n- **transition:** fix css:false with hooks with no explicit done callback ([9edbc27](https://github.com/vuejs/core/commit/9edbc27f45aafaa6bc27ab244dc77d4d86d09fc4)), closes [#1149](https://github.com/vuejs/core/issues/1149)\n- **transition:** fix dom transition cancel hooks not being called ([acd3156](https://github.com/vuejs/core/commit/acd3156d2c45609ab04cb54734258fe340c4ca02))\n- **transition-group:** vue 2 compatible handling of transition-group w/ multiple v-for children ([86d3972](https://github.com/vuejs/core/commit/86d3972855990c23f583a4b11b3c86fe04f1ab90)), closes [#1126](https://github.com/vuejs/core/issues/1126)\n- **types:** ensure correct public props interface for `defineComponent` instance type ([2961e14](https://github.com/vuejs/core/commit/2961e149c9825d56680e982acd056d9f337afc5e)), closes [#1385](https://github.com/vuejs/core/issues/1385)\n- **types:** export `ComponentOptionsMixin` ([#1361](https://github.com/vuejs/core/issues/1361)) ([68e2d6c](https://github.com/vuejs/core/commit/68e2d6c68a4e8a95d112597b82d40efb8571d9c0))\n- **types:** should unwrap array -> object -> ref ([82b28a5](https://github.com/vuejs/core/commit/82b28a5ecb95be1565e50427bfd5eefe4b2d408c))\n- **v-show:** fix v-show unmount with falsy value ([#1403](https://github.com/vuejs/core/issues/1403)) ([d7beea0](https://github.com/vuejs/core/commit/d7beea015bdb208d89a2352a5d43cc1913f87337)), closes [#1401](https://github.com/vuejs/core/issues/1401)\n\n### Features\n\n- **runtime-core:** expose version on app instance ([056cac9](https://github.com/vuejs/core/commit/056cac91855e644e94cd704ff5462c4e1acba66b)), closes [#1449](https://github.com/vuejs/core/issues/1449)\n- **ssr:** `renderToStream` ([#1197](https://github.com/vuejs/core/issues/1197)) ([6bc0e0a](https://github.com/vuejs/core/commit/6bc0e0a31a173cfd4cef82230862f269e4d94c94))\n\n### Performance Improvements\n\n- **compiler-core:** treat v-for with constant exp as a stable fragment ([#1394](https://github.com/vuejs/core/issues/1394)) ([8a2cf21](https://github.com/vuejs/core/commit/8a2cf21b717411e4e66f9223e9f6d1c5c817c6ac))\n- **reactivity:** should not track `__v_isRef` ([#1392](https://github.com/vuejs/core/issues/1392)) ([c43a6e6](https://github.com/vuejs/core/commit/c43a6e61a0952c629cfb062f67e8eb27a0f6f227))\n- **ssr:** avoid unnecessary await ticks when unrolling sync buffers ([30584bc](https://github.com/vuejs/core/commit/30584bcc61515eb9200071b8a4780e05c2ab786e))\n\n# [3.0.0-beta.15](https://github.com/vuejs/core/compare/v3.0.0-beta.14...v3.0.0-beta.15) (2020-06-12)\n\n### Bug Fixes\n\n- **build:** retain main vue package side effect for compiler registration ([dc986ad](https://github.com/vuejs/core/commit/dc986addd9f6c57a4d3d13b0f97132064a8d76a4)), closes [#1263](https://github.com/vuejs/core/issues/1263)\n- **compiler-core:** allow multiline expression on v-model and v-on ([#1234](https://github.com/vuejs/core/issues/1234)) ([958b6c8](https://github.com/vuejs/core/commit/958b6c80cf2e07ef6e829b5b5d698fd61c25b91f))\n- **compiler-core:** bail static stringfication even threshold is met ([#1298](https://github.com/vuejs/core/issues/1298)) ([64ec8bf](https://github.com/vuejs/core/commit/64ec8bfb54b97036d9cde765d923443ec8bc02b9)), closes [#1128](https://github.com/vuejs/core/issues/1128)\n- **compiler-core:** fix parsing for directive with dynamic argument containing dots ([0d26413](https://github.com/vuejs/core/commit/0d26413433d41389f5525a0ef2c2dd7cfbb454d4))\n- **compiler-core:** support static slot names containing dots for 2.x compat ([825ec15](https://github.com/vuejs/core/commit/825ec1500feda8b0c43245e7e92074af7f9dcca2)), closes [#1241](https://github.com/vuejs/core/issues/1241)\n- **hmr:** force full update on nested child components ([#1312](https://github.com/vuejs/core/issues/1312)) ([8f2a748](https://github.com/vuejs/core/commit/8f2a7489b7c74f5cfc1844697c60287c37fc0eb8))\n- **reactivity:** fix toRaw for objects prototype inheriting reactive ([10bb34b](https://github.com/vuejs/core/commit/10bb34bb869a47c37d945f8c80abf723fac9fc1a)), closes [#1246](https://github.com/vuejs/core/issues/1246)\n- **runtime-core:** should pass instance to patchProp on mount for event error handling ([#1337](https://github.com/vuejs/core/issues/1337)) ([aac9b03](https://github.com/vuejs/core/commit/aac9b03c11c9be0c67b924004364a42d04d78195)), closes [#1336](https://github.com/vuejs/core/issues/1336)\n- **runtime-core:** track access to $attrs ([6abac87](https://github.com/vuejs/core/commit/6abac87b3d1b7a22df80b7a70a10101a7f3d3732)), closes [#1346](https://github.com/vuejs/core/issues/1346)\n- always treat spellcheck and draggable as attributes ([4492b88](https://github.com/vuejs/core/commit/4492b88938922a7f1bcc36a608375ad99f16b22e)), closes [#1350](https://github.com/vuejs/core/issues/1350)\n- **compiler-core:** fix prod whitespace/comment removal ([f3623e4](https://github.com/vuejs/core/commit/f3623e4d1ea83d552b5ab29955dead6c36a87723)), closes [#1256](https://github.com/vuejs/core/issues/1256)\n- **compiler-dom:** add tfoot,caption,col element on bail stringification ([#1333](https://github.com/vuejs/core/issues/1333)) ([fbaf52a](https://github.com/vuejs/core/commit/fbaf52ae9fdd412e517e7edf44544db5d759dd2c))\n- **compiler-dom:** bail stringification on table elements ([a938b61](https://github.com/vuejs/core/commit/a938b61edca63c1f03f99b85de3f2a3a519268e6)), closes [#1230](https://github.com/vuejs/core/issues/1230) [#1268](https://github.com/vuejs/core/issues/1268)\n- **compiler-sfc:** asset url transform should ignore direct hash urls ([5ddd9d2](https://github.com/vuejs/core/commit/5ddd9d241747ef785de848d19246ef518abd8b8f))\n- **compiler-ssr:** should escape template string interpolation chars in generated code ([5f15d9a](https://github.com/vuejs/core/commit/5f15d9aa4b9024b3764b962bee042d72f94dee91))\n- **hmr:** force full update in child component on slot update ([2408a65](https://github.com/vuejs/core/commit/2408a656627358b21aa49209e64d14a1aeec7825))\n- **reactivity:** replaced ref in reactive object should be tracked ([#1058](https://github.com/vuejs/core/issues/1058)) ([80e1693](https://github.com/vuejs/core/commit/80e1693e1f525a6c5811689fbeaccdccae1e2c23))\n- **reactivity:** shallowReactive collection to not-readonly ([#1212](https://github.com/vuejs/core/issues/1212)) ([c97d1ba](https://github.com/vuejs/core/commit/c97d1bae56c3643304165d0e5b7924e5a0aad2df))\n- **runtime-core:** default value for function type prop ([#1349](https://github.com/vuejs/core/issues/1349)) ([d437a01](https://github.com/vuejs/core/commit/d437a0145df5b63a959da873041816af68b440db)), closes [#1348](https://github.com/vuejs/core/issues/1348)\n- **runtime-core:** mount children before setting element props ([8084156](https://github.com/vuejs/core/commit/8084156f4d0b572716a685a561d5087cddceab2c)), closes [#1318](https://github.com/vuejs/core/issues/1318) [#1320](https://github.com/vuejs/core/issues/1320)\n- **runtime-core:** respect props from mixins and extends ([2417a0c](https://github.com/vuejs/core/commit/2417a0cb302ed72e145986f85422470713edf2d8)), closes [#1236](https://github.com/vuejs/core/issues/1236) [#1250](https://github.com/vuejs/core/issues/1250)\n- **runtime-core:** use array destructuring instead of object for edge compat ([#1302](https://github.com/vuejs/core/issues/1302)) ([4a5021e](https://github.com/vuejs/core/commit/4a5021e763b7f49069e1f3d488bdddf910f09f3f)), closes [#1294](https://github.com/vuejs/core/issues/1294)\n- **runtime-dom:** compatibility for cases where event.timeStamp is 0 ([#1328](https://github.com/vuejs/core/issues/1328)) ([90c3532](https://github.com/vuejs/core/commit/90c35329468e1fbb5cd2c1df2e4efd5b12b4fd41)), closes [#1325](https://github.com/vuejs/core/issues/1325)\n- **ssr:** fix unintended error on `Teleport` hydration mismatch ([#1271](https://github.com/vuejs/core/issues/1271)) ([c463a71](https://github.com/vuejs/core/commit/c463a71bb31f01da55927424533e2ece3a3c4efe)), closes [#1235](https://github.com/vuejs/core/issues/1235)\n- **types:** add RawSlots in h signature ([#1293](https://github.com/vuejs/core/issues/1293)) ([cab769f](https://github.com/vuejs/core/commit/cab769f174f4c0bcad59454e4a77039830e796f8))\n- bail stringification for slots ([9b5d13e](https://github.com/vuejs/core/commit/9b5d13e598686b0a73bc8f4a0f5581f066c3e923)), closes [#1281](https://github.com/vuejs/core/issues/1281) [#1286](https://github.com/vuejs/core/issues/1286)\n- **ssr:** should set ref on hydration ([0a7932c](https://github.com/vuejs/core/commit/0a7932c6b3e6b6fdda27fa7161726a615a598355))\n- run ci ([6b889e7](https://github.com/vuejs/core/commit/6b889e7c8a599c829f9a240fdcdce3299fbd0e6d))\n\n### Features\n\n- **compiler:** better warning for invalid expressions in function/browser mode ([e29f0b3](https://github.com/vuejs/core/commit/e29f0b3fc2b10c76264cdd8e49c2ab4260286fd6)), closes [#1266](https://github.com/vuejs/core/issues/1266)\n- **runtime-core:** add inheritRef option + make `<transition>` & `<keep-alive>` inherit refs ([38f2d23](https://github.com/vuejs/core/commit/38f2d23a607cd7077da189ac274a3a0ad542cc1f))\n- **types:** adjust type exports for manual render function and tooling usage ([e4dc03a](https://github.com/vuejs/core/commit/e4dc03a8b17d5e9f167de6a62a645878ac7ef3e2)), closes [#1329](https://github.com/vuejs/core/issues/1329)\n- **types:** mixins/extends support in TypeScript ([#626](https://github.com/vuejs/core/issues/626)) ([d3c436a](https://github.com/vuejs/core/commit/d3c436ae2e66b75b7f2ed574dadda3f0e1fdce73))\n- **types:** support typing directive value via generic argument ([#1007](https://github.com/vuejs/core/issues/1007)) ([419b86d](https://github.com/vuejs/core/commit/419b86d1908f2a0521e6a7eafcbee764e9ee59a0)), closes [#998](https://github.com/vuejs/core/issues/998)\n- **types:** update to TypeScript 3.9 ([#1106](https://github.com/vuejs/core/issues/1106)) ([97dedeb](https://github.com/vuejs/core/commit/97dedebd8097116a16209664a1ca38392b964da3))\n\n### Performance Improvements\n\n- only patch string style when value has changed ([#1310](https://github.com/vuejs/core/issues/1310)) ([d4e9b19](https://github.com/vuejs/core/commit/d4e9b19932dac686f57091e66f21a80d4c5db881)), closes [#1309](https://github.com/vuejs/core/issues/1309)\n- optimize LRU access in keep-alive ([#1316](https://github.com/vuejs/core/issues/1316)) ([1f2926a](https://github.com/vuejs/core/commit/1f2926a33c78b6a6f4752a01b88f7cad809ed302))\n\n# [3.0.0-beta.14](https://github.com/vuejs/core/compare/v3.0.0-beta.13...v3.0.0-beta.14) (2020-05-18)\n\n### Bug Fixes\n\n- **compiler-dom:** should bail stringification on runtime constant regardless of position ([dd2bfb5](https://github.com/vuejs/core/commit/dd2bfb5a8f5b897a621b3ebb89a9fb1b8e4c63cd)), closes [vuejs/vite#157](https://github.com/vuejs/vite/issues/157)\n- **reactivity:** shallowReactive for collections ([#1204](https://github.com/vuejs/core/issues/1204)) ([488e2bc](https://github.com/vuejs/core/commit/488e2bcfef8dd69d15c224d94a433680db140ef9)), closes [#1202](https://github.com/vuejs/core/issues/1202)\n- **runtime-dom:** event handlers with modifiers should get all event arguments ([#1193](https://github.com/vuejs/core/issues/1193)) ([ab86b19](https://github.com/vuejs/core/commit/ab86b190ce540336a01f936baa836f1aefd90e85))\n- **Transition:** fix validate duration ([#1188](https://github.com/vuejs/core/issues/1188)) ([d73a508](https://github.com/vuejs/core/commit/d73a508a73c03d64cea0c376e25f4f0272728a18))\n- **v-model:** should not trigger updates during input composition ([#1183](https://github.com/vuejs/core/issues/1183)) ([83b7158](https://github.com/vuejs/core/commit/83b7158017325db03e5c677b5f1c6adfe41d1ca4))\n\n### Features\n\n- **watch:** support directly watching reactive object in multiple sources with deep default ([#1201](https://github.com/vuejs/core/issues/1201)) ([ba62ccd](https://github.com/vuejs/core/commit/ba62ccd55d659a874ece4b26454ae31c6de72f59))\n\n# [3.0.0-beta.13](https://github.com/vuejs/core/compare/v3.0.0-beta.12...v3.0.0-beta.13) (2020-05-17)\n\n### Features\n\n- improve static content stringification ([d965bb6](https://github.com/vuejs/core/commit/d965bb6227d53b715cfb797114b9452a6db841ec))\n\n# [3.0.0-beta.12](https://github.com/vuejs/core/compare/v3.0.0-beta.11...v3.0.0-beta.12) (2020-05-11)\n\n### Bug Fixes\n\n- **hmr:** static child traversal should only affect elements ([2bc6a8c](https://github.com/vuejs/core/commit/2bc6a8c1cf4f409eea0cefa8b8a7619aae1f3569))\n\n# [3.0.0-beta.11](https://github.com/vuejs/core/compare/v3.0.0-beta.10...v3.0.0-beta.11) (2020-05-11)\n\n### Bug Fixes\n\n- **hmr:** always force full child component props update in HMR mode ([1b946c8](https://github.com/vuejs/core/commit/1b946c85df3d213900faccfa0723d736fa0927a3))\n- **hmr:** ensure static nodes inherit DOM element in hmr mode ([66c5a55](https://github.com/vuejs/core/commit/66c5a556dc5b27e9a72fa7176fbb45d8c4c515b7)), closes [#1156](https://github.com/vuejs/core/issues/1156)\n- **runtime-core:** should not take unmount children fast path for v-for fragments ([5b8883a](https://github.com/vuejs/core/commit/5b8883a84689dd04dbbcd677bf177ffeda43489d)), closes [#1153](https://github.com/vuejs/core/issues/1153)\n- **transition:** should reset enter class after appear ([#1152](https://github.com/vuejs/core/issues/1152)) ([697de07](https://github.com/vuejs/core/commit/697de07e630c502db42e93e64ba556cc4599cbe4))\n\n### Features\n\n- **runtime-core:** expose isVNode ([a165d82](https://github.com/vuejs/core/commit/a165d8293dbd092828b14530577d45e2af40deda))\n\n# [3.0.0-beta.10](https://github.com/vuejs/core/compare/v3.0.0-beta.9...v3.0.0-beta.10) (2020-05-07)\n\n### Bug Fixes\n\n- **compiler:** warn against v-bind with empty attribute value ([675330b](https://github.com/vuejs/core/commit/675330ba542022935ebbb2d31af3ba643c37a5eb)), closes [github.com/vuejs/core/issues/1128#issuecomment-624647434](https://github.com/vuejs/core/issues/1128#issuecomment-624647434)\n- **compiler-dom:** bail static stringfication on non-attr bindings ([304ab8c](https://github.com/vuejs/core/commit/304ab8c99b954de4aa9ab6a5387116228345f544)), closes [#1128](https://github.com/vuejs/core/issues/1128)\n- **compiler-sfc:** should not transform external asset url with ([d662118](https://github.com/vuejs/core/commit/d66211849ca174c4458b59d3df5569730ee224f6))\n- **compiler-sfc:** template with alt lang should be parsed as raw text ([d10835a](https://github.com/vuejs/core/commit/d10835aee73e3be579c728df634fbaa8fe3a0e0f)), closes [#1120](https://github.com/vuejs/core/issues/1120)\n- **reactivity:** fix `__proto__` access on proxy objects ([#1133](https://github.com/vuejs/core/issues/1133)) ([037fa07](https://github.com/vuejs/core/commit/037fa07113eff6792cda58f91169d26cf6033aea))\n- **reactivity:** use correct thisArg for collection method callbacks ([#1132](https://github.com/vuejs/core/issues/1132)) ([e08f6f0](https://github.com/vuejs/core/commit/e08f6f0ede03d09e71e44de5e524abd9789971d8))\n- **runtime-dom/style:** normalize string when merging styles ([#1127](https://github.com/vuejs/core/issues/1127)) ([2d9f136](https://github.com/vuejs/core/commit/2d9f1360778154a232473fcf93f6164a6bd80ca5))\n\n### Code Refactoring\n\n- **compiler/types:** convert compiler options documentation to jsdoc ([e58beec](https://github.com/vuejs/core/commit/e58beecc97635ea61e39b84ea406fcc42166095b))\n\n### Features\n\n- **compiler-sfc:** improve sfc source map generation ([698c8d3](https://github.com/vuejs/core/commit/698c8d35d55ae6a157d7aad5ffb1f3a27e0b3970))\n- **types:** re-expose trasnformVNodeArgs ([40166a8](https://github.com/vuejs/core/commit/40166a8637a0f0272eb80777650398ccc067af88))\n\n### Performance Improvements\n\n- **compiler-sfc:** improve asset url transform efficiency ([c5dcfe1](https://github.com/vuejs/core/commit/c5dcfe16f6cd3503ce1d5349cfacbe099a7e19be))\n- **compiler-sfc:** only add character mapping if not whitespace ([2f69167](https://github.com/vuejs/core/commit/2f69167e889f2817138629a04c01c6baf565d485))\n\n### BREAKING CHANGES\n\n- **compiler/types:** `getTextMode` compiler option signature has changed from\n\n  ```ts\n  ;(tag: string, ns: string, parent: ElementNode | undefined) => TextModes\n  ```\n\n  to\n\n  ```ts\n  ;(node: ElementNode, parent: ElementNode | undefined) => TextModes\n  ```\n\n# [3.0.0-beta.9](https://github.com/vuejs/core/compare/v3.0.0-beta.8...v3.0.0-beta.9) (2020-05-04)\n\n### Bug Fixes\n\n- **compiler:** bail stringification on runtime constant expressions ([f9a3766](https://github.com/vuejs/core/commit/f9a3766fd68dc6996cdbda6475287c4005f55243))\n- **transitionGroup:** fix transition children resolving condition ([f05aeea](https://github.com/vuejs/core/commit/f05aeea7aec2e6cd859f40edc6236afd0ce2ea7d))\n\n### Features\n\n- **compiler-sfc:** support transforming absolute asset urls ([6a0be88](https://github.com/vuejs/core/commit/6a0be882d4ce95eb8d8093f273ea0e868acfcd24))\n\n### BREAKING CHANGES\n\n- **compiler-sfc:** `@vue/compiler-sfc`'s `transformAssetUrlsBase` option\n  has been removed. It is merged into `trasnformAssetUrls` which now also\n  accepts the format of\n\n  ```ts\n  {\n    base?: string\n    includeAbsolute?: string\n    tags?: { [name: string]: string[] }\n  }\n  ```\n\n# [3.0.0-beta.8](https://github.com/vuejs/core/compare/v3.0.0-beta.7...v3.0.0-beta.8) (2020-05-04)\n\n### Bug Fixes\n\n- **hmr:** handle cases where instances with same id having different definitions ([01b7e90](https://github.com/vuejs/core/commit/01b7e90eac88c79ed38a396f824f71c6653736c8))\n- **reactivity:** avoid polluting Object prototype ([f40f3a0](https://github.com/vuejs/core/commit/f40f3a0e9589bfa096d365f735c9bb54b9853fd3))\n- **reactivity:** check own property for existing proxy of target ([6be2b73](https://github.com/vuejs/core/commit/6be2b73f8aeb26be72eab22259c8a513b59b910f)), closes [#1107](https://github.com/vuejs/core/issues/1107)\n- **transitionGroup:** inner children should skip comment node ([#1105](https://github.com/vuejs/core/issues/1105)) ([26a50ce](https://github.com/vuejs/core/commit/26a50ce67f64439cfc242fba59b1e7129e59ba40))\n- **types/reactivity:** fix ref type inference on nested reactive properties with .value ([bc1f097](https://github.com/vuejs/core/commit/bc1f097e29c5c823737503532baa23c11d4824f8)), closes [#1111](https://github.com/vuejs/core/issues/1111)\n\n### Features\n\n- **shared:** support Map and Set in toDisplayString ([3c60d40](https://github.com/vuejs/core/commit/3c60d40827f65cbff024cfda4bb981a742bb83a7)), closes [#1067](https://github.com/vuejs/core/issues/1067) [#1100](https://github.com/vuejs/core/issues/1100)\n- **types:** re-expose resolve asset utitlies and registerRuntimeCompiler in type definitions ([64ef7c7](https://github.com/vuejs/core/commit/64ef7c76bf0dfa4897d930e9d369a026d1ecbaf6)), closes [#1109](https://github.com/vuejs/core/issues/1109)\n- **watch:** support directly watching reactive object with deep default ([6b33cc4](https://github.com/vuejs/core/commit/6b33cc422933a004fb116fc5182b3fa3a32567ff)), closes [#1110](https://github.com/vuejs/core/issues/1110)\n\n# [3.0.0-beta.7](https://github.com/vuejs/core/compare/v3.0.0-beta.6...v3.0.0-beta.7) (2020-05-02)\n\n### Bug Fixes\n\n- **warn:** cast symbols to strings ([#1103](https://github.com/vuejs/core/issues/1103)) ([71a942b](https://github.com/vuejs/core/commit/71a942b25a2cad61c3d670075523c31d296c7089))\n\n### Features\n\n- **compiler-sfc:** add transformAssetUrlsBase option ([36972c2](https://github.com/vuejs/core/commit/36972c20b5c2451c8345361f9c015655afbfdd87))\n- **types:** re-expose `withDirectives` as public type ([583ba0c](https://github.com/vuejs/core/commit/583ba0c172de7a2fd0d2dc93ad7e4f40c53ba7ac))\n\n# [3.0.0-beta.6](https://github.com/vuejs/core/compare/v3.0.0-beta.5...v3.0.0-beta.6) (2020-05-01)\n\n### Bug Fixes\n\n- **compiler-core:** hoist pure annotations should apply to all nested calls ([c5e7d8b](https://github.com/vuejs/core/commit/c5e7d8b532685e1e33e1cfb316f75c1b61109ee7))\n- **compiler-core:** hoisted vnode calls and scoped id calls should be marked pure ([cad25d9](https://github.com/vuejs/core/commit/cad25d95a3171628b0c95e89fb8e52eb5f41bbc5))\n- **compiler-ssr:** handle comments codegen + refactor ssr codegen transform ([6c60ce1](https://github.com/vuejs/core/commit/6c60ce13e061b43d314dde022d3f43ece7f03c30))\n- **runtime-core:** avoid infinite warning loop for isRef check on component public proxy ([6233608](https://github.com/vuejs/core/commit/62336085f497d42f0007bf9ad33f078d273605a6)), closes [#1091](https://github.com/vuejs/core/issues/1091)\n- **runtime-core:** cloned vnodes with extra props should de-opt ([08bf7e3](https://github.com/vuejs/core/commit/08bf7e360783d520bae3fbe37143c52d360bd52d))\n- **runtime-core:** fix slot fragment bail check ([ac6a6f1](https://github.com/vuejs/core/commit/ac6a6f11ac3931c723c9aca8a351768ea2cacf38))\n- **runtime-core:** should call Suspense fallback unmount hook ([#1061](https://github.com/vuejs/core/issues/1061)) ([8b85aae](https://github.com/vuejs/core/commit/8b85aaeea9b2ed343e2ae19958abbd9e5d223a77)), closes [#1059](https://github.com/vuejs/core/issues/1059)\n- **runtime-core:** should catch dom prop set TypeErrors ([98bee59](https://github.com/vuejs/core/commit/98bee596bddc8131cccfde4a11fa2e5cd9bf39e4)), closes [#1051](https://github.com/vuejs/core/issues/1051)\n- **runtime-dom:** should not coerce nullish values to empty strings for non-string dom props ([20bc7ba](https://github.com/vuejs/core/commit/20bc7ba1c55b43143a4cef98cadaad8d693f9275)), closes [#1049](https://github.com/vuejs/core/issues/1049) [#1092](https://github.com/vuejs/core/issues/1092) [#1093](https://github.com/vuejs/core/issues/1093) [#1094](https://github.com/vuejs/core/issues/1094)\n- **ssr:** fix escape and handling for raw Text, Comment and Static vnodes ([5b09e74](https://github.com/vuejs/core/commit/5b09e743a01a4dbc73b98ecf130a3a5f95ce41fe))\n- **teleport:** teleport should always be tracked as dynamic child for unmount ([7f23555](https://github.com/vuejs/core/commit/7f2355535613f1f5f5902cc7ca235fca8ee5493c)), closes [#1088](https://github.com/vuejs/core/issues/1088)\n- **types:** augment ref unwrap bail types in appropriate packages ([b40fcbc](https://github.com/vuejs/core/commit/b40fcbc4c66125bf6b390e208b61635a9e2c003f))\n\n### Code Refactoring\n\n- **types:** mark internal API exports and exclude from d.ts ([c9bf7de](https://github.com/vuejs/core/commit/c9bf7ded2e74790c902384e13c1d444c7136c1f9))\n\n### Features\n\n- **runtime-core:** warn against user properties with reserved prefixes ([1bddeea](https://github.com/vuejs/core/commit/1bddeea24797fe5c66e469bb6bc526c17bfb7fde))\n\n### Performance Improvements\n\n- instance public proxy should never be observed ([11f38d8](https://github.com/vuejs/core/commit/11f38d8a853b2d8043212c17612b63df92322de4))\n\n### BREAKING CHANGES\n\n- **types:** Internal APIs are now excluded from type declarations.\n\n# [3.0.0-beta.5](https://github.com/vuejs/core/compare/v3.0.0-beta.4...v3.0.0-beta.5) (2020-04-30)\n\n### Bug Fixes\n\n- **compiler-ssr:** avoid unnecessary withCtx import ([08b4e88](https://github.com/vuejs/core/commit/08b4e8815da4e8911058ccbab986bea6365c3352))\n- **hmr:** support hmr for static nodes ([386b093](https://github.com/vuejs/core/commit/386b093554c8665fa6a9313b61c0a9359c4ec819))\n- **hydration:** fix text mismatch warning ([e087b4e](https://github.com/vuejs/core/commit/e087b4e02467db18766b7acc2218b3d38d60ce8b))\n- **keep-alive:** do not invoke onVnodeBeforeUnmount if is KeepAlive component ([#1079](https://github.com/vuejs/core/issues/1079)) ([239270c](https://github.com/vuejs/core/commit/239270c38a56782bd7f29802cb583b0a8a5a4df4))\n- **transition-group:** should collect raw children with Fragment ([#1046](https://github.com/vuejs/core/issues/1046)) ([8ed3455](https://github.com/vuejs/core/commit/8ed3455251d721e62fd7f6f75a7ef04bc411c152)), closes [#1045](https://github.com/vuejs/core/issues/1045)\n- **warning:** always check for component instance presence when formatting traces ([a0e2c12](https://github.com/vuejs/core/commit/a0e2c1287466567d945e87496ce2f922f3dc6d8c))\n\n### Features\n\n- **runtime-core:** export queuePostFlushCb ([#1078](https://github.com/vuejs/core/issues/1078)) ([ba240eb](https://github.com/vuejs/core/commit/ba240eb497de75acd5f31ff6b3803da0560027d8))\n\n### types\n\n- use more consistent naming for apiWatch type exports ([892fb6d](https://github.com/vuejs/core/commit/892fb6d2290516df44241992b62d65f1376f611a))\n\n### BREAKING CHANGES\n\n- Some watch API types are renamed.\n\n  - `BaseWatchOptions` -> `WatchOptionsBase`\n  - `StopHandle` -> `WatchStopHandle`\n\n# [3.0.0-beta.4](https://github.com/vuejs/core/compare/v3.0.0-beta.3...v3.0.0-beta.4) (2020-04-24)\n\n### Bug Fixes\n\n- **compiler-core:** dynamic component should always be made blocks ([7d0ab33](https://github.com/vuejs/core/commit/7d0ab3392af5285147db111759fe380688ca17ea)), closes [#1018](https://github.com/vuejs/core/issues/1018)\n- **runtime-core:** dynamic component should support falsy values without warning ([ded92f9](https://github.com/vuejs/core/commit/ded92f93b423cda28a40746c1f5fa9bcba56e80d))\n- **runtime-core:** fix dynamic node tracking in dynamic component that resolves to plain elements ([dcf2458](https://github.com/vuejs/core/commit/dcf2458fa84d7573273b0306aaabcf28ee859622)), closes [#1039](https://github.com/vuejs/core/issues/1039)\n- **runtime-core:** fix key/ref resolution for cloneVNode ([d7379c7](https://github.com/vuejs/core/commit/d7379c7647e3222eddd18d7dad8d2520f59deb8a)), closes [#1041](https://github.com/vuejs/core/issues/1041)\n- **runtime-core:** mixin options that rely on this context should be deferred ([ff4d1fc](https://github.com/vuejs/core/commit/ff4d1fcd81d96f3ddb0e34f04e70e3539dc7a96f)), closes [#1016](https://github.com/vuejs/core/issues/1016) [#1029](https://github.com/vuejs/core/issues/1029)\n- **runtime-core:** only infer component name for object components ([e422b8b](https://github.com/vuejs/core/commit/e422b8b082f1765f596c3ae0ff5b2e65d756405a)), closes [#1023](https://github.com/vuejs/core/issues/1023)\n- **slots:** compiled slot fallback should be functions ([#1030](https://github.com/vuejs/core/issues/1030)) ([2b19965](https://github.com/vuejs/core/commit/2b19965bcf75d981400ed58a0348bcfc13f17e33)), closes [#1021](https://github.com/vuejs/core/issues/1021)\n- **types:** fix ref(false) type to Ref<boolean> ([#1028](https://github.com/vuejs/core/issues/1028)) ([0bdd889](https://github.com/vuejs/core/commit/0bdd8891569eb15e492007b3eb0f45d598e85b3f))\n- **types:** make return type of `defineComponent` assignable to `Component` type ([#1032](https://github.com/vuejs/core/issues/1032)) ([f3a9b51](https://github.com/vuejs/core/commit/f3a9b516bd6feb42d1ea611faf6550f709fd3173)), closes [#993](https://github.com/vuejs/core/issues/993)\n\n### Features\n\n- **compiler-sfc:** add preprocessCustomRequire option ([20d425f](https://github.com/vuejs/core/commit/20d425fb19e04cd5b66f76b0f52ca221c92eb74c))\n- **compiler-sfc:** built-in support for css modules ([fa216a0](https://github.com/vuejs/core/commit/fa216a0c3adc70ff74deca872e295a154fa147c8))\n- **reactivity:** add triggerRef API ([2acf3e8](https://github.com/vuejs/core/commit/2acf3e84b95d7f18925b4d7ada92f1992f5b7ee3))\n- **types:** expose `ToRefs` type ([#1037](https://github.com/vuejs/core/issues/1037)) ([28b4c31](https://github.com/vuejs/core/commit/28b4c317b412e0c08bb791d647d4234078c41542))\n\n### Performance Improvements\n\n- **reactivity:** ref should not trigger if value did not change ([b0d4df9](https://github.com/vuejs/core/commit/b0d4df974339a570fd30263797cf948619e1f57b)), closes [#1012](https://github.com/vuejs/core/issues/1012)\n\n# [3.0.0-beta.3](https://github.com/vuejs/core/compare/v3.0.0-beta.2...v3.0.0-beta.3) (2020-04-20)\n\n### Bug Fixes\n\n- **runtime-core:** should not cast prop value if prop did not change ([171cfa4](https://github.com/vuejs/core/commit/171cfa404f33a451376dcb84d66ddae012c343ec)), closes [#999](https://github.com/vuejs/core/issues/999)\n- **warn:** fix component name inference in warning trace ([0278992](https://github.com/vuejs/core/commit/0278992f78834bc8df677c4e8ec891bb79510edb))\n\n### Features\n\n- **build:** provide more specific warnings for runtime compilation ([e954ba2](https://github.com/vuejs/core/commit/e954ba21f04f0ef848c687233fcb849d75e4153f)), closes [#1004](https://github.com/vuejs/core/issues/1004)\n- **runtime-core:** improve warning for extraneous event listeners ([#1005](https://github.com/vuejs/core/issues/1005)) ([cebad64](https://github.com/vuejs/core/commit/cebad64d224ff9a2b7976643c85d55d8ec53ee54)), closes [#1001](https://github.com/vuejs/core/issues/1001)\n- **runtime-core:** more specific warning for failed v-on fallthrough ([ab844fd](https://github.com/vuejs/core/commit/ab844fd1692007cf2be4d01a9062caa36fa1d280)), closes [#1001](https://github.com/vuejs/core/issues/1001)\n- **warn:** infer anonymous component named based on resolve name ([dece610](https://github.com/vuejs/core/commit/dece6102aa84c115a3d6481c6e0f27e5b4be3ef1))\n\n### Performance Improvements\n\n- **core:** use `startsWith` instead of `indexOf` ([#989](https://github.com/vuejs/core/issues/989)) ([054ccec](https://github.com/vuejs/core/commit/054ccecd58c36b909661598f43a4056ed07e59c2))\n\n# [3.0.0-beta.2](https://github.com/vuejs/core/compare/v3.0.0-beta.1...v3.0.0-beta.2) (2020-04-17)\n\n### Bug Fixes\n\n- **runtime-core:** fix user attached public instance properties that start with \"$\" ([d7ca1c5](https://github.com/vuejs/core/commit/d7ca1c5c6e75648793d670299c9059b6db9b1715))\n- **watch:** fix deep watchers on refs containing primitives ([#984](https://github.com/vuejs/core/issues/984)) ([99fd158](https://github.com/vuejs/core/commit/99fd158d090594a433b57d9ff9420f3aed48ad2d))\n\n### Features\n\n- **types:** expose `ComponentCustomOptions` for declaring custom options ([c0adb67](https://github.com/vuejs/core/commit/c0adb67c2e10d07af74304accbc1c79d19f6c196))\n- **types:** expose `ExtractPropTypes` ([#983](https://github.com/vuejs/core/issues/983)) ([4cf5e07](https://github.com/vuejs/core/commit/4cf5e07608a85f1526b89e90ee3710d40cb5a964))\n- **types** add `ComponentCustomProperties` interface ([#982](https://github.com/vuejs/core/issues/982)) ([be21cfb](https://github.com/vuejs/core/commit/be21cfb1db1a60fb0f2dda57d7f62d1c126a064b))\n\n# [3.0.0-beta.1](https://github.com/vuejs/core/compare/v3.0.0-alpha.13...v3.0.0-beta.1) (2020-04-16)\n\n### Bug Fixes\n\n- **reactivity:** remove Symbol.observable ([#968](https://github.com/vuejs/core/issues/968)) ([4d014dc](https://github.com/vuejs/core/commit/4d014dc3d361c52ac6192c063100ad8655a6e397))\n\n### Code Refactoring\n\n- **reactivity:** adjust APIs ([09b4202](https://github.com/vuejs/core/commit/09b4202a22ae03072a8a8405511e37f65b626568))\n\n### Features\n\n- **runtime-core:** skip emit warn if has equivalent onXXX prop ([0709380](https://github.com/vuejs/core/commit/0709380c5faf0a86c25a0564781fdb2650c9c353))\n\n### Performance Improvements\n\n- **runtime-core:** use raw context on component options init ([bfd6744](https://github.com/vuejs/core/commit/bfd6744fb1db36a02914ef48da7116636343f313))\n\n### BREAKING CHANGES\n\n- **reactivity:** Reactivity APIs adjustments:\n\n* `readonly` is now non-tracking if called on plain objects.\n  `lock` and `unlock` have been removed. A `readonly` proxy can no\n  longer be directly mutated. However, it can still wrap an already\n  reactive object and track changes to the source reactive object.\n\n* `isReactive` now only returns true for proxies created by `reactive`,\n  or a `readonly` proxy that wraps a `reactive` proxy.\n\n* A new utility `isProxy` is introduced, which returns true for both\n  reactive or readonly proxies.\n\n* `markNonReactive` has been renamed to `markRaw`.\n\n# [3.0.0-alpha.13](https://github.com/vuejs/core/compare/v3.0.0-alpha.12...v3.0.0-alpha.13) (2020-04-15)\n\n### Bug Fixes\n\n- **compiler-core:** should not generate CLASS/STYLE patch flags on components ([a6e2b10](https://github.com/vuejs/core/commit/a6e2b1052a4d461767147a6c13854fcb4f9509d2)), closes [#677](https://github.com/vuejs/core/issues/677)\n- **runtime-core:** fix kebab-case props update ([7cbf684](https://github.com/vuejs/core/commit/7cbf68461118ced0c7c6eb79a395ae2b148e3737)), closes [#955](https://github.com/vuejs/core/issues/955)\n- **runtime-core:** should resolve value instead of delete for dynamic props with options ([c80b857](https://github.com/vuejs/core/commit/c80b857eb5b19f48f498147479a779af9953be32))\n- **runtime-dom:** fix patching for attributes starting with `on` ([6eb3399](https://github.com/vuejs/core/commit/6eb339931185a57cc36ddb6e12314a5283948169)), closes [#949](https://github.com/vuejs/core/issues/949)\n- **runtime-dom:** should patch svg innerHtml ([#956](https://github.com/vuejs/core/issues/956)) ([27b5c71](https://github.com/vuejs/core/commit/27b5c71944637bc04d715382851cc63ca7efc47a))\n- **runtime-dom/v-on:** support event.stopImmediatePropagation on multiple listeners ([d45e475](https://github.com/vuejs/core/commit/d45e47569d366b932c0e3461afc6478b45a4602d)), closes [#916](https://github.com/vuejs/core/issues/916)\n- **scheduler:** sort jobs before flushing ([78977c3](https://github.com/vuejs/core/commit/78977c399734da7c4f8d58f2ccd650533e89249f)), closes [#910](https://github.com/vuejs/core/issues/910) [/github.com/vuejs/core/issues/910#issuecomment-613097539](https://github.com//github.com/vuejs/core/issues/910/issues/issuecomment-613097539)\n- **types:** UnwrapRef should bail on DOM element types ([#952](https://github.com/vuejs/core/issues/952)) ([33ccfc0](https://github.com/vuejs/core/commit/33ccfc0a8b69de13065c4b995f88722dd72a1ae9)), closes [#951](https://github.com/vuejs/core/issues/951)\n\n### Code Refactoring\n\n- **reactivity:** remove stale API `markReadonly` ([e8a866e](https://github.com/vuejs/core/commit/e8a866ec9945ec0464035be4c4c58d6212080a50))\n- **runtime-core:** remove emit return value ([55566e8](https://github.com/vuejs/core/commit/55566e8f520eee8a07b85221174989c47c443c35))\n\n### Features\n\n- **reactivity:** add support for `customRef` API ([b83c580](https://github.com/vuejs/core/commit/b83c5801315e5e28ac51ecff743206e665f4d868))\n- **reactivity:** add support for `toRef` API ([486dc18](https://github.com/vuejs/core/commit/486dc188fe1593448d2bfb0c3c4c3c02b2d78ea4))\n- **runtime-core:** detect and warn against components made reactive ([2e06f5b](https://github.com/vuejs/core/commit/2e06f5bbe84155588dea82d90822a41dc93d0688)), closes [#962](https://github.com/vuejs/core/issues/962)\n- **runtime-core:** warn async data() ([3e7bb7d](https://github.com/vuejs/core/commit/3e7bb7d110818d7b90ca4acc47afc30508f465b7))\n\n### Reverts\n\n- Revert \"feat(reactivity): add effect to public api (#909)\" (#961) ([9e9d264](https://github.com/vuejs/core/commit/9e9d2644127a17f770f325d1f1c88b12a34c8789)), closes [#909](https://github.com/vuejs/core/issues/909) [#961](https://github.com/vuejs/core/issues/961)\n\n### BREAKING CHANGES\n\n- **reactivity:** `markReadonly` has been removed.\n- **runtime-dom:** Only props starting with `on` followed by an uppercase\n  letter or a non-letter character are considered event listeners.\n- **runtime-core:** this.$emit() and setupContext.emit() no longer\n  return values. For logic that relies on return value of listeners,\n  the listener should be declared as an `onXXX` prop and be called\n  directly. This still allows the parent component to pass in\n  a handler using `v-on`, since `v-on:foo` internally compiles\n  to `onFoo`.\n\n      ref: https://github.com/vuejs/rfcs/pull/16\n\n# [3.0.0-alpha.12](https://github.com/vuejs/core/compare/v3.0.0-alpha.11...v3.0.0-alpha.12) (2020-04-08)\n\n### Bug Fixes\n\n- **compiler:** should not condense `&nbsp;` ([8c17535](https://github.com/vuejs/core/commit/8c17535a470501f7f4ec3747cd3de25d9169c505)), closes [#945](https://github.com/vuejs/core/issues/945)\n- **compiler:** should only strip leading newline directly in pre tag ([be666eb](https://github.com/vuejs/core/commit/be666ebd59027eb2fc96595c1a6054ecf62832e8))\n- **compiler:** support full range of entity decoding in browser builds ([1f6e72b](https://github.com/vuejs/core/commit/1f6e72b11051561abe270fa233cf52d5aba01d6b))\n- **compiler-core:** elements with dynamic keys should be forced into blocks ([d531686](https://github.com/vuejs/core/commit/d531686f9154c2ef7f1d877c275df62a8d8da2a5)), closes [#916](https://github.com/vuejs/core/issues/916)\n- **reactivity:** track reactive keys in raw collection types ([5dcc645](https://github.com/vuejs/core/commit/5dcc645fc068f9a467fa31ba2d3c2a59e68a9fd7)), closes [#919](https://github.com/vuejs/core/issues/919)\n- **runtime-core:** fix globalProperties in check on instance render proxy ([c28a919](https://github.com/vuejs/core/commit/c28a9196b2165e8ce274b2708d6d772024c2933a))\n- **runtime-core:** set fragment root children should also update dynamicChildren ([#944](https://github.com/vuejs/core/issues/944)) ([a27e9ee](https://github.com/vuejs/core/commit/a27e9ee9aea3487ef3ef0c8a5df53227fc172886)), closes [#943](https://github.com/vuejs/core/issues/943)\n- **runtime-dom:** fix getModelAssigner order in vModelCheckbox ([#926](https://github.com/vuejs/core/issues/926)) ([da1fb7a](https://github.com/vuejs/core/commit/da1fb7afef75470826501fe6e9d81e5af296fea7))\n- **runtime-dom:** support native onxxx handlers ([2302dea](https://github.com/vuejs/core/commit/2302dea1624d4b964fed71e30089426212091c11)), closes [#927](https://github.com/vuejs/core/issues/927)\n- **slots:** should update compiled dynamic slots ([8444078](https://github.com/vuejs/core/commit/84440780f9e45aa5b060180078b769f27757c7bd))\n- **transition:** fix dynamic transition update on nested HOCs ([b8da8b2](https://github.com/vuejs/core/commit/b8da8b2dfac96558df1d038aac3bbe63bd42a8ce))\n- **transition:** should ship props declarations in production ([4227831](https://github.com/vuejs/core/commit/42278317e15a202e4e1c8f7084eafa7bb13f1ade))\n- **types:** accept generic Component type in h() ([c1d5928](https://github.com/vuejs/core/commit/c1d5928f3b240a4a69bcd8d88494e4fe8d2e625b)), closes [#922](https://github.com/vuejs/core/issues/922)\n- **v-model:** handle dynamic assigners and array assigners ([f42d11e](https://github.com/vuejs/core/commit/f42d11e8e19f7356f4e1629cd07c774c9af39288)), closes [#923](https://github.com/vuejs/core/issues/923)\n\n### Features\n\n- **asyncComponent:** add `onError` option for defineAsyncComponent ([e804463](https://github.com/vuejs/core/commit/e80446349215159c002223a41baeb5a8bc0f444c))\n- **runtime-core:** improve component public instance proxy inspection ([899287a](https://github.com/vuejs/core/commit/899287ad35d8b74e76a71f39772a92f261dfa4f8))\n\n### BREAKING CHANGES\n\n- **compiler:** compiler options have been adjusted.\n  - new option `decodeEntities` is added.\n  - `namedCharacterReferences` option has been removed.\n  - `maxCRNameLength` option has been removed.\n- **asyncComponent:** `retryWhen` and `maxRetries` options for\n  `defineAsyncComponent` has been replaced by the more flexible `onError`\n  option, per https://github.com/vuejs/rfcs/pull/148\n\n# [3.0.0-alpha.11](https://github.com/vuejs/core/compare/v3.0.0-alpha.10...v3.0.0-alpha.11) (2020-04-04)\n\n### Bug Fixes\n\n- **compiler:** fix pre tag whitespace handling ([7f30cb5](https://github.com/vuejs/core/commit/7f30cb577257ad5765261bbffa3cae862259fcab)), closes [#908](https://github.com/vuejs/core/issues/908)\n- **compiler-core/slots:** should support on-component named slots ([a022b63](https://github.com/vuejs/core/commit/a022b63605820c97923413ee457ba1fb69a5221e))\n- **compiler-sfc:** always use offset for template block sourcemaps ([#911](https://github.com/vuejs/core/issues/911)) ([db50009](https://github.com/vuejs/core/commit/db5000935306214b31e33865cd57935e80e27d41))\n- **inject:** allow default value to be `undefined` ([#894](https://github.com/vuejs/core/issues/894)) ([94562da](https://github.com/vuejs/core/commit/94562daea70fde33a340bb7b57746523c3660a8e)), closes [#892](https://github.com/vuejs/core/issues/892)\n- **portal:** portal should always remove its children when unmounted ([16cd8ee](https://github.com/vuejs/core/commit/16cd8eee7839cc4613f17642bf37b39f7bdf1fce))\n- **reactivity:** scheduled effect should not execute if stopped ([0764c33](https://github.com/vuejs/core/commit/0764c33d3da8c06d472893a4e451e33394726a42)), closes [#910](https://github.com/vuejs/core/issues/910)\n- **runtime-core:** support attr merging on child with root level comments ([e42cb54](https://github.com/vuejs/core/commit/e42cb543947d4286115b6adae6e8a5741d909f14)), closes [#904](https://github.com/vuejs/core/issues/904)\n- **runtime-dom:** v-cloak should be removed after compile on the root element ([#893](https://github.com/vuejs/core/issues/893)) ([0ed147d](https://github.com/vuejs/core/commit/0ed147d33610b86af72cbadcc4b32e6069bcaf08)), closes [#890](https://github.com/vuejs/core/issues/890)\n- **runtime-dom:** properly support creating customized built-in element ([b1d0b04](https://github.com/vuejs/core/commit/b1d0b046afb1e8f4640d8d80b6eeaf9f89e892f7))\n- **transition:** warn only when there is more than one rendered child ([#903](https://github.com/vuejs/core/issues/903)) ([37b1dc8](https://github.com/vuejs/core/commit/37b1dc8242608b072d14fd2a5e52f5d40829ea52))\n- **types:** allow use PropType with Function ([#915](https://github.com/vuejs/core/issues/915)) ([026eb72](https://github.com/vuejs/core/commit/026eb729f3d1566e95f2f4253d76c20e86d1ec9b)), closes [#748](https://github.com/vuejs/core/issues/748)\n- **types:** export missing types from runtime-core ([#889](https://github.com/vuejs/core/issues/889)) ([412ec86](https://github.com/vuejs/core/commit/412ec86128fa33fa41ce435c493fd8275a785fea))\n- **types/reactivity:** add generics constraint for markNonReactive ([f3b6559](https://github.com/vuejs/core/commit/f3b6559408fb42ff6dc0c67001c9c67093f2b059)), closes [#917](https://github.com/vuejs/core/issues/917)\n\n### Code Refactoring\n\n- **runtime-core:** adjust attr fallthrough behavior ([21bcdec](https://github.com/vuejs/core/commit/21bcdec9435700cac98868a36716b49a7766c48d))\n- rename `<portal>` to `<teleport>` ([eee5095](https://github.com/vuejs/core/commit/eee50956924d7d2c916cdb8b99043da616e53af5))\n- **runtime-core:** rename `createAsyncComponent` to `defineAsyncComponent` ([#888](https://github.com/vuejs/core/issues/888)) ([ebc5873](https://github.com/vuejs/core/commit/ebc587376ca1fb4bb8a20d4137332740605753c8))\n\n### Features\n\n- **asyncComponent:** retry support ([c01930e](https://github.com/vuejs/core/commit/c01930e60b4abf481900cdfcc2ba422890c41656))\n- **compiler-core:** export `transformElement` from compiler-core ([#907](https://github.com/vuejs/core/issues/907)) ([20f4965](https://github.com/vuejs/core/commit/20f4965b45d410a2fe95310ecf7293b2b7f46f36))\n- **compiler-core:** support v-is ([b8ffbff](https://github.com/vuejs/core/commit/b8ffbffaf771c259848743cf4eb1a5ea31795aaa))\n- **portal:** hydration support for portal disabled mode ([b74bab2](https://github.com/vuejs/core/commit/b74bab216c3be68ab046451cf5e5b5bec5f19483))\n- **portal:** SSR support for multi portal shared target ([e866434](https://github.com/vuejs/core/commit/e866434f0c54498dd0fc47d48287a1d0ada36388))\n- **portal:** SSR support for portal disabled prop ([9ed9bf3](https://github.com/vuejs/core/commit/9ed9bf3687a770aebc265839065832761e6bafa1))\n- **portal:** support disabled prop ([8ce3da0](https://github.com/vuejs/core/commit/8ce3da0104db9bdd89929724c6d841ac3dfb7336))\n- **portal:** support multiple portal appending to same target ([aafb880](https://github.com/vuejs/core/commit/aafb880a0a9e023b62cf8fb3ae269b31f22ac84e))\n- **reactivity:** add effect to public api ([#909](https://github.com/vuejs/core/issues/909)) ([6fba241](https://github.com/vuejs/core/commit/6fba2418507d9c65891e8d14bd63736adb377556))\n- **runtime-core:** config.performance tracing support ([e93e426](https://github.com/vuejs/core/commit/e93e426bfad13f40c8f1d80b8f45ac5d0926c2fc))\n- **runtime-core:** emits validation and warnings ([c7c3a6a](https://github.com/vuejs/core/commit/c7c3a6a3bef6275be8f9f8873358421017bb5386))\n- **runtime-core:** failed component resolution should fallback to native element ([cb31eb4](https://github.com/vuejs/core/commit/cb31eb4d0a0afdd2abf9e3897d9aac447dd0264b))\n- **runtime-core:** support app.config.globalProperties ([27873db](https://github.com/vuejs/core/commit/27873dbe1c09ac6a058d815949a4e13831513fd0))\n- **runtime-core:** type and attr fallthrough support for emits option ([bf473a6](https://github.com/vuejs/core/commit/bf473a64eacab21d734d556c66cc190aa4ff902d))\n- **templateRef:** should work with direct reactive property ([449ab03](https://github.com/vuejs/core/commit/449ab039feb10df7179898b13ecc45028a043002)), closes [#901](https://github.com/vuejs/core/issues/901)\n- **templateRef:** support template ref for all vnode types ([55b364d](https://github.com/vuejs/core/commit/55b364decc903a6c7fccd1cdcdcfc79948c848a2))\n\n### BREAKING CHANGES\n\n- **runtime-core:** attribute fallthrough behavior has been adjusted\n  according to https://github.com/vuejs/rfcs/pull/154\n- `<portal>` has been renamed to `<teleport>`.\n\n  `target` prop is also renamed to `to`, so the new usage will be:\n\n  ```html\n  <Teleport to=\"#modal-layer\" :disabled=\"isMobile\">\n    <div class=\"modal\">hello</div>\n  </Teleport>\n  ```\n\n  The primary reason for the renaming is to avoid potential naming\n  conflict with [native portals](https://wicg.github.io/portals/).\n\n- **asyncComponent:** async component `error` and `loading` options have been\n  renamed to `errorComponent` and `loadingComponent` respectively.\n- **runtime-core:** `createAsyncComponent` has been renamed to `defineAsyncComponent` for consistency with `defineComponent`.\n\n# [3.0.0-alpha.10](https://github.com/vuejs/core/compare/v3.0.0-alpha.9...v3.0.0-alpha.10) (2020-03-24)\n\n### Bug Fixes\n\n- fix option merge global mixins presence check ([10ad965](https://github.com/vuejs/core/commit/10ad965100a88e28cb528690f2e09070fefc8872))\n- **compiler-core:** assign patchFlag for template v-if fragment ([a1da9c2](https://github.com/vuejs/core/commit/a1da9c28a0a7030124b1deb9369685760c67be47)), closes [#850](https://github.com/vuejs/core/issues/850)\n- **compiler-core:** support interpolation in RCDATA mode (e.g. textarea) ([0831b98](https://github.com/vuejs/core/commit/0831b98eac344d9bdfd6f6e922902adb91ea180a))\n- **keep-alive:** should update re-activated component with latest props ([1237387](https://github.com/vuejs/core/commit/123738727a0af54fd632bf838dc3aa024722ee41))\n- **reactivity:** should not observe frozen objects ([1b2149d](https://github.com/vuejs/core/commit/1b2149dbb2dd224d01e90c1a9332bfe67aa465ce)), closes [#867](https://github.com/vuejs/core/issues/867)\n- **reactivity:** should not trigger map keys iteration when keys did not change ([45ba06a](https://github.com/vuejs/core/commit/45ba06ac5f49876b4f05e5996f595b2c4a761f47)), closes [#877](https://github.com/vuejs/core/issues/877)\n- **runtime-core:** fix boolean props validation ([3b282e7](https://github.com/vuejs/core/commit/3b282e7e3c96786af0a5ff61822882d1ed3f4db3))\n- **runtime-dom:** invalid lineGradient svg tag ([#863](https://github.com/vuejs/core/issues/863)) ([d425818](https://github.com/vuejs/core/commit/d425818901428ff919a0179fc910410cbcfa119b)), closes [#862](https://github.com/vuejs/core/issues/862)\n- **TransitionGroup:** ignore comment node when warn (fix[#869](https://github.com/vuejs/core/issues/869)) ([#875](https://github.com/vuejs/core/issues/875)) ([0dba5d4](https://github.com/vuejs/core/commit/0dba5d44e60d33b909f4e4d05663c7ddf746a1f2))\n- do not drop SFC runtime behavior code in global builds ([4c1a193](https://github.com/vuejs/core/commit/4c1a193617bee8ace6fad289b78e9d2557cb081e)), closes [#873](https://github.com/vuejs/core/issues/873)\n- dynamic component fallback to native element ([f529dbd](https://github.com/vuejs/core/commit/f529dbde236e9eaedbded78e926951a189234f9c)), closes [#870](https://github.com/vuejs/core/issues/870)\n- **runtime-core:** fix component proxy props presence check ([b3890a9](https://github.com/vuejs/core/commit/b3890a93e39342fd16e5fd72c59f361fc211309c)), closes [#864](https://github.com/vuejs/core/issues/864)\n- **suspense:** clear effects on suspense resolve ([ebc1ca8](https://github.com/vuejs/core/commit/ebc1ca8eff82789987c09a9f6a934898b00153ff))\n- **transition:** fix duration prop validation ([0dc2478](https://github.com/vuejs/core/commit/0dc24785699101fa24d2a68786feaaac8a887520)), closes [#868](https://github.com/vuejs/core/issues/868)\n\n### Features\n\n- **asyncComponent:** SSR/hydration support for async component ([cba2f1a](https://github.com/vuejs/core/commit/cba2f1aadbd0d4ae246040ecd5a91d8dd4e8fd1a))\n- **runtime-core:** async component support ([c3bb316](https://github.com/vuejs/core/commit/c3bb3169f497fc834654d8ae700f18b1a6613127))\n- **runtime-core:** support `config.optionMergeStrategies` ([528621b](https://github.com/vuejs/core/commit/528621ba41b1d7113940077574217d01d182b35f))\n- add hook for transforming h's arguments ([#851](https://github.com/vuejs/core/issues/851)) ([b7d1e0f](https://github.com/vuejs/core/commit/b7d1e0fa2ffe4561a589580eca6e92171c311347))\n\n### Performance Improvements\n\n- **transform-vif:** don't need to createBlock for a component ([#853](https://github.com/vuejs/core/issues/853)) ([a3601e9](https://github.com/vuejs/core/commit/a3601e9fa73d10f524ed3bdf3ae44df8847c1230))\n\n# [3.0.0-alpha.9](https://github.com/vuejs/core/compare/v3.0.0-alpha.8...v3.0.0-alpha.9) (2020-03-16)\n\n### Bug Fixes\n\n- **build:** remove **RUNTIME_COMPILE** flag ([206640a](https://github.com/vuejs/core/commit/206640a2d859a9ce9c19f22e201692f15a8d1da3)), closes [#817](https://github.com/vuejs/core/issues/817)\n- **compiler-core:** fix property shorthand detection ([586e5bb](https://github.com/vuejs/core/commit/586e5bb8003916ba6be9b3394087df80328657f4)), closes [#845](https://github.com/vuejs/core/issues/845)\n- **compiler-ssr:** fix input w/ v-bind=\"obj\" codegen ([3b40fc5](https://github.com/vuejs/core/commit/3b40fc56dba56a5c1085582d11f3287e9317a151))\n- **compiler-ssr:** should pass necessary tag names for dynamic v-bind ([a46f3b3](https://github.com/vuejs/core/commit/a46f3b354d451a857df750a318bd0536338008cd))\n- **runtime-core:** always set invalid vnode type ([#820](https://github.com/vuejs/core/issues/820)) ([28a9bee](https://github.com/vuejs/core/commit/28a9beed1624de9812e0f4ce9b63f7f3ed2c6db8))\n- **runtime-core:** empty boolean props ([#844](https://github.com/vuejs/core/issues/844)) ([c7ae269](https://github.com/vuejs/core/commit/c7ae2699724bd5206ce7d2db73b86c1ef5947641)), closes [#843](https://github.com/vuejs/core/issues/843)\n- **runtime-core:** pass instance proxy as data() argument ([#828](https://github.com/vuejs/core/issues/828)) ([d9dd1d8](https://github.com/vuejs/core/commit/d9dd1d8a0ac81d7d463e0788bb2e75b2d4866db6))\n- **runtime-dom:** patch xlink attribute ([#842](https://github.com/vuejs/core/issues/842)) ([d318576](https://github.com/vuejs/core/commit/d318576d74f8756e471942ff44d2af2a4661d775))\n- simplify and use correct ctx in withCtx ([4dc8ffc](https://github.com/vuejs/core/commit/4dc8ffc3788c38aff3e4c0f271d0ca111f723140))\n- **runtime-core:** pass prev value to hostPatchProp ([#809](https://github.com/vuejs/core/issues/809)) ([cd34603](https://github.com/vuejs/core/commit/cd34603864142d5468486ec3f379679b22014a1b)), closes [#808](https://github.com/vuejs/core/issues/808)\n- **runtime-core:** should allow empty string and 0 as valid vnode key ([#807](https://github.com/vuejs/core/issues/807)) ([54a0e93](https://github.com/vuejs/core/commit/54a0e93c276f95a35b3bd6510a7f52d967fd3b7f))\n- **types:** app.component should accept defineComponent return type ([#822](https://github.com/vuejs/core/issues/822)) ([1e9d131](https://github.com/vuejs/core/commit/1e9d1319c3f66a0a7430a4f6ac7b508486894b6b)), closes [#730](https://github.com/vuejs/core/issues/730)\n\n### Code Refactoring\n\n- **runtime-core:** adjust patchProp value arguments order ([ca5f39e](https://github.com/vuejs/core/commit/ca5f39ee3501a1d9cacdb74108318c15ee7c0abb))\n\n### Features\n\n- **compiler-core:** wrap slot functions with render context ([ecd7ce6](https://github.com/vuejs/core/commit/ecd7ce60d5234a7a0dbc11add6a690c3f9ff0617))\n- **compiler-sfc:** add ssr option ([3b2d236](https://github.com/vuejs/core/commit/3b2d23671409f8ac358252311bf5212882fa985a))\n- **runtime-core:** add special property to get class component options ([#821](https://github.com/vuejs/core/issues/821)) ([dd17fa1](https://github.com/vuejs/core/commit/dd17fa1c9071b9685c379e1b12102214b757cf35))\n- **runtime-core:** implement RFC-0020 ([bb7fa3d](https://github.com/vuejs/core/commit/bb7fa3dabce73de63d016c75f1477e7d8bed8858))\n- **runtime-core:** set context for manual slot functions as well ([8a58dce](https://github.com/vuejs/core/commit/8a58dce6034944b18c2e507b5d9ab8177f60e269))\n- **server-renderer:** render suspense in vnode mode ([#727](https://github.com/vuejs/core/issues/727)) ([589aeb4](https://github.com/vuejs/core/commit/589aeb402c58f463cc32d5e7728b56614bc9bf33))\n- **ssr:** compiler-ssr support for Suspense ([80c625d](https://github.com/vuejs/core/commit/80c625dce33610e53c953e9fb8fde26e3e10e358))\n- **ssr:** hide comment anchors during hydration in dev mode ([cad5bcc](https://github.com/vuejs/core/commit/cad5bcce40b9f2aaa520ccbd377cd5419650e55f))\n- **ssr:** improve fragment mismatch handling ([60ed4e7](https://github.com/vuejs/core/commit/60ed4e7e0821a2932660b87fbf8d5ca953e0e073))\n- **ssr:** support getSSRProps for vnode directives ([c450ede](https://github.com/vuejs/core/commit/c450ede12d1a93a70271a2fe7fcb6f8efcf1cd4c))\n- **ssr/suspense:** suspense hydration ([a3cc970](https://github.com/vuejs/core/commit/a3cc970030579f2c55d893d6e83bbc05324adad4))\n- **types:** export `ErrorTypes` ([#840](https://github.com/vuejs/core/issues/840)) ([760c3e0](https://github.com/vuejs/core/commit/760c3e0fd67f6360995cdbb125f9eae4e024f3af))\n\n### Reverts\n\n- Revert \"refactor(directives): remove binding.instance\" ([2370166](https://github.com/vuejs/core/commit/23701666cb487e55d05b74d66990361051715ba4))\n\n### BREAKING CHANGES\n\n- **runtime-core:** data no longer supports object format (per RFC-0020)\n- **runtime-core:** `RendererOptions.patchProp` arguments order has changed\n\n  The `prevValue` and `nextValue` position has been swapped to keep it\n  consistent with other functions in the renderer implementation. This\n  only affects custom renderers using the `createRenderer` API.\n\n# [3.0.0-alpha.8](https://github.com/vuejs/core/compare/v3.0.0-alpha.7...v3.0.0-alpha.8) (2020-03-06)\n\n### Bug Fixes\n\n- **directives:** ignore invalid directive hooks ([7971b04](https://github.com/vuejs/core/commit/7971b0468c81483dd7026204518f7c03187d13c4)), closes [#795](https://github.com/vuejs/core/issues/795)\n- **portal:** fix portal placeholder text ([4397528](https://github.com/vuejs/core/commit/439752822c175c737e58896e0f365f2b02bab577))\n- **reactivity:** allow effect trigger inside no-track execution contexts ([274f81c](https://github.com/vuejs/core/commit/274f81c5db83f0f77e1aba3240b2134a2474a72f)), closes [#804](https://github.com/vuejs/core/issues/804)\n- **reactivity:** Map/Set identity methods should work even if raw value contains reactive entries ([cc69fd7](https://github.com/vuejs/core/commit/cc69fd72e3f9ef3572d2be40af71d22232e1b9af)), closes [#799](https://github.com/vuejs/core/issues/799)\n- **reactivity:** should not trigger length dependency on Array delete ([a306658](https://github.com/vuejs/core/commit/a3066581f3014aae31f2d96b96428100f1674166)), closes [#774](https://github.com/vuejs/core/issues/774)\n- **runtime-core:** ensure inherited attrs update on optimized child root ([6810d14](https://github.com/vuejs/core/commit/6810d1402e214a12fa274ff5fb7475bad002d1b1)), closes [#677](https://github.com/vuejs/core/issues/677) [#784](https://github.com/vuejs/core/issues/784)\n- **slots:** fix conditional slot ([3357ff4](https://github.com/vuejs/core/commit/3357ff438c6ff0d4fea67923724dd3cb99ff2756)), closes [#787](https://github.com/vuejs/core/issues/787)\n- **ssr:** fix ssr on-the-fly compilation + slot fallback branch helper injection ([3be3785](https://github.com/vuejs/core/commit/3be3785f945253918469da456a14a2d9381bcbd0))\n\n### Code Refactoring\n\n- **runtime-core:** adjust attr fallthrough behavior ([e1660f4](https://github.com/vuejs/core/commit/e1660f4338fbf4d2a434e13193a58e00f844379b)), closes [#749](https://github.com/vuejs/core/issues/749)\n- **runtime-core:** revert setup() result reactive conversion ([e67f655](https://github.com/vuejs/core/commit/e67f655b2687042fcc74dc0993581405abed56de))\n\n### Features\n\n- **compiler-core:** switch to @babel/parser for expression parsing ([8449a97](https://github.com/vuejs/core/commit/8449a9727c942b6049c9e577c7c15b43fdca2867))\n- **compiler-ssr:** compile portal ([#775](https://github.com/vuejs/core/issues/775)) ([d8ed0e7](https://github.com/vuejs/core/commit/d8ed0e7fbf9bbe734667eb94e809235e79e431eb))\n- **ssr:** hydration mismatch handling ([91269da](https://github.com/vuejs/core/commit/91269da52c30abf6c50312555b715f5360224bb0))\n\n### BREAKING CHANGES\n\n- **runtime-core:** adjust attr fallthrough behavior\n\n  Updated per pending RFC https://github.com/vuejs/rfcs/pull/137\n\n  - Implicit fallthrough now by default only applies for a whitelist\n    of attributes (class, style, event listeners, a11y attributes, and\n    data attributes).\n\n  - Fallthrough is now applied regardless of whether the component has\n\n- **runtime-core:** revert setup() result reactive conversion\n\n  Revert 6b10f0c & a840e7d. The motivation of the original change was\n  avoiding unnecessary deep conversions, but that can be achieved by\n  explicitly marking values non-reactive via `markNonReactive`.\n\n  Removing the reactive conversion behavior leads to an usability\n  issue in that plain objects containing refs (which is what most\n  composition functions will return), when exposed as a nested\n  property from `setup()`, will not unwrap the refs in templates. This\n  goes against the \"no .value in template\" intuition and the only\n  workaround requires users to manually wrap it again with `reactive()`.\n\n  So in this commit we are reverting to the previous behavior where\n  objects returned from `setup()` are implicitly wrapped with\n  `reactive()` for deep ref unwrapping.\n\n# [3.0.0-alpha.7](https://github.com/vuejs/core/compare/v3.0.0-alpha.6...v3.0.0-alpha.7) (2020-02-26)\n\n### Bug Fixes\n\n- **renderSlot:** set slot render as a STABLE_FRAGMENT ([#776](https://github.com/vuejs/core/issues/776)) ([8cb0b83](https://github.com/vuejs/core/commit/8cb0b8308801159177ec16ab5a3e23672c4c1d00)), closes [#766](https://github.com/vuejs/core/issues/766)\n- **runtime-core:** fix slot fallback + slots typing ([4a5b91b](https://github.com/vuejs/core/commit/4a5b91bd1faec76bbaa0522b095f4a07ca88a9e5)), closes [#773](https://github.com/vuejs/core/issues/773)\n- **runtime-core:** make watchEffect ignore deep option ([#765](https://github.com/vuejs/core/issues/765)) ([19a799c](https://github.com/vuejs/core/commit/19a799c28b149b14e85d9e2081fa65ed58d108ba))\n- **runtime-core:** set appContext.provides to Object.create(null) ([#781](https://github.com/vuejs/core/issues/781)) ([04f83fa](https://github.com/vuejs/core/commit/04f83fa6810e07915e98b94c954ff0c1859aaa49))\n- **template-explorer:** rename watch -> watchEffect ([#780](https://github.com/vuejs/core/issues/780)) ([59393dd](https://github.com/vuejs/core/commit/59393dd75766720330cb69e22086c97a392dbbe4))\n- **template-ref:** fix string template refs inside slots ([3eab143](https://github.com/vuejs/core/commit/3eab1438432a3bab15ccf2f6092fc3e4355f3cdd))\n- **types:** ref value type unwrapping should happen at creation time ([d4c6957](https://github.com/vuejs/core/commit/d4c6957e2d8ac7920a649f3a3576689cd5e1099f))\n- **types:** shallowRef should not unwrap value type ([3206e5d](https://github.com/vuejs/core/commit/3206e5dfe58fd0e93644d13929558d71c5171888))\n\n### Code Refactoring\n\n- **directives:** remove binding.instance ([52cc7e8](https://github.com/vuejs/core/commit/52cc7e823148289b3dcdcb6b521984ab815fce79))\n\n### BREAKING CHANGES\n\n- **directives:** custom directive bindings no longer expose instance\n\n  This is a rarely used property that creates extra complexity in\n  ensuring it points to the correct instance. From a design\n  perspective, a custom directive should be scoped to the element and\n  data it is bound to and should not have access to the entire\n  instance in the first place.\n\n# [3.0.0-alpha.6](https://github.com/vuejs/core/compare/v3.0.0-alpha.5...v3.0.0-alpha.6) (2020-02-22)\n\n### Bug Fixes\n\n- **compiler-core:** should alias name in helperString ([#743](https://github.com/vuejs/core/issues/743)) ([7b987d9](https://github.com/vuejs/core/commit/7b987d9450fc7befcd0946a0d53991d27ed299ec)), closes [#740](https://github.com/vuejs/core/issues/740)\n- **compiler-dom:** properly stringify class/style bindings when hoisting static strings ([1b9b235](https://github.com/vuejs/core/commit/1b9b235663b75db040172d2ffbee1dd40b4db032))\n- **reactivity:** should trigger all effects when array length is mutated ([#754](https://github.com/vuejs/core/issues/754)) ([5fac655](https://github.com/vuejs/core/commit/5fac65589b4455b98fd4e2f9eb3754f0acde97bb))\n- **sfc:** inherit parent scopeId on child root ([#756](https://github.com/vuejs/core/issues/756)) ([9547c2b](https://github.com/vuejs/core/commit/9547c2b93d6d8f469314cfe055960746a3e3acbe))\n- **types:** improve ref typing, close [#759](https://github.com/vuejs/core/issues/759) ([627b9df](https://github.com/vuejs/core/commit/627b9df4a293ae18071009d9cac7a5e995d40716))\n- **types:** update setup binding unwrap types for 6b10f0c ([a840e7d](https://github.com/vuejs/core/commit/a840e7ddf0b470b5da27b7b2b8b5fcf39a7197a2)), closes [#738](https://github.com/vuejs/core/issues/738)\n\n### Code Refactoring\n\n- preserve refs in reactive arrays ([775a7c2](https://github.com/vuejs/core/commit/775a7c2b414ca44d4684badb29e8e80ff6b5d3dd)), closes [#737](https://github.com/vuejs/core/issues/737)\n\n### Features\n\n- **reactivity:** expose unref and shallowRef ([e9024bf](https://github.com/vuejs/core/commit/e9024bf1b7456b9cf9b913c239502593364bc773))\n- **runtime-core:** add watchEffect API ([99a2e18](https://github.com/vuejs/core/commit/99a2e18c9711d3d1f79f8c9c59212880efd058b9))\n\n### Performance Improvements\n\n- **effect:** optimize effect trigger for array length mutation ([#761](https://github.com/vuejs/core/issues/761)) ([76c7f54](https://github.com/vuejs/core/commit/76c7f5426919f9d29a303263bc54a1e42a66e94b))\n- **reactivity:** only trigger all effects on Array length mutation if new length is shorter than old length ([33622d6](https://github.com/vuejs/core/commit/33622d63600ba0f18ba4dae97bda882c918b5f7d))\n\n### BREAKING CHANGES\n\n- **runtime-core:** replace `watch(fn, options?)` with `watchEffect`\n\n  The `watch(fn, options?)` signature has been replaced by the new\n  `watchEffect` API, which has the same usage and behavior. `watch`\n  now only supports the `watch(source, cb, options?)` signature.\n\n- **reactivity:** reactive arrays no longer unwraps contained refs\n\n  When reactive arrays contain refs, especially a mix of refs and\n  plain values, Array prototype methods will fail to function\n  properly - e.g. sort() or reverse() will overwrite the ref's value\n  instead of moving it (see #737).\n\n  Ensuring correct behavior for all possible Array methods while\n  retaining the ref unwrapping behavior is exceedingly complicated; In\n  addition, even if Vue handles the built-in methods internally, it\n  would still break when the user attempts to use a 3rd party utility\n  function (e.g. lodash) on a reactive array containing refs.\n\n  After this commit, similar to other collection types like Map and\n  Set, Arrays will no longer automatically unwrap contained refs.\n\n  The usage of mixed refs and plain values in Arrays should be rare in\n  practice. In cases where this is necessary, the user can create a\n  computed property that performs the unwrapping.\n\n# [3.0.0-alpha.5](https://github.com/vuejs/core/compare/v3.0.0-alpha.4...v3.0.0-alpha.5) (2020-02-18)\n\n### Bug Fixes\n\n- **compiler:** fix v-for fragment openBlock argument ([12fcf9a](https://github.com/vuejs/core/commit/12fcf9ab953acdbb8706b549c7e63f69482a495a))\n- **compiler-core:** fix keep-alive when used in templates ([ade07c6](https://github.com/vuejs/core/commit/ade07c64a1f98c0958e80db0458c699c21998f64)), closes [#715](https://github.com/vuejs/core/issues/715)\n- **compiler-core:** only check is prop on `<component>` ([78c4f32](https://github.com/vuejs/core/commit/78c4f321cd0902a117c599ac705dda294fa198ed))\n- **compiler-core:** relax error on unknown entities ([730d329](https://github.com/vuejs/core/commit/730d329f794caf1ea2cc47628f8d74ef2d07f96e)), closes [#663](https://github.com/vuejs/core/issues/663)\n- **compiler-core:** should apply text transform to if branches ([e0f3c6b](https://github.com/vuejs/core/commit/e0f3c6b352ab35adcad779ef0ac9670acf3d7b37)), closes [#725](https://github.com/vuejs/core/issues/725)\n- **compiler-core:** should not hoist element with cached + merged event handlers ([5455e8e](https://github.com/vuejs/core/commit/5455e8e69a59cd1ff72330b1aed9c8e6aedc4b36))\n- **compiler-dom:** fix duplicated transforms ([9e51297](https://github.com/vuejs/core/commit/9e51297702f975ced1cfebad9a46afc46f0593bb))\n- **compiler-sfc:** handle empty nodes with src attribute ([#695](https://github.com/vuejs/core/issues/695)) ([2d56dfd](https://github.com/vuejs/core/commit/2d56dfdc4fcf824bba4c0166ca5471258c4f883b))\n- **compiler-ssr:** import helpers from correct packages ([8f6b669](https://github.com/vuejs/core/commit/8f6b6690a2011846446804267ec49073996c3800))\n- **computed:** support arrow function usage for computed option ([2fb7a63](https://github.com/vuejs/core/commit/2fb7a63943d9d995248cb6d2d4fb5f22ff2ac000)), closes [#733](https://github.com/vuejs/core/issues/733)\n- **reactivity:** avoid cross-component dependency leaks in setup() ([d9d63f2](https://github.com/vuejs/core/commit/d9d63f21b1e6f99f2fb63d736501095b131e5ad9))\n- **reactivity:** effect should handle self dependency mutations ([e8e6772](https://github.com/vuejs/core/commit/e8e67729cb7649d736be233b2a5e00768dd6f4ba))\n- **reactivity:** trigger iteration effect on Map.set ([e1c9153](https://github.com/vuejs/core/commit/e1c9153b9ed71f9b2e1ad4f9018c51d239e7dcd0)), closes [#709](https://github.com/vuejs/core/issues/709)\n- **runtime-core:** ensure renderCache always exists ([8383e54](https://github.com/vuejs/core/commit/8383e5450e4f9679ac8a284f1c3960e3ee5b5211))\n- **runtime-core:** fix keep-alive tree-shaking ([5b43764](https://github.com/vuejs/core/commit/5b43764eacb59ff6ebba3195a55af4ac0cf253bb))\n- **runtime-core:** fix ShapeFlags tree shaking ([0f67aa7](https://github.com/vuejs/core/commit/0f67aa7da50d6ffc543754a42f1e677af11f9173))\n- **runtime-core:** handle component updates with only class/style bindings ([35d91f4](https://github.com/vuejs/core/commit/35d91f4e18ccb72cbf39a86fe8f39060f0bf075e))\n- **runtime-core:** render context set should not unwrap reactive values ([27fbfbd](https://github.com/vuejs/core/commit/27fbfbdb8beffc96134c931425f33178c23a72db))\n- **runtime-core:** rework vnode hooks handling ([cfadb98](https://github.com/vuejs/core/commit/cfadb98011e188114bb822ee6f678cd09ddac7e3)), closes [#684](https://github.com/vuejs/core/issues/684)\n- **runtime-core:** should not return early on text patchFlag ([778f3a5](https://github.com/vuejs/core/commit/778f3a5e886a1a1136bc8b00b849370d7c4041be))\n- **runtime-core/scheduler:** avoid duplicate updates of child component ([8a87074](https://github.com/vuejs/core/commit/8a87074df013fdbb0e88f34074c2605e4af2937c))\n- **runtime-core/scheduler:** invalidate job ([#717](https://github.com/vuejs/core/issues/717)) ([fe9da2d](https://github.com/vuejs/core/commit/fe9da2d0e4f9b338252b1b62941ee9ead71f0346))\n- **runtime-core/watch:** trigger watcher with undefined as initial value ([#687](https://github.com/vuejs/core/issues/687)) ([5742a0b](https://github.com/vuejs/core/commit/5742a0b826fe77d2310acb530667adb758822f66)), closes [#683](https://github.com/vuejs/core/issues/683)\n- **runtime-dom/ssr:** properly handle xlink and boolean attributes ([e6e2c58](https://github.com/vuejs/core/commit/e6e2c58234cab46fa530c383c0f7ae1cb3494da3))\n- **ssr:** avoid hard-coded ssr checks in cjs builds ([bc07e95](https://github.com/vuejs/core/commit/bc07e95ca84686bfa43798a444a3220581b183d8))\n- **ssr:** fix class/style rendering + ssrRenderComponent export name ([688ad92](https://github.com/vuejs/core/commit/688ad9239105625f7b63ac43181dfb2e9d1d4720))\n- **ssr:** render components returning render function from setup ([#720](https://github.com/vuejs/core/issues/720)) ([4669215](https://github.com/vuejs/core/commit/4669215ca2f82d90a1bd730613259f3167e199cd))\n- **transition-group:** handle multiple move-classes ([#679](https://github.com/vuejs/core/issues/679)) ([5495c70](https://github.com/vuejs/core/commit/5495c70c4a3f740ef4ac575ffee5466ca747cca1)), closes [#678](https://github.com/vuejs/core/issues/678)\n- **types:** app.component should accept defineComponent return type ([57ee5df](https://github.com/vuejs/core/commit/57ee5df364f03816e548f4f3bf05edc7a089c362)), closes [#730](https://github.com/vuejs/core/issues/730)\n- **types:** ensure correct oldValue typing based on lazy option ([c6a9787](https://github.com/vuejs/core/commit/c6a9787941ca99877d268182a5bb57fcf8b80b75)), closes [#719](https://github.com/vuejs/core/issues/719)\n- **v-on:** transform click.right and click.middle modifiers ([028f748](https://github.com/vuejs/core/commit/028f748c32f80842be39897fdacc37f6700f00a7)), closes [#735](https://github.com/vuejs/core/issues/735)\n- remove effect from public API ([4bc4cb9](https://github.com/vuejs/core/commit/4bc4cb970f7a65177948c5d817bb43ecb0324636)), closes [#712](https://github.com/vuejs/core/issues/712)\n- **v-model:** should use dynamic directive on input with dynamic v-bind ([1f2de9e](https://github.com/vuejs/core/commit/1f2de9e232409b09c97b67d0824d1450beed6eb1))\n\n### Code Refactoring\n\n- **watch:** adjust watch API behavior ([9571ede](https://github.com/vuejs/core/commit/9571ede84bb6949e13c25807cc8f016ace29dc8a))\n\n### Features\n\n- **compiler:** mark hoisted trees with patchFlag ([175f8aa](https://github.com/vuejs/core/commit/175f8aae8d009e044e3674f7647bf1397f3a794a))\n- **compiler:** warn invalid children for transition and keep-alive ([4cc39e1](https://github.com/vuejs/core/commit/4cc39e14a297f42230f5aac5ec08e3c98902b98d))\n- **compiler-core:** support mode: cjs in codegen ([04da2a8](https://github.com/vuejs/core/commit/04da2a82e8fbde2b60b2392bc4bdcc5e61113202))\n- **compiler-core/v-on:** support [@vnode-xxx](https://github.com/vnode-xxx) usage for vnode hooks ([571ed42](https://github.com/vuejs/core/commit/571ed4226be618dcc9f95e4c2da8d82d7d2f7750))\n- **compiler-dom:** handle constant expressions when stringifying static content ([8b7c162](https://github.com/vuejs/core/commit/8b7c162125cb72068727a76ede8afa2896251db0))\n- **compiler-dom/runtime-dom:** stringify eligible static trees ([27913e6](https://github.com/vuejs/core/commit/27913e661ac551f580bd5fd42b49fe55cbe8dbb8))\n- **reactivity:** add shallowReactive function ([#689](https://github.com/vuejs/core/issues/689)) ([7f38c1e](https://github.com/vuejs/core/commit/7f38c1e0ff5a7591f67ed21aa3a2944db2e72a27))\n- **runtime-core/reactivity:** expose shallowReactive ([#711](https://github.com/vuejs/core/issues/711)) ([21944c4](https://github.com/vuejs/core/commit/21944c4a42a65f20245794fa5f07add579b7121f))\n- **server-renderer:** support on-the-fly template compilation ([#707](https://github.com/vuejs/core/issues/707)) ([6d10a6c](https://github.com/vuejs/core/commit/6d10a6c77242aec98103f15d6cb672ba63c18abf))\n- **ssr:** render portals ([#714](https://github.com/vuejs/core/issues/714)) ([e495fa4](https://github.com/vuejs/core/commit/e495fa4a1872d03ed59252e7ed5dd2b708adb7ae))\n- **ssr:** support portal hydration ([70dc3e3](https://github.com/vuejs/core/commit/70dc3e3ae74f08d53243e6f078794c16f359e272))\n- **ssr:** useSSRContext ([fd03149](https://github.com/vuejs/core/commit/fd031490fb89b7c0d1d478b586151a24324101a3))\n\n### Performance Improvements\n\n- prevent renderer hot functions being inlined by minifiers ([629ee75](https://github.com/vuejs/core/commit/629ee75588fc2ca4ab2b3786046f788d3547b6bc))\n- **reactivity:** better computed tracking ([#710](https://github.com/vuejs/core/issues/710)) ([8874b21](https://github.com/vuejs/core/commit/8874b21a7e2383a8bb6c15a7095c1853aa5ae705))\n\n### BREAKING CHANGES\n\n- **watch:** `watch` behavior has been adjusted.\n\n  - When using the `watch(source, callback, options?)` signature, the\n    callback now fires lazily by default (consistent with 2.x\n    behavior).\n\n    Note that the `watch(effect, options?)` signature is still eager,\n    since it must invoke the `effect` immediately to collect\n    dependencies.\n\n  - The `lazy` option has been replaced by the opposite `immediate`\n    option, which defaults to `false`. (It's ignored when using the\n    effect signature)\n\n  - Due to the above changes, the `watch` option in Options API now\n    behaves exactly the same as 2.x.\n\n  - When using the effect signature or `{ immediate: true }`, the\n    initial execution is now performed synchronously instead of\n    deferred until the component is mounted. This is necessary for\n    certain use cases to work properly with `async setup()` and\n    Suspense.\n\n    The side effect of this is the immediate watcher invocation will\n    no longer have access to the mounted DOM. However, the watcher can\n    be initiated inside `onMounted` to retain previous behavior.\n\n# [3.0.0-alpha.4](https://github.com/vuejs/core/compare/v3.0.0-alpha.3...v3.0.0-alpha.4) (2020-01-27)\n\n### Bug Fixes\n\n- **reactivity:** Array methods relying on identity should work with raw values ([aefb7d2](https://github.com/vuejs/core/commit/aefb7d282ed716923ca1a288a63a83a94af87ebc))\n- **runtime-core:** instance should not expose non-declared props ([2884831](https://github.com/vuejs/core/commit/2884831065e16ccf5bd3ae1ee95116803ee3b18c))\n- **runtime-dom:** should not access document in non-browser env ([48152bc](https://github.com/vuejs/core/commit/48152bc88ea817ae23e2987dce99d64b426366c1)), closes [#657](https://github.com/vuejs/core/issues/657)\n- **v-model/emit:** update:camelCase events should trigger kebab case equivalent ([2837ce8](https://github.com/vuejs/core/commit/2837ce842856d51dfbb55e3fa4a36a352446fb54)), closes [#656](https://github.com/vuejs/core/issues/656)\n\n### Code Refactoring\n\n- adjust `createApp` related API signatures ([c07751f](https://github.com/vuejs/core/commit/c07751fd3605f301dc0f02fd2a48acc7ba7a0397))\n- remove implicit reactive() call on renderContext ([6b10f0c](https://github.com/vuejs/core/commit/6b10f0cd1da942c1d96746672b5f595df7d125b5))\n\n### Performance Improvements\n\n- **ssr:** avoid unnecessary async overhead ([297282a](https://github.com/vuejs/core/commit/297282a81259289bfed207d0c9393337aea70117))\n\n### BREAKING CHANGES\n\n- object returned from `setup()` are no longer implicitly\n  passed to `reactive()`.\n\n  The renderContext is the object returned by `setup()` (or a new object\n  if no setup() is present). Before this change, it was implicitly passed\n  to `reactive()` for ref unwrapping. But this has the side effect of\n  unnecessary deep reactive conversion on properties that should not be\n  made reactive (e.g. computed return values and injected non-reactive\n  objects), and can lead to performance issues.\n\n  This change removes the `reactive()` call and instead performs a\n  shallow ref unwrapping at the render proxy level. The breaking part is\n  when the user returns an object with a plain property from `setup()`,\n  e.g. `return { count: 0 }`, this property will no longer trigger\n  updates when mutated by a in-template event handler. Instead, explicit\n  refs are required.\n\n  This also means that any objects not explicitly made reactive in\n  `setup()` will remain non-reactive. This can be desirable when\n  exposing heavy external stateful objects on `this`.\n\n- `createApp` API has been adjusted.\n\n  - `createApp()` now accepts the root component, and optionally a props\n    object to pass to the root component.\n  - `app.mount()` now accepts a single argument (the root container)\n  - `app.unmount()` no longer requires arguments.\n\n  New behavior looks like the following:\n\n  ```js\n  const app = createApp(RootComponent)\n  app.mount('#app')\n  app.unmount()\n  ```\n\n# [3.0.0-alpha.3](https://github.com/vuejs/core/compare/v3.0.0-alpha.2...v3.0.0-alpha.3) (2020-01-22)\n\n### Bug Fixes\n\n- Suspense should include into dynamic children ([#653](https://github.com/vuejs/core/issues/653)) ([ec63623](https://github.com/vuejs/core/commit/ec63623fe8d395e1cd759f27b90b1ccc1b616931)), closes [#649](https://github.com/vuejs/core/issues/649)\n- **compiler-core:** avoid override user keys when injecting branch key ([#630](https://github.com/vuejs/core/issues/630)) ([aca2c2a](https://github.com/vuejs/core/commit/aca2c2a81e2793befce516378a02afd1e4da3d3d))\n- **compiler-core:** force `<svg>` into blocks for correct runtime isSVG ([f2ac28b](https://github.com/vuejs/core/commit/f2ac28b31e9f1e8ebcd68ca9a1e8ea29653b0916))\n- **compiler-sfc:** only transform relative asset URLs ([#628](https://github.com/vuejs/core/issues/628)) ([c71ca35](https://github.com/vuejs/core/commit/c71ca354b9368135b55676c5817cebffaf3fd9c5))\n- **dom:** fix `<svg>` and `<foreignObject>` mount and updates ([4f06eeb](https://github.com/vuejs/core/commit/4f06eebc1c2a29d0e4165c6e87f849732ec2cd0f))\n- **runtime-core:** condition for parent node check should be any different nodes ([c35fea3](https://github.com/vuejs/core/commit/c35fea3d608acbb571ace6693284061e1cadf7ba)), closes [#622](https://github.com/vuejs/core/issues/622)\n- **runtime-core:** isSVG check should also apply for patch branch ([035b656](https://github.com/vuejs/core/commit/035b6560f7eb64ce940ed0d06e19086ad9a3890f)), closes [#639](https://github.com/vuejs/core/issues/639)\n- **runtime-core:** should not warn unused attrs when accessed via setup context ([751d838](https://github.com/vuejs/core/commit/751d838fb963e580a40df2d84840ba2198480185)), closes [#625](https://github.com/vuejs/core/issues/625)\n- **transition:** handle multiple transition classes ([#638](https://github.com/vuejs/core/issues/638)) ([#645](https://github.com/vuejs/core/issues/645)) ([98d50d8](https://github.com/vuejs/core/commit/98d50d874dcb32a246216b936e442e5b95ab4825))\n\n### Features\n\n- **runtime-core:** emit now returns array of return values from all triggered handlers ([e81c8a3](https://github.com/vuejs/core/commit/e81c8a32c7b66211cbaecffa93efd4629ec45ad9)), closes [#635](https://github.com/vuejs/core/issues/635)\n- **runtime-core:** support app.unmount(container) ([#601](https://github.com/vuejs/core/issues/601)) ([04ac6c4](https://github.com/vuejs/core/commit/04ac6c467a4122877c204d7494c86f89498d2dc6)), closes [#593](https://github.com/vuejs/core/issues/593)\n\n# [3.0.0-alpha.2](https://github.com/vuejs/core/compare/v3.0.0-alpha.1...v3.0.0-alpha.2) (2020-01-13)\n\n### Bug Fixes\n\n- **compiler/v-on:** handle multiple statements in v-on handler (close [#572](https://github.com/vuejs/core/issues/572)) ([137893a](https://github.com/vuejs/core/commit/137893a4fdd3d2b901adca31e30d916df925b108))\n- **compiler/v-slot:** handle implicit default slot mixed with named slots ([2ac4b72](https://github.com/vuejs/core/commit/2ac4b723e010082488b5be64af73e41c9677a28d))\n- **reactivity:** should delete observe value ([#598](https://github.com/vuejs/core/issues/598)) ([63a6563](https://github.com/vuejs/core/commit/63a656310676e3927b2e57d813fd6300c0a42590)), closes [#597](https://github.com/vuejs/core/issues/597)\n- **runtime-core:** allow classes to be passed as plugins ([#588](https://github.com/vuejs/core/issues/588)) ([8f616a8](https://github.com/vuejs/core/commit/8f616a89c580bc211540d5e4d60488ff24d024cc))\n- **runtime-core:** should preserve props casing when component has no declared props ([bb6a346](https://github.com/vuejs/core/commit/bb6a346996ce0bf05596c605ba5ddbe0743ef84b)), closes [#583](https://github.com/vuejs/core/issues/583)\n- **runtime-core/renderer:** fix v-if toggle inside blocks ([2e9726e](https://github.com/vuejs/core/commit/2e9726e6a219d546cd28e4ed42be64719708f047)), closes [#604](https://github.com/vuejs/core/issues/604) [#607](https://github.com/vuejs/core/issues/607)\n- **runtime-core/vnode:** should not render boolean values in vnode children (close [#574](https://github.com/vuejs/core/issues/574)) ([84dc5a6](https://github.com/vuejs/core/commit/84dc5a686275528733977ea1570e0a892ba3e177))\n- **types:** components options should accept components defined with defineComponent ([#602](https://github.com/vuejs/core/issues/602)) ([74baea1](https://github.com/vuejs/core/commit/74baea108aa93377c4959f9a6b8bc8f9548700ba))\n- **watch:** remove recorded effect on manual stop ([#590](https://github.com/vuejs/core/issues/590)) ([453e688](https://github.com/vuejs/core/commit/453e6889da22e7224b638261a32438bdf5c62e41))\n\n# [3.0.0-alpha.1](https://github.com/vuejs/core/compare/v3.0.0-alpha.0...v3.0.0-alpha.1) (2020-01-02)\n\n### Bug Fixes\n\n- **runtime-core:** pass options to plugins ([#561](https://github.com/vuejs/core/issues/561)) ([4d20981](https://github.com/vuejs/core/commit/4d20981eb069b20e1627916b977aedb2d68eca86))\n- **sfc:** treat custom block content as raw text ([d6275a3](https://github.com/vuejs/core/commit/d6275a3c310e6e9426f897afe35ff6cdb125c023))\n- mounting new children ([7d436ab](https://github.com/vuejs/core/commit/7d436ab59a30562a049e199ae579df7ac8066829))\n- **core:** clone mounted hoisted vnodes on patch ([47a6a84](https://github.com/vuejs/core/commit/47a6a846311203fa59584486265f5da387afa51d))\n- **fragment:** perform direct remove when removing fragments ([2fdb499](https://github.com/vuejs/core/commit/2fdb499bd96b4d1a8a7a1964d59e8dc5dacd9d22))\n\n### Features\n\n- **hmr:** root instance reload ([eda495e](https://github.com/vuejs/core/commit/eda495efd824f17095728a4d2a6db85ca874e5ca))\n\n### Performance Improvements\n\n- **compiler-core:** simplify `advancePositionWithMutation` ([#564](https://github.com/vuejs/core/issues/564)) ([ad2a0bd](https://github.com/vuejs/core/commit/ad2a0bde988de743d4abc62b681b6a4888545a51))\n\n# [3.0.0-alpha.0](https://github.com/vuejs/core/compare/a8522cf48c09efbb2063f129cf1bea0dae09f10a...v3.0.0-alpha.0) (2019-12-20)\n\nFor changes between 2.x and 3.0 up to this release, please refer to merged RFCs [here](https://github.com/vuejs/rfcs/pulls?q=is%3Apr+is%3Amerged+label%3A3.x).\n"
  },
  {
    "path": "changelogs/CHANGELOG-3.1.md",
    "content": "## [3.1.5](https://github.com/vuejs/core/compare/v3.1.4...v3.1.5) (2021-07-16)\n\n### Bug Fixes\n\n- **compat:** fix props check for v-model compat warning ([#4056](https://github.com/vuejs/core/issues/4056)) ([f3e15f6](https://github.com/vuejs/core/commit/f3e15f633edfa2d4f116bf52fd5dee02655567e3))\n- **compat:** fix v3 compiled fn detection in production ([8dbad83](https://github.com/vuejs/core/commit/8dbad83e7fa39be3e61ca694a6090c1646117953))\n- **compiler:** Addressed infinite loop in compiler ([#3992](https://github.com/vuejs/core/issues/3992)) ([e00aa56](https://github.com/vuejs/core/commit/e00aa56658ec207d45aae6eb23f0267b9e1c55e2)), closes [#3987](https://github.com/vuejs/core/issues/3987)\n- **compiler-core:** fix forwarded slots detection on template slots ([#4124](https://github.com/vuejs/core/issues/4124)) ([c23153d](https://github.com/vuejs/core/commit/c23153d82eb2aa57d254dd362a78383defec3968)), closes [#4123](https://github.com/vuejs/core/issues/4123)\n- **compiler-sfc:** duplicated injected css var with repeated vars in style ([#2802](https://github.com/vuejs/core/issues/2802)) ([2901050](https://github.com/vuejs/core/commit/29010501cc9611eb9cacb99a24827053ced3e018))\n- **compiler-sfc:** should not rewrite ref sugar identifiers in types ([6fad209](https://github.com/vuejs/core/commit/6fad2093a46898636af34ddc148616473a234617)), closes [#4062](https://github.com/vuejs/core/issues/4062)\n- **reactivity:** call array subclass methods ([#3624](https://github.com/vuejs/core/issues/3624)) ([1cfe290](https://github.com/vuejs/core/commit/1cfe290352456f0faf8319d7e193a4b3a31ef352)), closes [#2314](https://github.com/vuejs/core/issues/2314) [#2315](https://github.com/vuejs/core/issues/2315)\n- **ref:** should not trigger when setting value to same proxy ([#3658](https://github.com/vuejs/core/issues/3658)) ([08f504c](https://github.com/vuejs/core/commit/08f504c1b7798d95c1c0a9d0894b846ff955ce3c))\n- **runtime-core:** enter optimized mode for component as root ([68365b9](https://github.com/vuejs/core/commit/68365b9b2bc2ccef93e88475c4f15e7cfb4f2497)), closes [#3943](https://github.com/vuejs/core/issues/3943)\n- **runtime-dom:** capture errors when setting value for IDL ([#3578](https://github.com/vuejs/core/issues/3578)) ([3756270](https://github.com/vuejs/core/commit/37562702725fc328286b63499422856ac47890d7)), closes [#3576](https://github.com/vuejs/core/issues/3576)\n- **runtime-dom:** remove class attribute on nullish values ([7013e8f](https://github.com/vuejs/core/commit/7013e8f5781e838256bf07e7d5de58a974e761a8)), closes [#3173](https://github.com/vuejs/core/issues/3173)\n- **sfc:** fix `<script setup>` async context preservation logic ([03e2684](https://github.com/vuejs/core/commit/03e26845e2c220b1350a35179acf3435e2711282)), closes [#4050](https://github.com/vuejs/core/issues/4050)\n- **sfc:** fix style variables injection on static vnode ([#3847](https://github.com/vuejs/core/issues/3847)) ([6a0c7cd](https://github.com/vuejs/core/commit/6a0c7cd9051e1b3eb1a3ce1eaadfd9c828b53daa)), closes [#3841](https://github.com/vuejs/core/issues/3841)\n- **sfc:** only enable jsx parser plugin when explicitly using tsx ([5df7dfc](https://github.com/vuejs/core/commit/5df7dfcd71172f97a045297cdeea226e0b354a93)), closes [#4106](https://github.com/vuejs/core/issues/4106)\n- **type:** infer parent as `this` on `nextTick` function ([#3608](https://github.com/vuejs/core/issues/3608)) ([18911ab](https://github.com/vuejs/core/commit/18911abb917788106221027032bc771f0e37886d)), closes [#3599](https://github.com/vuejs/core/issues/3599)\n- **v-model:** handle mutations of v-model bound array/sets ([2937530](https://github.com/vuejs/core/commit/2937530beff5c6bb57286c2556307859e37aa809)), closes [#4096](https://github.com/vuejs/core/issues/4096)\n- **v-model:** support calling methods in v-model expression ([5af718b](https://github.com/vuejs/core/commit/5af718ba41f53d032fd33861494f96b70c107acd)), closes [#3993](https://github.com/vuejs/core/issues/3993)\n- **v-on:** proper member exp detection for bracket assignment ([395572b](https://github.com/vuejs/core/commit/395572b593c300be4db698777503bebe2bba2950)), closes [#4097](https://github.com/vuejs/core/issues/4097)\n- **v-on:** properly detect member expressions with optional chaining ([963085d](https://github.com/vuejs/core/commit/963085d18c472b13c2d3894d5bd4aac1420767f8)), closes [#4107](https://github.com/vuejs/core/issues/4107)\n\n## [3.1.4](https://github.com/vuejs/core/compare/v3.1.3...v3.1.4) (2021-07-02)\n\n### Bug Fixes\n\n- **build:** avoid using async/await syntax ([438754a](https://github.com/vuejs/core/commit/438754a0d1428d10e27d1a290beb4b81da5fdaeb))\n- **build:** fix generated code containing unprocessed class field syntax ([2788154](https://github.com/vuejs/core/commit/2788154f7707928f1dd3e4d9bd144f758a8c0478)), closes [#4052](https://github.com/vuejs/core/issues/4052) [vuejs/vue-cli#6562](https://github.com/vuejs/vue-cli/issues/6562)\n- **codegen:** ensure valid types in generated code when using global directives ([a44d528](https://github.com/vuejs/core/commit/a44d528af1227c05dedf610b6ec45504d8e58276)), closes [#4054](https://github.com/vuejs/core/issues/4054)\n- **compiler-sfc:** fix parse-only mode when there is no script setup block ([253ca27](https://github.com/vuejs/core/commit/253ca2729d808fc051215876aa4af986e4caa43c))\n- **runtime-core:** add useAttrs and useSlots export ([#4053](https://github.com/vuejs/core/issues/4053)) ([735ada1](https://github.com/vuejs/core/commit/735ada1507623b8d36e80b30a4f67a8af4a45c99))\n- **runtime-core:** fix instance accessed via $parent chain when using expose() ([#4048](https://github.com/vuejs/core/issues/4048)) ([12cf9f4](https://github.com/vuejs/core/commit/12cf9f4ea148a59fd9002ecf9ea9d365829ce37c))\n\n## [3.1.3](https://github.com/vuejs/core/compare/v3.1.2...v3.1.3) (2021-07-01)\n\n### Bug Fixes\n\n- **compiler-core:** properly exit self-closing pre tag ([d2df28d](https://github.com/vuejs/core/commit/d2df28dca42f6679766033f8986b5637dfe64e1e)), closes [#4030](https://github.com/vuejs/core/issues/4030)\n- **compiler-sfc:** avoid script setup marker showing up in devtools ([211793d](https://github.com/vuejs/core/commit/211793d3767b12dd457de62160b672af24b921e7))\n- **compiler-sfc:** fix defineProps() call on imported identifier ([691d354](https://github.com/vuejs/core/commit/691d354af9e3a66c781494656b367950fcd8faec))\n- **compiler-sfc:** fix defineProps/defineEmits usage in multi-variable declarations ([62c1b2f](https://github.com/vuejs/core/commit/62c1b2f7dc4d2dd22a1b1ab1897f0ce765008d59)), closes [#3739](https://github.com/vuejs/core/issues/3739)\n- **compiler-sfc:** fix script setup hidden flag codegen ([a5a66c5](https://github.com/vuejs/core/commit/a5a66c5196f5e00e8cbf7f6008d350d6eabcee71))\n- **compiler-sfc:** support method signature in defineProps ([afdd2f2](https://github.com/vuejs/core/commit/afdd2f28354ce8cea647279ed25d61e7b9946cf5)), closes [#2983](https://github.com/vuejs/core/issues/2983)\n- **compiler-sfc:** support TS runtime enum in `<script setup>` ([1ffd48a](https://github.com/vuejs/core/commit/1ffd48a2f5fd3eead3ea29dae668b7ed1c6f6130))\n- **runtime-core:** add missing serverPrefetch hook error string ([#4014](https://github.com/vuejs/core/issues/4014)) ([d069796](https://github.com/vuejs/core/commit/d069796b8f0cf8df9aa77d781c4b5429b9411204))\n- **runtime-core:** fix mouting of detached static vnode ([fded1e8](https://github.com/vuejs/core/commit/fded1e8dfa22ca7fecd300c4cbffd6a37b887be8)), closes [#4023](https://github.com/vuejs/core/issues/4023)\n- **runtime-dom:** fix static node content caching edge cases ([ba89ca9](https://github.com/vuejs/core/commit/ba89ca9ecafe86292e3adf751671ed5e9ca6e928)), closes [#4023](https://github.com/vuejs/core/issues/4023) [#4031](https://github.com/vuejs/core/issues/4031) [#4037](https://github.com/vuejs/core/issues/4037)\n- **sfc:** allow variables that start with \\_ or $ in `<script setup>` ([0b8b576](https://github.com/vuejs/core/commit/0b8b5764287b4814a37034ad4bc6f2b8ac8f8700))\n- **ssr:** ensure behavior consistency between prod/dev when mounting SSR app to empty containers ([33708e8](https://github.com/vuejs/core/commit/33708e8bf44a037070af5c8eabdfe1ccad22bbc2)), closes [#4034](https://github.com/vuejs/core/issues/4034)\n- **ssr:** properly hydrate non-string value bindings ([34d4991](https://github.com/vuejs/core/commit/34d4991dd5876325eb8747afa9a835929bde3974)), closes [#4006](https://github.com/vuejs/core/issues/4006)\n- **types:** improve type of unref() ([127ed1b](https://github.com/vuejs/core/commit/127ed1b969cb2d237d0f588aab726e04f4732641)), closes [#3954](https://github.com/vuejs/core/issues/3954)\n- defineExpose type definition and runtime warning ([1675b6d](https://github.com/vuejs/core/commit/1675b6d723829d1f61e697735e3da7b16aa1362d))\n- prevent withAsyncContext currentInstance leak in edge cases ([9ee41e1](https://github.com/vuejs/core/commit/9ee41e14d2d173866300e75758468c6788180277))\n\n### Features\n\n- **compiler-sfc:** compileScript parseOnly mode ([601a290](https://github.com/vuejs/core/commit/601a290caaf7fa29c58c88ac79fc2f1d2c57e337))\n- **expose:** always expose $ instance properties on child refs ([b0203a3](https://github.com/vuejs/core/commit/b0203a30929e4e7f59e035574e43d72ed3b9d7fd))\n- **sfc:** add `defineEmits` and deprecate `defineEmit` ([#3725](https://github.com/vuejs/core/issues/3725)) ([a137da8](https://github.com/vuejs/core/commit/a137da8a9f728edacd50d288bce281e32597197b))\n- **sfc:** auto restore current instance after await statements in async setup() ([0240e82](https://github.com/vuejs/core/commit/0240e82a38e2e0c5f0b63c228fd02b059a19073d))\n- **sfc:** change `<script setup>` directive resolution to require v prefix ([d35e0b1](https://github.com/vuejs/core/commit/d35e0b1468ce3c22b713020ed29f81aba40dd039)), closes [#3543](https://github.com/vuejs/core/issues/3543)\n- **sfc:** defineExpose ([be2b1d3](https://github.com/vuejs/core/commit/be2b1d3c2f16de8dc6e2a22f65fefaa2d25ec3ee))\n- **sfc:** make ref sugar disabled by default ([96cc335](https://github.com/vuejs/core/commit/96cc335aa7050b6bf2ae53cc209d0032a8d59d0e))\n- **sfc:** remove `<template inherit-attrs>` support ([6f6f0cf](https://github.com/vuejs/core/commit/6f6f0cf5dcc02f4a648fab86439eb29a4b5596d2))\n- **sfc:** support referenced types for defineEmits ([2973b6c](https://github.com/vuejs/core/commit/2973b6c30ae5b3ff65aeb71a26a6de1c7789537d))\n- **sfc:** support using declared interface or type alias with defineProps() ([2f91db3](https://github.com/vuejs/core/commit/2f91db30cda5c315ed3e4d20800b55721b0cb17c))\n- **sfc:** useAttrs + useSlots ([63e9e2e](https://github.com/vuejs/core/commit/63e9e2e9aae07c701548f3350ea83535bea22066))\n- **sfc:** withDefaults helper ([4c5844a](https://github.com/vuejs/core/commit/4c5844a9ca0acc4ea45565a0dc9a21c2502d64a4))\n- **sfc-playground:** support lang=ts ([be0f614](https://github.com/vuejs/core/commit/be0f614ac096bdfe44cfddb04c859c9747dcd6dd))\n- **sfc/types:** make `<script setup>` helper types available globally ([004bd18](https://github.com/vuejs/core/commit/004bd18cf75526bd79f68ccea8102aa94a8a28e2))\n- **types:** support IDE renaming for props ([#3656](https://github.com/vuejs/core/issues/3656)) ([81e69b2](https://github.com/vuejs/core/commit/81e69b29ecf992d215d8ddc56bf7e40661144595))\n- **types/ide:** support find definition for jsx tags, events ([#3570](https://github.com/vuejs/core/issues/3570)) ([8ed3ed6](https://github.com/vuejs/core/commit/8ed3ed6c27b0fb9a1b6994eddc967e42d4b3d4e1))\n\n## [3.1.2](https://github.com/vuejs/core/compare/v3.1.1...v3.1.2) (2021-06-22)\n\n### Bug Fixes\n\n- **compiler-core:** improve member expression check ([bc100c5](https://github.com/vuejs/core/commit/bc100c5c48b98b6e2eabfa1d50e0d3099ea2a90d)), closes [#3910](https://github.com/vuejs/core/issues/3910)\n- **compiler-core/compat:** fix is prop usage on components ([08e9322](https://github.com/vuejs/core/commit/08e93220f146118aad8ab07e18066bbb2d4b0040)), closes [#3934](https://github.com/vuejs/core/issues/3934)\n- **compiler-sfc:** rewriteDefault support multiline ([#3917](https://github.com/vuejs/core/issues/3917)) ([b228abb](https://github.com/vuejs/core/commit/b228abb72fcdb4fc9dced907f3614abcaaacdce5))\n- **compiler-ssr:** fix attr fallthrough for transition/keep-alive as template root ([9f6f8b3](https://github.com/vuejs/core/commit/9f6f8b35c1fdfa5b76b834673e2f991c5fa7c9c5)), closes [#3981](https://github.com/vuejs/core/issues/3981)\n- **devtools:** expose root instance ([2b52d5d](https://github.com/vuejs/core/commit/2b52d5d7c53f7843f4a1e85fd7f1720dc2847ebc))\n- **runtime-core:** bind default function of inject to instance ([#3925](https://github.com/vuejs/core/issues/3925)) ([db1dc1c](https://github.com/vuejs/core/commit/db1dc1c63097ed62a3f683a7a11c7e819d90bb73)), closes [#3923](https://github.com/vuejs/core/issues/3923)\n- **runtime-core:** fix multiple .once event handlers on same component ([#3904](https://github.com/vuejs/core/issues/3904)) ([011dee8](https://github.com/vuejs/core/commit/011dee8644bb52f5bdc6365c6e8404936d57e2cd)), closes [#3902](https://github.com/vuejs/core/issues/3902)\n- **Suspense:** emit initial fallback and pending events ([#3965](https://github.com/vuejs/core/issues/3965)) ([ab6e927](https://github.com/vuejs/core/commit/ab6e927041e4082acac9a5effe332557e70e4f2a)), closes [#3964](https://github.com/vuejs/core/issues/3964)\n- **Suspense:** fallback should work with transition ([#3968](https://github.com/vuejs/core/issues/3968)) ([43e2a72](https://github.com/vuejs/core/commit/43e2a72900b96870fe6f16248ecec50ff58278df)), closes [#3963](https://github.com/vuejs/core/issues/3963)\n- **watch:** fix watch option merging from mixins ([9b607fe](https://github.com/vuejs/core/commit/9b607fe409d70e991ba458e7c994e008a4b621e8)), closes [#3966](https://github.com/vuejs/core/issues/3966)\n\n### Performance Improvements\n\n- improve static content insertion perf ([4de5d24](https://github.com/vuejs/core/commit/4de5d24aa72f6bc68da967ead330147032983e30)), closes [#3090](https://github.com/vuejs/core/issues/3090)\n\n## [3.1.1](https://github.com/vuejs/core/compare/v3.1.0...v3.1.1) (2021-06-07)\n\n### Bug Fixes\n\n- **compat:** update cjs dist file names ([#3893](https://github.com/vuejs/core/issues/3893)) ([434ea30](https://github.com/vuejs/core/commit/434ea30505466bceb433f113d84f4b4ef8866047))\n\n# [3.1.0](https://github.com/vuejs/core/compare/v3.1.0-beta.7...v3.1.0) (2021-06-07)\n\n### Features\n\n- [Migration Build](https://v3-migration.vuejs.org/migration-build.html)\n- **compiler-core:** whitespace handling strategy ([dee3d6a](https://github.com/vuejs/core/commit/dee3d6ab8b4da6653d15eb148c51d9878007f6b6))\n- support component-level `compilerOptions` when using runtime compiler ([ce0bbe0](https://github.com/vuejs/core/commit/ce0bbe053abaf8ba18de8baf535e175048596ee5))\n- **config:** support configuring runtime compiler via `app.config.compilerOptions` ([091e6d6](https://github.com/vuejs/core/commit/091e6d67bfcc215227d78be578c68ead542481ad))\n- support casting plain element to component via is=\"vue:xxx\" ([af9e699](https://github.com/vuejs/core/commit/af9e6999e1779f56b5cf827b97310d8e4e1fe5ec))\n- **devtools:** improved KeepAlive support ([03ae300](https://github.com/vuejs/core/commit/03ae3006e1e678ade4377cd10d206e8f7b4ad0cb))\n- **devtools:** performance events ([f7c54ca](https://github.com/vuejs/core/commit/f7c54caeb1dac69a26b79c98409e9633a7fe4bd3))\n- onServerPrefetch ([#3070](https://github.com/vuejs/core/issues/3070)) ([349eb0f](https://github.com/vuejs/core/commit/349eb0f0ad78f9cb491278eb4c7f9fe0c2e78b79))\n\n### Performance Improvements\n\n- only trigger `$attrs` update when it has actually changed ([5566d39](https://github.com/vuejs/core/commit/5566d39d467ebdd4e4234bc97d62600ff01ea28e))\n- **compiler:** skip unnecessary checks when parsing end tag ([048ac29](https://github.com/vuejs/core/commit/048ac299f35709b25ae1bc1efa67d2abc53dbc3b))\n- avoid deopt for props/emits normalization when global mixins are used ([51d2be2](https://github.com/vuejs/core/commit/51d2be20386d4dc59006d31a1cc96676871027ce))\n\n### Deprecations\n\n- `app.config.isCustomElement` has been deprecated and should be now nested under `app.config.compilerOptions`. [[Docs](https://v3.vuejs.org/api/application-config.html#compileroptions)]\n- `delimiters` component option has been deprecated and should now be nested under the `compilerOptions` component option. [[Docs](https://v3.vuejs.org/api/options-misc.html#compileroptions)]\n- `v-is` has been deprecated in favor of `is=\"vue:xxx\"` [[Docs](https://v3.vuejs.org/api/special-attributes.html#is)]\n\n### Minor Breaking Changes\n\n- `this.$props` and the `props` object passed to `setup()` now always contain all the keys for declared props, even for props that are absent ([4fe4de0](https://github.com/vuejs/core/commit/4fe4de0a49ffc2461b0394e74674af38ff5e2a20)). This has always been the behavior in Vue 2 and is therefore considered a fix (see reasoning in [#3288](https://github.com/vuejs/core/issues/3288)). However, this could break Vue 3 code that relied on the keys for prop absence checks. The workaround is to use a Symbol default value for props that need absence checks:\n\n  ```js\n  const isAbsent = Symbol()\n\n  export default {\n    props: {\n      foo: { default: isAbsent }\n    },\n    setup(props) {\n      if (props.foo === isAbsent) {\n        // foo is absent\n      }\n    }\n  }\n  ```\n\n- `optionMergeStrategies` functions no longer receive\n  the component instance as the 3rd argument. The argument was technically\n  internal in Vue 2 and only used for generating warnings, and should not\n  be needed in userland code. This removal enables much more efficient\n  caching of option merging.\n\n### Bug Fixes\n\n- **compat:** revert private properties on $options in comapt mode ([ad844cf](https://github.com/vuejs/core/commit/ad844cf1e767137a713f715779969ffb94207c7a)), closes [#3883](https://github.com/vuejs/core/issues/3883)\n- **runtime-core:** fix fragment update inside de-opt slots ([5bce2ae](https://github.com/vuejs/core/commit/5bce2ae723d43f23ccfac961f29b80fc870fba1f)), closes [#3881](https://github.com/vuejs/core/issues/3881)\n\n* **compat:** fix deep data merge with extended constructor ([c7efb96](https://github.com/vuejs/core/commit/c7efb967ca5ab42ea2713331b8e53ae5c2746a78)), closes [#3852](https://github.com/vuejs/core/issues/3852)\n* **compiler-sfc:** fix style injection when using normal script + setup ([8b94464](https://github.com/vuejs/core/commit/8b94464a3b9759a7a98c23efeafc7a9359c9807d)), closes [#3688](https://github.com/vuejs/core/issues/3688)\n* **compiler-sfc:** fix template expression assignment codegen for script setup let refs ([#3626](https://github.com/vuejs/core/issues/3626)) ([2c7bd42](https://github.com/vuejs/core/commit/2c7bd428011e027efa8f66487d2269c8dd79a2b0)), closes [#3625](https://github.com/vuejs/core/issues/3625)\n* **runtime-core:** align option merge behavior with Vue 2 ([e2ca67b](https://github.com/vuejs/core/commit/e2ca67b59a4de57a9bce8d3394263ba493a35a39)), closes [#3566](https://github.com/vuejs/core/issues/3566) [#2791](https://github.com/vuejs/core/issues/2791)\n* **runtime-dom/v-model:** only set selectedIndex when the value changes ([#3845](https://github.com/vuejs/core/issues/3845)) ([ecd97ee](https://github.com/vuejs/core/commit/ecd97ee6e465ec5c841d58d96833fece4e899785))\n* **suspense:** fix suspense regression for errored template component ([44996d1](https://github.com/vuejs/core/commit/44996d1a0a2de1bc6b3abfac6b2b8b3c969d4e01)), closes [#3857](https://github.com/vuejs/core/issues/3857)\n* **watch:** avoid traversing objects that are marked non-reactive ([9acc9a1](https://github.com/vuejs/core/commit/9acc9a1fa838bdcdf673d2f7cc3f996b2b69ffbc))\n* **compiler-core:** improve the isMemberExpression function ([#3675](https://github.com/vuejs/core/issues/3675)) ([9b2e894](https://github.com/vuejs/core/commit/9b2e8940176b3b75fa052b3c3e9eeaabc46a95e6))\n* **compiler-dom:** fix in-browser attribute value decoding w/ html tags ([6690372](https://github.com/vuejs/core/commit/669037277b03bb8e67f517faf2811a8668ea86d6)), closes [#3001](https://github.com/vuejs/core/issues/3001)\n* **compiler-sfc:** correctly remove parens used for wrapping ([#3582](https://github.com/vuejs/core/issues/3582)) ([6bfb50a](https://github.com/vuejs/core/commit/6bfb50aff98038a1f854ce24733f545eec2ee796)), closes [#3581](https://github.com/vuejs/core/issues/3581)\n* **reactivity:** ensure computed always expose value ([03a7a73](https://github.com/vuejs/core/commit/03a7a73148a9e210a7889c7a2ecf925338735c70)), closes [#3099](https://github.com/vuejs/core/issues/3099) [#910](https://github.com/vuejs/core/issues/910)\n* **runtime-core:** fix cases of reused children arrays in render functions ([#3670](https://github.com/vuejs/core/issues/3670)) ([a641eb2](https://github.com/vuejs/core/commit/a641eb201fe51620d50884b988f6fefc3e21a20b)), closes [#3666](https://github.com/vuejs/core/issues/3666)\n* **runtime-core:** fix resolving inheritAttrs from mixins ([#3742](https://github.com/vuejs/core/issues/3742)) ([d6607c9](https://github.com/vuejs/core/commit/d6607c9864376fbe17899f3d35fc7b097670a1b1)), closes [#3741](https://github.com/vuejs/core/issues/3741)\n* **runtime-core:** should disable tracking inside directive lifecycle hooks ([#3699](https://github.com/vuejs/core/issues/3699)) ([ff50e8d](https://github.com/vuejs/core/commit/ff50e8d78c033252c4ce7ffddb8069b3ddae5936))\n* **runtime-core:** stricter compat root mount check ([32e2133](https://github.com/vuejs/core/commit/32e21333dd1197a978cf42802729b2133bda5a0b))\n* **runtime-dom:** should remove attribute when binding `null` to `value` ([#3564](https://github.com/vuejs/core/issues/3564)) ([e3f5dcb](https://github.com/vuejs/core/commit/e3f5dcb99bf42fed48d995438e459203dc3f6ed0))\n* **suspense:** fix suspense patching in optimized mode ([9f24195](https://github.com/vuejs/core/commit/9f24195d2ce24184ccdc5020793dd9423f0d3148)), closes [#3828](https://github.com/vuejs/core/issues/3828)\n* **transition:** fix higher order transition components with merged listeners ([071986a](https://github.com/vuejs/core/commit/071986a2c6459fd99b91a48793a9ab6d6618b52d)), closes [#3227](https://github.com/vuejs/core/issues/3227)\n* **keep-alive:** include/exclude should work with async component ([#3531](https://github.com/vuejs/core/issues/3531)) ([9e3708c](https://github.com/vuejs/core/commit/9e3708ca754c0ecd66dbb45984f8d103772bd55c)), closes [#3529](https://github.com/vuejs/core/issues/3529)\n* **runtime-core:** properly check forwarded slots type ([#3781](https://github.com/vuejs/core/issues/3781)) ([e8ddf86](https://github.com/vuejs/core/commit/e8ddf8608021785c7b1b6f4211c633b40f26ddfc)), closes [#3779](https://github.com/vuejs/core/issues/3779)\n* **runtime-core:** should not track dynamic children when the user calls a compiled slot inside template expression ([#3554](https://github.com/vuejs/core/issues/3554)) ([2010607](https://github.com/vuejs/core/commit/201060717d4498b4b7933bf8a8513866ab9347e4)), closes [#3548](https://github.com/vuejs/core/issues/3548) [#3569](https://github.com/vuejs/core/issues/3569)\n* **runtime-core/teleport:** ensure the nested teleport can be unmounted correctly ([#3629](https://github.com/vuejs/core/issues/3629)) ([4e3f82f](https://github.com/vuejs/core/commit/4e3f82f6835472650741896e19fbdc116d86d1eb)), closes [#3623](https://github.com/vuejs/core/issues/3623)\n* **scheduler:** handle preFlush cb queued inside postFlush cb ([b57e995](https://github.com/vuejs/core/commit/b57e995edd29eff685aeaf40712e0e029073d1cb)), closes [#3806](https://github.com/vuejs/core/issues/3806)\n* **ssr:** handle hydrated async component unmounted before resolve ([b46a4dc](https://github.com/vuejs/core/commit/b46a4dccf656280f9905e1bdc47022cb01c062c3)), closes [#3787](https://github.com/vuejs/core/issues/3787)\n* **watch:** should not leak this context to setup watch getters ([1526f94](https://github.com/vuejs/core/commit/1526f94edf023899490d7c58afcf36b051e25b6c)), closes [#3603](https://github.com/vuejs/core/issues/3603)\n* **compat:** avoid accidentally delete the modelValue prop ([#3772](https://github.com/vuejs/core/issues/3772)) ([4f17be7](https://github.com/vuejs/core/commit/4f17be7b1ce4872ded085a36b95c1897d8c1f299))\n* **compat:** enum coercion warning ([#3755](https://github.com/vuejs/core/issues/3755)) ([f01aadf](https://github.com/vuejs/core/commit/f01aadf2a16a7bef422eb039d7b157bef9ad32fc))\n* **compiler-core:** fix whitespace management for slots with whitespace: 'preserve' ([#3767](https://github.com/vuejs/core/issues/3767)) ([47da921](https://github.com/vuejs/core/commit/47da92146c9fb3fa6b1e250e064ca49b74d815e4)), closes [#3766](https://github.com/vuejs/core/issues/3766)\n* **compiler-dom:** comments in the v-if branches should be ignored when used in Transition ([#3622](https://github.com/vuejs/core/issues/3622)) ([7c74feb](https://github.com/vuejs/core/commit/7c74feb3dc6beae7ff3ad22193be3b5a0f4d8aac)), closes [#3619](https://github.com/vuejs/core/issues/3619)\n* **compiler-sfc:** support tsx in setup script ([#3825](https://github.com/vuejs/core/issues/3825)) ([01e8ba8](https://github.com/vuejs/core/commit/01e8ba8f873afe3857a23fb68b44fdc057e31781)), closes [#3808](https://github.com/vuejs/core/issues/3808)\n* **compiler-ssr:** disable hoisting in compiler-ssr ([3ef1fcc](https://github.com/vuejs/core/commit/3ef1fcc8590da186664197a0a82e7856011c1693)), closes [#3536](https://github.com/vuejs/core/issues/3536)\n* **devtools:** send update to component owning the slot ([1355ee2](https://github.com/vuejs/core/commit/1355ee27a65d466bfe8f3a7ba99aa2213e25bc50))\n* **runtime-core:** avoid double-setting props when casting ([0255be2](https://github.com/vuejs/core/commit/0255be2f4b3581bfdf4af9368dcd6c1a27a5ee03)), closes [#3371](https://github.com/vuejs/core/issues/3371) [#3384](https://github.com/vuejs/core/issues/3384)\n* **runtime-core:** avoid the proxy object polluting the slots of the internal instance ([#3698](https://github.com/vuejs/core/issues/3698)) ([4ce0df6](https://github.com/vuejs/core/commit/4ce0df6ef1a31ee45402e61e01777e3836b2c223)), closes [#3695](https://github.com/vuejs/core/issues/3695)\n* **types:** declared prop keys should always exist in `props` argument ([#3726](https://github.com/vuejs/core/issues/3726)) ([9b160b9](https://github.com/vuejs/core/commit/9b160b940555abb6b6ce722fddbd9649ee196f7b))\n* **types/reactivity:** error TS4058 caused by `RefSymbol` ([#2548](https://github.com/vuejs/core/issues/2548)) ([90aa835](https://github.com/vuejs/core/commit/90aa8358129f25826bfc4c234325c1442aef8d55))\n* **compat:** correctly merge lifecycle hooks when using Vue.extend ([#3762](https://github.com/vuejs/core/issues/3762)) ([2bfb8b5](https://github.com/vuejs/core/commit/2bfb8b574d39a20a0e4da2ff4f2c007680ee2038)), closes [#3761](https://github.com/vuejs/core/issues/3761)\n* **compiler-core:** bail out to array children when the element has custom directives + only one text child node ([#3757](https://github.com/vuejs/core/issues/3757)) ([a56ab14](https://github.com/vuejs/core/commit/a56ab148fd1f2702e699d31cdc854800c8283fde))\n* **compat:** handle and warn config.optionMergeStrategies ([94e69fd](https://github.com/vuejs/core/commit/94e69fd3896214da6ff8b9fb09ad942c598053c7))\n* **compiler-core:** preserve comment content in production when comments option is enabled ([e486254](https://github.com/vuejs/core/commit/e4862544310a4187dfc8b3a49944700888bb60e3))\n* **hmr:** don't remove \\_\\_file key from component type ([9db3cbb](https://github.com/vuejs/core/commit/9db3cbbfc1a072675a8d0e53edf3869af115dc60))\n* **hydration:** fix update before async component is hydrated ([#3563](https://github.com/vuejs/core/issues/3563)) ([c8d9683](https://github.com/vuejs/core/commit/c8d96837b871d7ad34cd73b4669338be5fdd59fd)), closes [#3560](https://github.com/vuejs/core/issues/3560)\n* **reactivity:** fix tracking for readonly + reactive Map ([#3604](https://github.com/vuejs/core/issues/3604)) ([5036c51](https://github.com/vuejs/core/commit/5036c51cb78435c145ffea5e82cd620d0d056ff7)), closes [#3602](https://github.com/vuejs/core/issues/3602)\n* **runtime-core:** ensure declare prop keys are always present ([4fe4de0](https://github.com/vuejs/core/commit/4fe4de0a49ffc2461b0394e74674af38ff5e2a20)), closes [#3288](https://github.com/vuejs/core/issues/3288)\n* **runtime-core:** watching multiple sources: computed ([#3066](https://github.com/vuejs/core/issues/3066)) ([e7300eb](https://github.com/vuejs/core/commit/e7300eb47960a153311d568d7976ac5256eb6297)), closes [#3068](https://github.com/vuejs/core/issues/3068)\n* **Teleport:** avoid changing the reference of vnode.dynamicChildren ([#3642](https://github.com/vuejs/core/issues/3642)) ([43f7815](https://github.com/vuejs/core/commit/43f78151bfdff2103a9be25e66e3f3be68d03a08)), closes [#3641](https://github.com/vuejs/core/issues/3641)\n* **watch:** avoid traversing non-plain objects ([62b8f4a](https://github.com/vuejs/core/commit/62b8f4a39ca56b48a8c8fdf7e200cb80735e16ae))\n* **watch:** this.$watch should support watching keypath ([870f2a7](https://github.com/vuejs/core/commit/870f2a7ba35245fd8c008d2ff666ea130a7e4704))\n\n# [3.1.0-beta.7](https://github.com/vuejs/core/compare/v3.1.0-beta.6...v3.1.0-beta.7) (2021-06-02)\n\n### Bug Fixes\n\n- **compat:** fix deep data merge with extended constructor ([c7efb96](https://github.com/vuejs/core/commit/c7efb967ca5ab42ea2713331b8e53ae5c2746a78)), closes [#3852](https://github.com/vuejs/core/issues/3852)\n- **compiler-sfc:** fix style injection when using normal script + setup ([8b94464](https://github.com/vuejs/core/commit/8b94464a3b9759a7a98c23efeafc7a9359c9807d)), closes [#3688](https://github.com/vuejs/core/issues/3688)\n- **compiler-sfc:** fix template expression assignment codegen for script setup let refs ([#3626](https://github.com/vuejs/core/issues/3626)) ([2c7bd42](https://github.com/vuejs/core/commit/2c7bd428011e027efa8f66487d2269c8dd79a2b0)), closes [#3625](https://github.com/vuejs/core/issues/3625)\n- **runtime-core:** align option merge behavior with Vue 2 ([e2ca67b](https://github.com/vuejs/core/commit/e2ca67b59a4de57a9bce8d3394263ba493a35a39)), closes [#3566](https://github.com/vuejs/core/issues/3566) [#2791](https://github.com/vuejs/core/issues/2791)\n- **runtime-dom/v-model:** only set selectedIndex when the value changes ([#3845](https://github.com/vuejs/core/issues/3845)) ([ecd97ee](https://github.com/vuejs/core/commit/ecd97ee6e465ec5c841d58d96833fece4e899785))\n- **suspense:** fix suspense regression for errored template component ([44996d1](https://github.com/vuejs/core/commit/44996d1a0a2de1bc6b3abfac6b2b8b3c969d4e01)), closes [#3857](https://github.com/vuejs/core/issues/3857)\n- **watch:** avoid traversing objects that are marked non-reactive ([9acc9a1](https://github.com/vuejs/core/commit/9acc9a1fa838bdcdf673d2f7cc3f996b2b69ffbc))\n\n### Code Refactoring\n\n- adjust component options merge cache strategy ([1e35a86](https://github.com/vuejs/core/commit/1e35a860b995c1158d5c4e1706d2fc9bcd3b8412))\n\n### Performance Improvements\n\n- avoid deopt for props/emits normalization when global mixins are used ([51d2be2](https://github.com/vuejs/core/commit/51d2be20386d4dc59006d31a1cc96676871027ce))\n\n### BREAKING CHANGES\n\n- optionMergeStrategies functions no longer receive\n  the component instance as the 3rd argument. The argument was technically\n  internal in Vue 2 and only used for generating warnings, and should not\n  be needed in userland code. This removal enables much more efficient\n  caching of option merging.\n\n# [3.1.0-beta.6](https://github.com/vuejs/core/compare/v3.1.0-beta.5...v3.1.0-beta.6) (2021-05-28)\n\n### Bug Fixes\n\n- **compiler-core:** improve the isMemberExpression function ([#3675](https://github.com/vuejs/core/issues/3675)) ([9b2e894](https://github.com/vuejs/core/commit/9b2e8940176b3b75fa052b3c3e9eeaabc46a95e6))\n- **compiler-dom:** fix in-browser attribute value decoding w/ html tags ([6690372](https://github.com/vuejs/core/commit/669037277b03bb8e67f517faf2811a8668ea86d6)), closes [#3001](https://github.com/vuejs/core/issues/3001)\n- **compiler-sfc:** correctly remove parens used for wrapping ([#3582](https://github.com/vuejs/core/issues/3582)) ([6bfb50a](https://github.com/vuejs/core/commit/6bfb50aff98038a1f854ce24733f545eec2ee796)), closes [#3581](https://github.com/vuejs/core/issues/3581)\n- **reactivity:** ensure computed always expose value ([03a7a73](https://github.com/vuejs/core/commit/03a7a73148a9e210a7889c7a2ecf925338735c70)), closes [#3099](https://github.com/vuejs/core/issues/3099) [#910](https://github.com/vuejs/core/issues/910)\n- **runtime-core:** fix cases of reused children arrays in render functions ([#3670](https://github.com/vuejs/core/issues/3670)) ([a641eb2](https://github.com/vuejs/core/commit/a641eb201fe51620d50884b988f6fefc3e21a20b)), closes [#3666](https://github.com/vuejs/core/issues/3666)\n- **runtime-core:** fix resolving inheritAttrs from mixins ([#3742](https://github.com/vuejs/core/issues/3742)) ([d6607c9](https://github.com/vuejs/core/commit/d6607c9864376fbe17899f3d35fc7b097670a1b1)), closes [#3741](https://github.com/vuejs/core/issues/3741)\n- **runtime-core:** should disable tracking inside directive lifecycle hooks ([#3699](https://github.com/vuejs/core/issues/3699)) ([ff50e8d](https://github.com/vuejs/core/commit/ff50e8d78c033252c4ce7ffddb8069b3ddae5936))\n- **runtime-core:** stricter compat root mount check ([32e2133](https://github.com/vuejs/core/commit/32e21333dd1197a978cf42802729b2133bda5a0b))\n- **runtime-dom:** should remove attribute when binding `null` to `value` ([#3564](https://github.com/vuejs/core/issues/3564)) ([e3f5dcb](https://github.com/vuejs/core/commit/e3f5dcb99bf42fed48d995438e459203dc3f6ed0))\n- **suspense:** fix suspense patching in optimized mode ([9f24195](https://github.com/vuejs/core/commit/9f24195d2ce24184ccdc5020793dd9423f0d3148)), closes [#3828](https://github.com/vuejs/core/issues/3828)\n- **transition:** fix higher order transition components with merged listeners ([071986a](https://github.com/vuejs/core/commit/071986a2c6459fd99b91a48793a9ab6d6618b52d)), closes [#3227](https://github.com/vuejs/core/issues/3227)\n\n# [3.1.0-beta.5](https://github.com/vuejs/core/compare/v3.1.0-beta.4...v3.1.0-beta.5) (2021-05-26)\n\n### Bug Fixes\n\n- **keep-alive:** include/exclude should work with async component ([#3531](https://github.com/vuejs/core/issues/3531)) ([9e3708c](https://github.com/vuejs/core/commit/9e3708ca754c0ecd66dbb45984f8d103772bd55c)), closes [#3529](https://github.com/vuejs/core/issues/3529)\n- **runtime-core:** properly check forwarded slots type ([#3781](https://github.com/vuejs/core/issues/3781)) ([e8ddf86](https://github.com/vuejs/core/commit/e8ddf8608021785c7b1b6f4211c633b40f26ddfc)), closes [#3779](https://github.com/vuejs/core/issues/3779)\n- **runtime-core:** should not track dynamic children when the user calls a compiled slot inside template expression ([#3554](https://github.com/vuejs/core/issues/3554)) ([2010607](https://github.com/vuejs/core/commit/201060717d4498b4b7933bf8a8513866ab9347e4)), closes [#3548](https://github.com/vuejs/core/issues/3548) [#3569](https://github.com/vuejs/core/issues/3569)\n- **runtime-core/teleport:** ensure the nested teleport can be unmounted correctly ([#3629](https://github.com/vuejs/core/issues/3629)) ([4e3f82f](https://github.com/vuejs/core/commit/4e3f82f6835472650741896e19fbdc116d86d1eb)), closes [#3623](https://github.com/vuejs/core/issues/3623)\n- **scheduler:** handle preFlush cb queued inside postFlush cb ([b57e995](https://github.com/vuejs/core/commit/b57e995edd29eff685aeaf40712e0e029073d1cb)), closes [#3806](https://github.com/vuejs/core/issues/3806)\n- **ssr:** handle hydrated async component unmounted before resolve ([b46a4dc](https://github.com/vuejs/core/commit/b46a4dccf656280f9905e1bdc47022cb01c062c3)), closes [#3787](https://github.com/vuejs/core/issues/3787)\n- **watch:** should not leak this context to setup watch getters ([1526f94](https://github.com/vuejs/core/commit/1526f94edf023899490d7c58afcf36b051e25b6c)), closes [#3603](https://github.com/vuejs/core/issues/3603)\n\n# [3.1.0-beta.4](https://github.com/vuejs/core/compare/v3.1.0-beta.3...v3.1.0-beta.4) (2021-05-24)\n\n### Bug Fixes\n\n- **compat:** avoid accidentally delete the modelValue prop ([#3772](https://github.com/vuejs/core/issues/3772)) ([4f17be7](https://github.com/vuejs/core/commit/4f17be7b1ce4872ded085a36b95c1897d8c1f299))\n- **compat:** enum coercion warning ([#3755](https://github.com/vuejs/core/issues/3755)) ([f01aadf](https://github.com/vuejs/core/commit/f01aadf2a16a7bef422eb039d7b157bef9ad32fc))\n- **compiler-core:** fix whitespace management for slots with whitespace: 'preserve' ([#3767](https://github.com/vuejs/core/issues/3767)) ([47da921](https://github.com/vuejs/core/commit/47da92146c9fb3fa6b1e250e064ca49b74d815e4)), closes [#3766](https://github.com/vuejs/core/issues/3766)\n- **compiler-dom:** comments in the v-if branches should be ignored when used in Transition ([#3622](https://github.com/vuejs/core/issues/3622)) ([7c74feb](https://github.com/vuejs/core/commit/7c74feb3dc6beae7ff3ad22193be3b5a0f4d8aac)), closes [#3619](https://github.com/vuejs/core/issues/3619)\n- **compiler-sfc:** support tsx in setup script ([#3825](https://github.com/vuejs/core/issues/3825)) ([01e8ba8](https://github.com/vuejs/core/commit/01e8ba8f873afe3857a23fb68b44fdc057e31781)), closes [#3808](https://github.com/vuejs/core/issues/3808)\n- **compiler-ssr:** disable hoisting in compiler-ssr ([3ef1fcc](https://github.com/vuejs/core/commit/3ef1fcc8590da186664197a0a82e7856011c1693)), closes [#3536](https://github.com/vuejs/core/issues/3536)\n- **devtools:** send update to component owning the slot ([1355ee2](https://github.com/vuejs/core/commit/1355ee27a65d466bfe8f3a7ba99aa2213e25bc50))\n- **runtime-core:** avoid double-setting props when casting ([0255be2](https://github.com/vuejs/core/commit/0255be2f4b3581bfdf4af9368dcd6c1a27a5ee03)), closes [#3371](https://github.com/vuejs/core/issues/3371) [#3384](https://github.com/vuejs/core/issues/3384)\n- **runtime-core:** avoid the proxy object polluting the slots of the internal instance ([#3698](https://github.com/vuejs/core/issues/3698)) ([4ce0df6](https://github.com/vuejs/core/commit/4ce0df6ef1a31ee45402e61e01777e3836b2c223)), closes [#3695](https://github.com/vuejs/core/issues/3695)\n- **types:** declared prop keys should always exist in `props` argument ([#3726](https://github.com/vuejs/core/issues/3726)) ([9b160b9](https://github.com/vuejs/core/commit/9b160b940555abb6b6ce722fddbd9649ee196f7b))\n- **types/reactivity:** error TS4058 caused by `RefSymbol` ([#2548](https://github.com/vuejs/core/issues/2548)) ([90aa835](https://github.com/vuejs/core/commit/90aa8358129f25826bfc4c234325c1442aef8d55))\n\n### Features\n\n- **devtools:** performance events ([f7c54ca](https://github.com/vuejs/core/commit/f7c54caeb1dac69a26b79c98409e9633a7fe4bd3))\n\n# [3.1.0-beta.3](https://github.com/vuejs/core/compare/v3.1.0-beta.2...v3.1.0-beta.3) (2021-05-12)\n\n### Bug Fixes\n\n- **compat:** correctly merge lifecycle hooks when using Vue.extend ([#3762](https://github.com/vuejs/core/issues/3762)) ([2bfb8b5](https://github.com/vuejs/core/commit/2bfb8b574d39a20a0e4da2ff4f2c007680ee2038)), closes [#3761](https://github.com/vuejs/core/issues/3761)\n- **compiler-core:** bail out to array children when the element has custom directives + only one text child node ([#3757](https://github.com/vuejs/core/issues/3757)) ([a56ab14](https://github.com/vuejs/core/commit/a56ab148fd1f2702e699d31cdc854800c8283fde))\n\n# [3.1.0-beta.2](https://github.com/vuejs/core/compare/v3.1.0-beta.1...v3.1.0-beta.2) (2021-05-08)\n\n### Bug Fixes\n\n- **compat:** handle and warn config.optionMergeStrategies ([94e69fd](https://github.com/vuejs/core/commit/94e69fd3896214da6ff8b9fb09ad942c598053c7))\n\n# [3.1.0-beta.1](https://github.com/vuejs/core/compare/v3.0.11...v3.1.0-beta.1) (2021-05-08)\n\n### Bug Fixes\n\n- **compiler-core:** preserve comment content in production when comments option is enabled ([e486254](https://github.com/vuejs/core/commit/e4862544310a4187dfc8b3a49944700888bb60e3))\n- **hmr:** don't remove \\_\\_file key from component type ([9db3cbb](https://github.com/vuejs/core/commit/9db3cbbfc1a072675a8d0e53edf3869af115dc60))\n- **hydration:** fix update before async component is hydrated ([#3563](https://github.com/vuejs/core/issues/3563)) ([c8d9683](https://github.com/vuejs/core/commit/c8d96837b871d7ad34cd73b4669338be5fdd59fd)), closes [#3560](https://github.com/vuejs/core/issues/3560)\n- **reactivity:** fix tracking for readonly + reactive Map ([#3604](https://github.com/vuejs/core/issues/3604)) ([5036c51](https://github.com/vuejs/core/commit/5036c51cb78435c145ffea5e82cd620d0d056ff7)), closes [#3602](https://github.com/vuejs/core/issues/3602)\n- **runtime-core:** ensure declare prop keys are always present ([4fe4de0](https://github.com/vuejs/core/commit/4fe4de0a49ffc2461b0394e74674af38ff5e2a20)), closes [#3288](https://github.com/vuejs/core/issues/3288)\n- **runtime-core:** watching multiple sources: computed ([#3066](https://github.com/vuejs/core/issues/3066)) ([e7300eb](https://github.com/vuejs/core/commit/e7300eb47960a153311d568d7976ac5256eb6297)), closes [#3068](https://github.com/vuejs/core/issues/3068)\n- **Teleport:** avoid changing the reference of vnode.dynamicChildren ([#3642](https://github.com/vuejs/core/issues/3642)) ([43f7815](https://github.com/vuejs/core/commit/43f78151bfdff2103a9be25e66e3f3be68d03a08)), closes [#3641](https://github.com/vuejs/core/issues/3641)\n- **watch:** avoid traversing non-plain objects ([62b8f4a](https://github.com/vuejs/core/commit/62b8f4a39ca56b48a8c8fdf7e200cb80735e16ae))\n- **watch:** this.$watch should support watching keypath ([870f2a7](https://github.com/vuejs/core/commit/870f2a7ba35245fd8c008d2ff666ea130a7e4704))\n\n### Features\n\n- onServerPrefetch ([#3070](https://github.com/vuejs/core/issues/3070)) ([349eb0f](https://github.com/vuejs/core/commit/349eb0f0ad78f9cb491278eb4c7f9fe0c2e78b79))\n- support component-level `compilerOptions` when using runtime compiler ([ce0bbe0](https://github.com/vuejs/core/commit/ce0bbe053abaf8ba18de8baf535e175048596ee5))\n- **compiler-core:** whitespace handling strategy ([dee3d6a](https://github.com/vuejs/core/commit/dee3d6ab8b4da6653d15eb148c51d9878007f6b6))\n- **config:** support configuring runtime compiler via `app.config.compilerOptions` ([091e6d6](https://github.com/vuejs/core/commit/091e6d67bfcc215227d78be578c68ead542481ad))\n- **devtools:** improved KeepAlive support ([03ae300](https://github.com/vuejs/core/commit/03ae3006e1e678ade4377cd10d206e8f7b4ad0cb))\n- support casting plain element to component via is=\"vue:xxx\" ([af9e699](https://github.com/vuejs/core/commit/af9e6999e1779f56b5cf827b97310d8e4e1fe5ec))\n\n### Performance Improvements\n\n- only trigger $attrs update when it has actually changed ([5566d39](https://github.com/vuejs/core/commit/5566d39d467ebdd4e4234bc97d62600ff01ea28e))\n- **compiler:** skip unnecessary checks when parsing end tag ([048ac29](https://github.com/vuejs/core/commit/048ac299f35709b25ae1bc1efa67d2abc53dbc3b))\n"
  },
  {
    "path": "changelogs/CHANGELOG-3.2.md",
    "content": "## [3.2.47](https://github.com/vuejs/core/compare/v3.2.46...v3.2.47) (2023-02-02)\n\n\n### Bug Fixes\n\n* **build:** enforce __esModule interop for cjs builds ([4b70366](https://github.com/vuejs/core/commit/4b7036653e5dfd7be95e6efe8c79621b52dcccb7))\n\n\n\n## [3.2.46](https://github.com/vuejs/core/compare/v3.2.45...v3.2.46) (2023-02-02)\n\n\n### Bug Fixes\n\n* **build:** ensure cjs re-exports can be properly detected when imported from esm ([fb6ff3e](https://github.com/vuejs/core/commit/fb6ff3e99689022d963ea7257b03f73ff514c0c4))\n* **build:** ensure type exports is first ([957722c](https://github.com/vuejs/core/commit/957722c4185ea87aabc711f6f8997e528dd3ba1b))\n* **build:** fix cjs re-exports check for compat build ([ce064a1](https://github.com/vuejs/core/commit/ce064a172b3b5bcb096b4984fe0c1a54177ac9c0))\n* **compat:** fix custom transition classes in compat mode ([#7435](https://github.com/vuejs/core/issues/7435)) ([efe2efd](https://github.com/vuejs/core/commit/efe2efd210f500311e5b603345cb0d353886bd7a)), closes [#6253](https://github.com/vuejs/core/issues/6253)\n* **compiler-core:** typeof should be allowed in browser expression validation ([#7037](https://github.com/vuejs/core/issues/7037)) ([3783866](https://github.com/vuejs/core/commit/378386694be6dd43da71f1fa08ee9c5705c13f86))\n* **compiler-sfc:** allow declaring variables after defineProps ([#7461](https://github.com/vuejs/core/issues/7461)) ([686c829](https://github.com/vuejs/core/commit/686c829fec9137cdfe6e51af34f2af01a575f7c6))\n* **compiler-sfc:** always generate runtime prop type for Function ([#7112](https://github.com/vuejs/core/issues/7112)) ([584eae6](https://github.com/vuejs/core/commit/584eae60d1abe80d15b317ec80b7556712df8e5a)), closes [#7111](https://github.com/vuejs/core/issues/7111)\n* **compiler-sfc:** support resolving type declaration from normal script ([#5831](https://github.com/vuejs/core/issues/5831)) ([30399d4](https://github.com/vuejs/core/commit/30399d46b15f890056e7a5d076cd588b3806cc15)), closes [#5830](https://github.com/vuejs/core/issues/5830)\n* **compiler:** add `hgroup` to supported `HTML_TAGS` ([#6321](https://github.com/vuejs/core/issues/6321)) ([7443174](https://github.com/vuejs/core/commit/7443174e2aa9244bc08c63b4d6c78acc6ff89767)), closes [#6313](https://github.com/vuejs/core/issues/6313)\n* **custom-elements:** use strict number casting ([7d0c63f](https://github.com/vuejs/core/commit/7d0c63ff4361e59e820441a24bf4fb2a93335a1e)), closes [#4946](https://github.com/vuejs/core/issues/4946) [#2598](https://github.com/vuejs/core/issues/2598) [#2604](https://github.com/vuejs/core/issues/2604)\n* **customElement:** customElement can emit event ([#7296](https://github.com/vuejs/core/issues/7296)) ([c6e5bda](https://github.com/vuejs/core/commit/c6e5bda27d13554675d68dbe33b07f3474467aa6))\n* **reactivity-transform:** fix $$ escape edge cases ([e06d3b6](https://github.com/vuejs/core/commit/e06d3b614ea518e9cdf83fca9200fc816eb4e5a1)), closes [#6312](https://github.com/vuejs/core/issues/6312) [#6944](https://github.com/vuejs/core/issues/6944)\n* **reactivity-transform:** prohibit const assignment at compile time ([#6993](https://github.com/vuejs/core/issues/6993)) ([3427052](https://github.com/vuejs/core/commit/3427052229db3448252d938292a40e960a0f4b9c)), closes [#6992](https://github.com/vuejs/core/issues/6992)\n* **reactivity:** `triggerRef` working with `toRef` from reactive ([#7507](https://github.com/vuejs/core/issues/7507)) ([e64c9ae](https://github.com/vuejs/core/commit/e64c9ae957aa2606b55e8652bbde30a6ada59fb0))\n* **reactivity:** ensure watch(Effect) can run independent of unmounted instance if created in a detached effectScope (fix [#7319](https://github.com/vuejs/core/issues/7319)) ([#7330](https://github.com/vuejs/core/issues/7330)) ([cd7c887](https://github.com/vuejs/core/commit/cd7c887b755810aedf83f3d458cb956d5b147f6f))\n* **reactivity:** track hasOwnProperty ([588bd44](https://github.com/vuejs/core/commit/588bd44f036b79d7dee5d23661aa7244f70e6beb)), closes [#2619](https://github.com/vuejs/core/issues/2619) [#2621](https://github.com/vuejs/core/issues/2621)\n* **runtime-core:** ensure prop type validation warning shows custom class names  ([#7198](https://github.com/vuejs/core/issues/7198)) ([620327d](https://github.com/vuejs/core/commit/620327d527593c6263a21500baddbae1ebc30db8))\n* **runtime-core:** fix keep-alive cache prune logic on vnodes with same type but different keys ([#7510](https://github.com/vuejs/core/issues/7510)) ([1fde49c](https://github.com/vuejs/core/commit/1fde49c0f57cc50fedf91366a274c9759d1d9a39)), closes [#7355](https://github.com/vuejs/core/issues/7355)\n* **runtime-core:** set scope id before props ([#6948](https://github.com/vuejs/core/issues/6948)) ([da2ced1](https://github.com/vuejs/core/commit/da2ced15339b6fdb7a1459fa359bb79346a82bc2)), closes [#6923](https://github.com/vuejs/core/issues/6923)\n* **runtime-dom:** style update error when component use shorthand properties ([#7425](https://github.com/vuejs/core/issues/7425)) ([b7cfa6f](https://github.com/vuejs/core/commit/b7cfa6f53952daced312862fbb3a88c86e42a77e))\n* **shared:** `feDistanceLight` changed to `feDistantLight` ([#7540](https://github.com/vuejs/core/issues/7540)) ([bef85e7](https://github.com/vuejs/core/commit/bef85e7975084b05af00b60ecd171c83f251c6d5))\n* **shared:** toNumber should only coerce strings ([b55846f](https://github.com/vuejs/core/commit/b55846f05c4a3b163be2ed70ce64014feec29fac))\n* **types/effectScope:** re-expose `active` as readonly property ([#6187](https://github.com/vuejs/core/issues/6187)) ([59ffe5e](https://github.com/vuejs/core/commit/59ffe5ee1f1618be119875313970c72050b37b03)), closes [#6186](https://github.com/vuejs/core/issues/6186)\n* **types:** accept sync `serverPrefetch()` ([#7000](https://github.com/vuejs/core/issues/7000)) ([5f1883e](https://github.com/vuejs/core/commit/5f1883ec53547d0847e1270f5a8fb0c46396fb07))\n* **types:** add or update referrerpolicy ([#7199](https://github.com/vuejs/core/issues/7199)) ([1fa3d95](https://github.com/vuejs/core/commit/1fa3d9573051f549e6d381a5e88ec8d5d855e4c9))\n* **types:** allow assigning wider SetupContext type ([#2818](https://github.com/vuejs/core/issues/2818)) ([eb2a832](https://github.com/vuejs/core/commit/eb2a83283caa9de0a45881d860a3cbd9d0bdd279)), closes [#2362](https://github.com/vuejs/core/issues/2362)\n* **types:** optional boolean props should have boolean type in return type of defineProps ([#7619](https://github.com/vuejs/core/issues/7619)) ([a0a010d](https://github.com/vuejs/core/commit/a0a010ddc9ba8ef3e883454c73997bf6fb40b385)), closes [#7116](https://github.com/vuejs/core/issues/7116) [#5847](https://github.com/vuejs/core/issues/5847) [#7487](https://github.com/vuejs/core/issues/7487)\n* **v-model:** ensure v-model listener casing is consistent with manual v-on listener ([#7067](https://github.com/vuejs/core/issues/7067)) ([87c72ae](https://github.com/vuejs/core/commit/87c72ae49a315a5464dd0c6b00f07163d1cb39e9)), closes [#7066](https://github.com/vuejs/core/issues/7066)\n\n\n\n## [3.2.45](https://github.com/vuejs/core/compare/v3.2.44...v3.2.45) (2022-11-11)\n\n\n### Bug Fixes\n\n* **compiler/v-model:** catch incorrect v-model usage on prop bindings ([001184e](https://github.com/vuejs/core/commit/001184e6bbbc85c4698f460b1f810beca3aed262)), closes [#5584](https://github.com/vuejs/core/issues/5584)\n* **custom-elements:** also dispatch hyphenated version of emitted events ([#5378](https://github.com/vuejs/core/issues/5378)) ([0b39e46](https://github.com/vuejs/core/commit/0b39e46192c6258d5bf9d3b6992b84edb0b641d3)), closes [#5373](https://github.com/vuejs/core/issues/5373)\n* **custom-elements:** custom element should re-instantiate when inserted again ([#6966](https://github.com/vuejs/core/issues/6966)) ([67890da](https://github.com/vuejs/core/commit/67890daad1a8474c5178565f32a4efa427db911a)), closes [#6934](https://github.com/vuejs/core/issues/6934)\n* **custom-elements:** define declared properties in constructor ([#5328](https://github.com/vuejs/core/issues/5328)) ([55382ae](https://github.com/vuejs/core/commit/55382aed58aa3d937f442ad9445b3fff83a07de1))\n* **custom-elements:** ensure custom elements can inherit provides from ancestors ([#5098](https://github.com/vuejs/core/issues/5098)) ([192dcb6](https://github.com/vuejs/core/commit/192dcb648c0630ac20d2009eed512e142a72654a)), closes [#5096](https://github.com/vuejs/core/issues/5096)\n* **custom-elements:** fix event emitting for async custom elements ([#5601](https://github.com/vuejs/core/issues/5601)) ([665f2ae](https://github.com/vuejs/core/commit/665f2ae121ec31d65cf22bd577f12fb1d9ffa4a2)), closes [#5599](https://github.com/vuejs/core/issues/5599)\n* **custom-elements:** fix number type props casting check ([89f37ce](https://github.com/vuejs/core/commit/89f37ceb62363c77697d177675790a9ab81ba34f)), closes [#5793](https://github.com/vuejs/core/issues/5793) [#5794](https://github.com/vuejs/core/issues/5794)\n* **custom-elements:** properties set pre-upgrade should not show up in $attrs ([afe8899](https://github.com/vuejs/core/commit/afe889999cbcaa11020c46c30b591a5ee6c3d4cf))\n* **custom-elements:** respect slot props in custom element mode ([ffef822](https://github.com/vuejs/core/commit/ffef8228694b39638f07c0fe5bc30d826262b672))\n* **custom-elements:** should not reflect non-decalred properties set before upgrade ([5e50909](https://github.com/vuejs/core/commit/5e509091000779acbfae4c85cc1cc3973b1b2e64))\n* **hmr/keep-alive:** fix error in reload component ([#7049](https://github.com/vuejs/core/issues/7049)) ([a54bff2](https://github.com/vuejs/core/commit/a54bff2c9c8e1d908b4a0f3826ac715c9a35e68c)), closes [#7042](https://github.com/vuejs/core/issues/7042)\n* **runtime-core:** fix move/removal of static fragments containing text nodes ([#6858](https://github.com/vuejs/core/issues/6858)) ([4049ffc](https://github.com/vuejs/core/commit/4049ffcf29dc12dca71f682edf0b422a5c502e23)), closes [#6852](https://github.com/vuejs/core/issues/6852)\n* **sfc:** also generate getter for import bindings during dev ([0594400](https://github.com/vuejs/core/commit/0594400980d3bdc394e92db63fc939a6609f7a94))\n* **sfc:** ensure `<script setup>` binding behavior consistency on `this` between prod and dev ([f73925d](https://github.com/vuejs/core/commit/f73925d76a76ee259749b8b48cb68895f539a00f)), closes [#6248](https://github.com/vuejs/core/issues/6248)\n* **sfc:** ensure consistent dev/prod behavior for non-reactive variables declared in `<script setup>` ([5a3d45a](https://github.com/vuejs/core/commit/5a3d45ae29e26938a36e16c7ab9a804bfe4bcb08)), closes [#5655](https://github.com/vuejs/core/issues/5655)\n* **teleport/css-v-bind:** fix css v-bind for teleported content ([42239cf](https://github.com/vuejs/core/commit/42239cf2846f50b6ac2c060dad381113840d9ea1)), closes [#4605](https://github.com/vuejs/core/issues/4605) [#4609](https://github.com/vuejs/core/issues/4609)\n* **teleport/css-v-bind:** fix css v-bind in teleport in child component slot ([11214ee](https://github.com/vuejs/core/commit/11214eedd2699e15106c44927f4d1206b111fbd3))\n* **v-model:** fix incorrect codegen for non-ref bindings ([15e889a](https://github.com/vuejs/core/commit/15e889afaf75143484946b2dde281572ebf9e8ab)), closes [#6241](https://github.com/vuejs/core/issues/6241)\n\n\n\n## [3.2.44](https://github.com/vuejs/core/compare/v3.2.43...v3.2.44) (2022-11-09)\n\n\n### Bug Fixes\n\n* **watch:** for immediate watch with single source, ensure cb is called with undefined as oldValue ([#7075](https://github.com/vuejs/core/issues/7075)) ([5dc593b](https://github.com/vuejs/core/commit/5dc593ba2833e98eab12bd6c73765805b172185a)), closes [#7074](https://github.com/vuejs/core/issues/7074)\n\n\n\n## [3.2.43](https://github.com/vuejs/core/compare/v3.2.42...v3.2.43) (2022-11-09)\n\n\n### Bug Fixes\n\n* **watch:** ensure oldValue in multi-source watcher is always an array ([23e85e2](https://github.com/vuejs/core/commit/23e85e21a50926c48dea4f978e212e4301c20037)), closes [#7070](https://github.com/vuejs/core/issues/7070)\n\n\n\n## [3.2.42](https://github.com/vuejs/core/compare/v3.2.41...v3.2.42) (2022-11-09)\n\n\n### Bug Fixes\n\n* **compiler-core/v-on:** only apply case preservation on native elements ([#6902](https://github.com/vuejs/core/issues/6902)) ([5bfe438](https://github.com/vuejs/core/commit/5bfe438ef391522bddbe43cd2669061c6a88b03a)), closes [#6900](https://github.com/vuejs/core/issues/6900)\n* **compiler-core/v-on:** support inline handler with return type annotation ([#6769](https://github.com/vuejs/core/issues/6769)) ([bcfe480](https://github.com/vuejs/core/commit/bcfe480d75d822111c0d3e5fcbc7e10e073d53dc)), closes [#6378](https://github.com/vuejs/core/issues/6378)\n* **compiler-core:** avoid duplicate keys in codegen with `v-if` ([#6689](https://github.com/vuejs/core/issues/6689)) ([640cfce](https://github.com/vuejs/core/commit/640cfce4ff808fdfc419058f39a2ff4874a25899)), closes [#6641](https://github.com/vuejs/core/issues/6641)\n* **compiler-core:** fix parsing error on comments between v-if in prod ([dd3354c](https://github.com/vuejs/core/commit/dd3354c4c709c0d76e651bb9202158434619cb6a)), closes [#6843](https://github.com/vuejs/core/issues/6843)\n* **compiler-core:** keep whitespaces between interpolation and comment ([#6828](https://github.com/vuejs/core/issues/6828)) ([4887618](https://github.com/vuejs/core/commit/48876182dbe5ef88a65a0aa7377e882c735b6104)), closes [#6352](https://github.com/vuejs/core/issues/6352)\n* **compiler-sfc:** add semicolon after `defineProps` statement ([#6461](https://github.com/vuejs/core/issues/6461)) ([b72a4af](https://github.com/vuejs/core/commit/b72a4af38a402447d19b4616d09935c390d0702f)), closes [#6428](https://github.com/vuejs/core/issues/6428)\n* **compiler-sfc:** allow type annotation for defineEmits variable ([#5394](https://github.com/vuejs/core/issues/5394)) ([eab7604](https://github.com/vuejs/core/commit/eab76046e3b1779dd7a856b6b974e928075d6a1e)), closes [#5393](https://github.com/vuejs/core/issues/5393)\n* **compiler-sfc:** check import source during binding analysation ([#6826](https://github.com/vuejs/core/issues/6826)) ([4a00fdd](https://github.com/vuejs/core/commit/4a00fddfed16caee7a1e07756b9c110bc928c17a)), closes [#6825](https://github.com/vuejs/core/issues/6825)\n* **compiler-sfc:** fix binding analysis for aliased late import ([8d1f526](https://github.com/vuejs/core/commit/8d1f526174db277ae5aa9297a43f20a43e991294))\n* **compiler-sfc:** fix macro usage in multi-variable declaration ([#6778](https://github.com/vuejs/core/issues/6778)) ([99b6697](https://github.com/vuejs/core/commit/99b6697fb44dd1094ea0bf372c1d05214ffb92a2)), closes [#6757](https://github.com/vuejs/core/issues/6757)\n* **compiler-sfc:** handle method shorthand syntax in withDefaults ([#6972](https://github.com/vuejs/core/issues/6972)) ([8a882ce](https://github.com/vuejs/core/commit/8a882ce0a10bfa5482d6b8a9b68fd49cff4f6937)), closes [#6971](https://github.com/vuejs/core/issues/6971)\n* **compiler-sfc:** only escape parsing-breaking characters in v-bind css var names ([#6816](https://github.com/vuejs/core/issues/6816)) ([57c9013](https://github.com/vuejs/core/commit/57c901383792176fd7267b7d34d845088dbeff63)), closes [#6803](https://github.com/vuejs/core/issues/6803)\n* **compiler-sfc:** require \\<template\\> or \\<script\\> in SFC ([#6781](https://github.com/vuejs/core/issues/6781)) ([a0c7f27](https://github.com/vuejs/core/commit/a0c7f271a2efb2bacf0889a9ac259263b5526112)), closes [#6676](https://github.com/vuejs/core/issues/6676)\n* **compiler-sfc:** resolve computed object key ([#6963](https://github.com/vuejs/core/issues/6963)) ([910fa76](https://github.com/vuejs/core/commit/910fa7677f4ef690b612fae4a069b2293672c439))\n* **compiler-sfc:** support using extends interface with defineProps() ([#4512](https://github.com/vuejs/core/issues/4512)) ([83f7e6f](https://github.com/vuejs/core/commit/83f7e6f8a688e823274379fe79f58b90ea58892d)), closes [#4498](https://github.com/vuejs/core/issues/4498)\n* **compiler-ssr:** fix invalid codegen when v-slot name is explicit empty attr ([#3326](https://github.com/vuejs/core/issues/3326)) ([09bb3e9](https://github.com/vuejs/core/commit/09bb3e996ef17967022243a519d7dcc2921dd049))\n* **compiler/runtime-dom:** ignore comments in inline styles ([#6808](https://github.com/vuejs/core/issues/6808)) ([50e2253](https://github.com/vuejs/core/commit/50e225305721a95515e8aa7dca68ebd5fe9fe025)), closes [#6807](https://github.com/vuejs/core/issues/6807)\n* **compiler:** avoid namespace collisions when transforming template refs in inline mode ([#6975](https://github.com/vuejs/core/issues/6975)) ([2c27556](https://github.com/vuejs/core/commit/2c27556fe5fa8ba991dd55c766a92d3a50fbf8e6)), closes [#6964](https://github.com/vuejs/core/issues/6964)\n* **hmr:** fix hmr for components managed by keep-alive ([#6809](https://github.com/vuejs/core/issues/6809)) ([bdaf83a](https://github.com/vuejs/core/commit/bdaf83aae7b5651965870a0646da5ae4e5d96944)), closes [#6222](https://github.com/vuejs/core/issues/6222)\n* **reactivity-transform:** add semicolon after statements ([#6303](https://github.com/vuejs/core/issues/6303)) ([c4f213b](https://github.com/vuejs/core/commit/c4f213b42535da3558d406da9b33dd1f9455aeaf))\n* **reactivity-transform:** respect user defined symbols that conflict with macros ([#6840](https://github.com/vuejs/core/issues/6840)) ([7663a79](https://github.com/vuejs/core/commit/7663a79a295800da7c889fcd2e8e1e6d775263db)), closes [#6838](https://github.com/vuejs/core/issues/6838)\n* **reactivity:** enable trigger when use str to set length of arr ([#6810](https://github.com/vuejs/core/issues/6810)) ([e6224f4](https://github.com/vuejs/core/commit/e6224f4256be2fdac3651ade87f9f91ccf6def71))\n* **runtime-core:** `in` operator returning `false` for built-in instance properties in `exposeProxy` ([#6138](https://github.com/vuejs/core/issues/6138)) ([32b5124](https://github.com/vuejs/core/commit/32b51249bff70d1e03a3f9193f5a42461974daa6)), closes [#6137](https://github.com/vuejs/core/issues/6137)\n* **runtime-core:** custom-element: ensure number casting of camelCase props. (fix: [#5374](https://github.com/vuejs/core/issues/5374)) ([#5377](https://github.com/vuejs/core/issues/5377)) ([b0b74a1](https://github.com/vuejs/core/commit/b0b74a160c08941fa9a7a5460f36a1f2fccbf423))\n* **runtime-core:** do not throw on unknown directives ([#6671](https://github.com/vuejs/core/issues/6671)) ([0455378](https://github.com/vuejs/core/commit/04553786e4391b3bfa02f50c2a5baa8d2fe8c7a4)), closes [#6340](https://github.com/vuejs/core/issues/6340)\n* **runtime-core:** ensure props definition objects are not mutated during props normalization (close: [#6915](https://github.com/vuejs/core/issues/6915)) ([#6916](https://github.com/vuejs/core/issues/6916)) ([54b6ba3](https://github.com/vuejs/core/commit/54b6ba32cafcc41fa9b7b85f1f1a306923204177))\n* **runtime-core:** watching multiple values - handle `undefined` as initial values (fix: [#5032](https://github.com/vuejs/core/issues/5032)) ([#5033](https://github.com/vuejs/core/issues/5033)) ([bc167b5](https://github.com/vuejs/core/commit/bc167b5c6c7c5756f3b7720a7d3ddcdb2c7f717f))\n* **runtime-dom:** ensure customElement handles empty props correctly. ([#6182](https://github.com/vuejs/core/issues/6182)) ([f67bb50](https://github.com/vuejs/core/commit/f67bb500b6071bc0e55a89709a495a27da73badd)), closes [#6163](https://github.com/vuejs/core/issues/6163) [#6895](https://github.com/vuejs/core/issues/6895)\n* **sfc/types:** improve the type inference using withDefaults ([#6764](https://github.com/vuejs/core/issues/6764)) ([168c857](https://github.com/vuejs/core/commit/168c8572475c82902f9cb0480f85b5d3100ffa0d)), closes [#6552](https://github.com/vuejs/core/issues/6552)\n* **shared:** fix parsing of multi-line inline style ([#6777](https://github.com/vuejs/core/issues/6777)) ([9768949](https://github.com/vuejs/core/commit/9768949ce0cbe91cffb708cf005807413d60c031))\n* **ssr:** remove css number value check ([#6636](https://github.com/vuejs/core/issues/6636)) ([79e7c1e](https://github.com/vuejs/core/commit/79e7c1ee43b39afef3ce316dff0e7e3b6cd7220c)), closes [#6625](https://github.com/vuejs/core/issues/6625)\n* **transition/keep-alive:** fix unmount bug for component with out-in transition ([#6839](https://github.com/vuejs/core/issues/6839)) ([64e6d92](https://github.com/vuejs/core/commit/64e6d9221d353598b5f61c158c978d80e3b4628c)), closes [#6835](https://github.com/vuejs/core/issues/6835)\n* **types/reactivity-transform:** fix type when initial value is not used ([#6821](https://github.com/vuejs/core/issues/6821)) ([fdc5902](https://github.com/vuejs/core/commit/fdc5902cce0d077c722dfd422850ca69fd51be8e)), closes [#6820](https://github.com/vuejs/core/issues/6820)\n* **types:** `$watch` callback parameters type ([#6136](https://github.com/vuejs/core/issues/6136)) ([41d9c47](https://github.com/vuejs/core/commit/41d9c47300888fce9d4ff6a02f69d8a912cded8f)), closes [#6135](https://github.com/vuejs/core/issues/6135)\n* **types:** ensure createBlock() helper accepts Teleport and Suspense types (fix: [#2855](https://github.com/vuejs/core/issues/2855)) ([#5458](https://github.com/vuejs/core/issues/5458)) ([e5fc7dc](https://github.com/vuejs/core/commit/e5fc7dcc02f2dd3fa8172958259049031626375f))\n* **types:** export `Raw` type ([#6380](https://github.com/vuejs/core/issues/6380)) ([e9172db](https://github.com/vuejs/core/commit/e9172db68b86fad2e0bb1de9e5d0dddbe3c2a25e)), closes [#7048](https://github.com/vuejs/core/issues/7048)\n* **types:** should unwrap tuple correctly ([#3820](https://github.com/vuejs/core/issues/3820)) ([e816812](https://github.com/vuejs/core/commit/e816812f10b9e3a375eef8dffd617d7f08b23c00)), closes [#3819](https://github.com/vuejs/core/issues/3819)\n* **types:** stricter type condition for `EventHandlers` ([#6855](https://github.com/vuejs/core/issues/6855)) ([bad3f3c](https://github.com/vuejs/core/commit/bad3f3ce46aad1f5fec47d1d02aee26af393bcff)), closes [#6899](https://github.com/vuejs/core/issues/6899)\n* **types:** support inferring injected properties in options api ([#6804](https://github.com/vuejs/core/issues/6804)) ([e4de623](https://github.com/vuejs/core/commit/e4de623ea7289665ac8e827d8aa4783de1d6d380)), closes [#3031](https://github.com/vuejs/core/issues/3031) [#5931](https://github.com/vuejs/core/issues/5931)\n* **v-model:** fix trim modifier on events with non-string args ( ([#5770](https://github.com/vuejs/core/issues/5770)) ([018b850](https://github.com/vuejs/core/commit/018b8503994c2dae3c42dd03ea50d062956be970)), closes [#5765](https://github.com/vuejs/core/issues/5765)\n\n\n\n## [3.2.41](https://github.com/vuejs/core/compare/v3.2.40...v3.2.41) (2022-10-14)\n\n\n### Bug Fixes\n\n* **devtools:** avoid memory leak caused by devtools event buffer ([24f4c47](https://github.com/vuejs/core/commit/24f4c479d661698afd967cf428f9439be4578a04)), closes [#6591](https://github.com/vuejs/core/issues/6591)\n* **devtools:** use cleanupBuffer instead of modifying _buffer ([#6812](https://github.com/vuejs/core/issues/6812)) ([35a113e](https://github.com/vuejs/core/commit/35a113eda43a49e921a6eb60d45db81dc847d665))\n* **effectScope:** calling off() of a detached scope should not break currentScope ([a71f9ac](https://github.com/vuejs/core/commit/a71f9ac41af464fdb69220e69c50739dd3a8f365))\n* **runtime-core:** ensure that errors in slot function execution do not affect block tracking ([#5670](https://github.com/vuejs/core/issues/5670)) ([82a73da](https://github.com/vuejs/core/commit/82a73da351bb5d26735f734ae2540a3033c00c9e)), closes [#5657](https://github.com/vuejs/core/issues/5657)\n* **runtime-core:** fix v-for ref reactivity behavior difference between prod and dev ([#6714](https://github.com/vuejs/core/issues/6714)) ([9ae796d](https://github.com/vuejs/core/commit/9ae796d1567f1b0acb08659a2363a54b525a9ee4)), closes [#6697](https://github.com/vuejs/core/issues/6697)\n* **runtime-dom:** fix event timestamp check in iframes ([5ee4053](https://github.com/vuejs/core/commit/5ee40532a63e0b792e0c1eccf3cf68546a4e23e9)), closes [#2513](https://github.com/vuejs/core/issues/2513) [#3933](https://github.com/vuejs/core/issues/3933) [#5474](https://github.com/vuejs/core/issues/5474)\n\n\n\n## [3.2.40](https://github.com/vuejs/core/compare/v3.2.39...v3.2.40) (2022-09-28)\n\n\n### Bug Fixes\n\n* **compat:** list cjs dependencies for compat build ([96cd924](https://github.com/vuejs/core/commit/96cd924e440984a37e4759673f3c16921b69affe)), closes [#6602](https://github.com/vuejs/core/issues/6602)\n* **compiler-dom:** remove v-bind boolean attribute with literal false value when stringifying ([#6635](https://github.com/vuejs/core/issues/6635)) ([6c6fe2c](https://github.com/vuejs/core/commit/6c6fe2c0cd89ce513503b1f85e0ddb696fd81e54)), closes [#6617](https://github.com/vuejs/core/issues/6617)\n* **compiler-sfc:** fix expression check for v-on with object literal value ([#6652](https://github.com/vuejs/core/issues/6652)) ([6958ec1](https://github.com/vuejs/core/commit/6958ec1b37fb4a9244ae222a35fcac032d26ad8a)), closes [#6650](https://github.com/vuejs/core/issues/6650) [#6674](https://github.com/vuejs/core/issues/6674)\n* **compilre-core:** dynamic v-on and static v-on should be merged ([#6747](https://github.com/vuejs/core/issues/6747)) ([f9d43b9](https://github.com/vuejs/core/commit/f9d43b99f83af7fc140938a1d8d2db89666fb4e1)), closes [#6742](https://github.com/vuejs/core/issues/6742)\n* **runtime-core:** avoid hoisted vnodes retaining detached DOM nodes ([fc5bdb3](https://github.com/vuejs/core/commit/fc5bdb36ed429d6c3c956f373206ce75467adaf3)), closes [#6591](https://github.com/vuejs/core/issues/6591)\n* **runtime-core:** Lifecycle hooks should support callbacks shared by reference ([#6687](https://github.com/vuejs/core/issues/6687)) ([c71a08e](https://github.com/vuejs/core/commit/c71a08e6fd44ee06c6b4f61d67727a7b7503605e)), closes [#6686](https://github.com/vuejs/core/issues/6686)\n* **runtime-core:** remove prod-only hoisted clone behavior for manual DOM manipulation compat ([aa70188](https://github.com/vuejs/core/commit/aa70188c41fab1a4139748dd7b7c71532d063f3a)), closes [#6727](https://github.com/vuejs/core/issues/6727) [#6739](https://github.com/vuejs/core/issues/6739)\n* **runtime-core:** unset removed props first in full diff mode ([c0d8db8](https://github.com/vuejs/core/commit/c0d8db81a636f0ad1e725b7c04608d3a211cf163)), closes [#6571](https://github.com/vuejs/core/issues/6571)\n* **runtime-dom:** fix unnecessary warning when setting coerced dom property value ([b1817fe](https://github.com/vuejs/core/commit/b1817fe9eeb66a18f405ada9072149515654a9bd)), closes [#6616](https://github.com/vuejs/core/issues/6616)\n* **ssr:** avoid ast.helpers duplication ([#6664](https://github.com/vuejs/core/issues/6664)) ([57ffc3e](https://github.com/vuejs/core/commit/57ffc3e546395ba048009396a4b82d3f968cca2c))\n* **ssr:** fix dynamic slot regression in ssr ([8963c55](https://github.com/vuejs/core/commit/8963c5508cde3a0c990b2748787ffb582b16f23f)), closes [#6651](https://github.com/vuejs/core/issues/6651)\n* **ssr:** fix hydration mismatch when entire multi-root template is stringified ([9698dd3](https://github.com/vuejs/core/commit/9698dd3cf1dfdb95d4dc4b4f7bd24ff94b4b5d84)), closes [#6637](https://github.com/vuejs/core/issues/6637)\n* **ssr:** fix pre tag windows newline hydration mismatch ([0382019](https://github.com/vuejs/core/commit/03820193a8f768293d665ca2753439fe73aed0fd)), closes [#6410](https://github.com/vuejs/core/issues/6410)\n* **ssr:** respect case when rendering dynamic attrs on svg ([121eb32](https://github.com/vuejs/core/commit/121eb32fb0a21cf9988d788cfad1b4249b15997b)), closes [#6755](https://github.com/vuejs/core/issues/6755)\n\n\n\n## [3.2.39](https://github.com/vuejs/core/compare/v3.2.38...v3.2.39) (2022-09-08)\n\n\n### Bug Fixes\n\n* **runtime-core:** avoid double firing when mounting inside a watcher callback ([6aaf8ef](https://github.com/vuejs/core/commit/6aaf8efefffdb0d4b93f178b2bb36cd3c6bc31b8)), closes [#6614](https://github.com/vuejs/core/issues/6614)\n* **runtime-core:** support extends template for runtime compiler ([#6250](https://github.com/vuejs/core/issues/6250)) ([9875ecd](https://github.com/vuejs/core/commit/9875ecd762155732008e397d450edb0f8c01b05c)), closes [#6249](https://github.com/vuejs/core/issues/6249)\n* **ssr:** reset current instance ([#6184](https://github.com/vuejs/core/issues/6184)) ([6493da5](https://github.com/vuejs/core/commit/6493da5bfa4624267248deb3d31dca2a4fb22aee)), closes [#6110](https://github.com/vuejs/core/issues/6110)\n* **types:** support TypeScript 4.8 ([5381abc](https://github.com/vuejs/core/commit/5381abc0571e58a9be6cf482dc50c8db8300f86c)), closes [#6554](https://github.com/vuejs/core/issues/6554)\n\n\n\n## [3.2.38](https://github.com/vuejs/core/compare/v3.2.37...v3.2.38) (2022-08-30)\n\n\n### Bug Fixes\n\n* **compiler-sfc:** fix template usage check edge case for v-on statements ([769e555](https://github.com/vuejs/core/commit/769e5555f9d9004ce541613341652db859881570))\n* **compiler-sfc:** only add decorators-legacy parser plugin when new decorators plugin is not used ([3ff8369](https://github.com/vuejs/core/commit/3ff83694f523e3fe148d22a469ed742b46603bb4))\n* **compiler-sfc:** rewriteDefault for class with decorators ([#6320](https://github.com/vuejs/core/issues/6320)) ([81a7819](https://github.com/vuejs/core/commit/81a7819535c4382ba7817c817722bac6d41921d8)), closes [#6318](https://github.com/vuejs/core/issues/6318)\n* **custom-element:** fix event listeners with capital letter event names on custom elements ([0739f89](https://github.com/vuejs/core/commit/0739f8909a0e56ae0fa760f233dfb8c113c9bde2))\n* **hmr:** fix HMR for nested non-SFC components ([#4077](https://github.com/vuejs/core/issues/4077)) ([96eb745](https://github.com/vuejs/core/commit/96eb7452548293c343613ab778248a5da9619f45))\n* **reactivity:** fix shallow/readonly edge cases ([a95554d](https://github.com/vuejs/core/commit/a95554d35c65e5bfd0bf9d1c5b908ae789345a6d))\n* **runtime-core:** only set cache for object keys ([#6266](https://github.com/vuejs/core/issues/6266)) ([c3465c1](https://github.com/vuejs/core/commit/c3465c1e889651df925324ed2a10ac2d5f229110))\n* **slots:** ensure different branches of dynamic slots have different keys ([00036bb](https://github.com/vuejs/core/commit/00036bb52c4e641b2be7fa55c39ced9448163b0f)), closes [#6202](https://github.com/vuejs/core/issues/6202)\n* **ssr:** forward helpers provided by CSS `v-bind` ([#6489](https://github.com/vuejs/core/issues/6489)) ([2024d11](https://github.com/vuejs/core/commit/2024d11db03d9c6e49e20b3355f3df0ba04bb834)), closes [#6201](https://github.com/vuejs/core/issues/6201)\n* **types:** add types field for sub package exports ([c1ee6ca](https://github.com/vuejs/core/commit/c1ee6caa82da89b3a9c33e2253c07a681ebb2628))\n* **types:** fix on* props incorrect type for TS 4.7 ([#6216](https://github.com/vuejs/core/issues/6216)) ([8dcb6c7](https://github.com/vuejs/core/commit/8dcb6c7bbdd2905469e2bb11dfff27b58cc784b2)), closes [#6052](https://github.com/vuejs/core/issues/6052)\n* **watch:** flush:pre watchers should not fire if state change causes ([78c199d](https://github.com/vuejs/core/commit/78c199d6dbe8931520b75d8bfe0d49366a06922a)), closes [#2291](https://github.com/vuejs/core/issues/2291)\n\n\n### Features\n\n* **custom-elements:** automatically respect custom elements when compiling in browser ([9f8f07e](https://github.com/vuejs/core/commit/9f8f07ed38b2e003f308875fe3a3e4c0d5477b32))\n\n\n### Performance Improvements\n\n* **ssr:** improve isComment check ([#6078](https://github.com/vuejs/core/issues/6078)) ([25f7a16](https://github.com/vuejs/core/commit/25f7a16a6eccbfa8d857977dcf1f23fb36b830b5))\n\n\n\n## [3.2.37](https://github.com/vuejs/core/compare/v3.2.36...v3.2.37) (2022-06-06)\n\n\n### Bug Fixes\n\n* **compiler-sfc:** improve css v-bind parsing ([e60244b](https://github.com/vuejs/core/commit/e60244bcdf0b386de1560ff7c205ae0870bab355)), closes [#6022](https://github.com/vuejs/core/issues/6022)\n* **runtime-core:** hydrate Static vnode ([#6015](https://github.com/vuejs/core/issues/6015)) ([11e17a1](https://github.com/vuejs/core/commit/11e17a1a29cf3d0b37628241d63ff3e8d8525f95)), closes [#6008](https://github.com/vuejs/core/issues/6008)\n* **sfc:** avoid auto name inference leading to unwanted recursion ([9734b31](https://github.com/vuejs/core/commit/9734b31c312244a2b5c5cf83c75d7b34076a0c4b)), closes [#5965](https://github.com/vuejs/core/issues/5965) [#6027](https://github.com/vuejs/core/issues/6027) [#6029](https://github.com/vuejs/core/issues/6029)\n* **ssr:** ensure app  can be unmounted when created with createSSRApp() ([#5992](https://github.com/vuejs/core/issues/5992)) ([d4d3319](https://github.com/vuejs/core/commit/d4d3319c1be16dc9a046b2c5521096debc205f25)), closes [#5990](https://github.com/vuejs/core/issues/5990)\n* **ssr:** hydration for transition wrapper components with empty slot content ([#5995](https://github.com/vuejs/core/issues/5995)) ([eb22a62](https://github.com/vuejs/core/commit/eb22a62798d845a8756b0a73b68afdd874feda59)), closes [#5991](https://github.com/vuejs/core/issues/5991)\n\n\n\n## [3.2.36](https://github.com/vuejs/core/compare/v3.2.35...v3.2.36) (2022-05-23)\n\n\n### Bug Fixes\n\n* **compat:** fix app-level asset registration affecting other local apps ([#5979](https://github.com/vuejs/core/issues/5979)) ([7fb5732](https://github.com/vuejs/core/commit/7fb57327b9d0e4d9eb675149f167d915fb0d59fa))\n* **compat:** fix globalProperties pollution in v3 mode ([2f07e34](https://github.com/vuejs/core/commit/2f07e3460bf51bc1b083f3d03b3d192e042d2d75)), closes [#5699](https://github.com/vuejs/core/issues/5699)\n* **compiler-core:** fix svg with directives being incorrectly hoisted ([#5919](https://github.com/vuejs/core/issues/5919)) ([7fbc933](https://github.com/vuejs/core/commit/7fbc933f4d80c0259ee24872ba790681cf3cbe76)), closes [#5289](https://github.com/vuejs/core/issues/5289)\n* **sfc/types:** allow use default factory for primitive types in `withDefaults` ([#5939](https://github.com/vuejs/core/issues/5939)) ([b546282](https://github.com/vuejs/core/commit/b5462822d6c0a43866deef2b3437bbe3bbfb3625)), closes [#5938](https://github.com/vuejs/core/issues/5938)\n* **transition:** fix cancel leave regression ([#5974](https://github.com/vuejs/core/issues/5974)) ([dddbd96](https://github.com/vuejs/core/commit/dddbd96dfe69292cee401f72d2703e8fb3708a14)), closes [#5973](https://github.com/vuejs/core/issues/5973)\n\n\n### Performance Improvements\n\n* improve the performance of getNow ([#5944](https://github.com/vuejs/core/issues/5944)) ([3bdc41d](https://github.com/vuejs/core/commit/3bdc41dff305422cb5334a64353c314bce1202a4))\n\n\n\n## [3.2.35](https://github.com/vuejs/core/compare/v3.2.34...v3.2.35) (2022-05-20)\n\n\n### Bug Fixes\n\n* **compiler-sfc:** fix usage detection for types in v-for/v-slot expressions ([583b625](https://github.com/vuejs/core/commit/583b6259870211c32efee0bb4a60b342799d80f7)), closes [#5959](https://github.com/vuejs/core/issues/5959)\n* **types:** fix typescript error when spreading `$props`([#5968](https://github.com/vuejs/core/issues/5968)) ([0c7fd13](https://github.com/vuejs/core/commit/0c7fd13ea628a2f1b72c6f4150c0dba32da4468e))\n* **types:** restore DefineComponent argument order ([8071ef4](https://github.com/vuejs/core/commit/8071ef47b5adcd5fcd9d0d2ea2cefff5c34ce095)), closes [#5416](https://github.com/vuejs/core/issues/5416) [#3796](https://github.com/vuejs/core/issues/3796) [#5967](https://github.com/vuejs/core/issues/5967)\n\n\n\n## [3.2.34](https://github.com/vuejs/core/compare/v3.2.34-beta.1...v3.2.34) (2022-05-19)\n\n\n### Bug Fixes\n\n* **compiler-core:** should generate HYDRATE_EVENTS flag on dynamic component that resolves to element ([415091b](https://github.com/vuejs/core/commit/415091b0ee2de66e622145028f00523f2032ce77)), closes [#5870](https://github.com/vuejs/core/issues/5870)\n* **compiler-sfc:** support `export { default } from '...'` ([#5937](https://github.com/vuejs/core/issues/5937)) ([73e6523](https://github.com/vuejs/core/commit/73e6523134a013f9e369f53f213a214497ac7c40)), closes [#5935](https://github.com/vuejs/core/issues/5935)\n* **compiler-sfc:** type-only defineProps does not recognize Promise (fix [#5941](https://github.com/vuejs/core/issues/5941)) ([#5943](https://github.com/vuejs/core/issues/5943)) ([991d623](https://github.com/vuejs/core/commit/991d62322fa67d50b7ae8b0460f294d6b39f9711))\n* **compiler-ssr:** fix component event handlers inheritance in ssr ([f811dc2](https://github.com/vuejs/core/commit/f811dc2b60ba7efdbb9b1ab330dcbc18c1cc9a75)), closes [#5664](https://github.com/vuejs/core/issues/5664)\n* **compiler-ssr:** fix wrong attrs fallthrough on non-single-root v-if branches ([516bc54](https://github.com/vuejs/core/commit/516bc548fce295f6d564c7fb371c8067ead7cd71)), closes [#5140](https://github.com/vuejs/core/issues/5140)\n* **compiler-ssr:** only inject fallthrough attrs for root transition/keep-alive ([c65b805](https://github.com/vuejs/core/commit/c65b805ef1f9b164fb8aaa7bc679a91248b5891a))\n* **keep-alive:** fix keep-alive rendering when placed in vnode branch ([0841b9b](https://github.com/vuejs/core/commit/0841b9b5243acdaf191099b25e9a145b30189dea)), closes [#4817](https://github.com/vuejs/core/issues/4817)\n* **runtime-core:** adjust force diff of dev root fragments ([cdda49b](https://github.com/vuejs/core/commit/cdda49bbfb1939c9cf812d624992ea7bdae74c78)), closes [#5946](https://github.com/vuejs/core/issues/5946)\n* **ssr/teleport:** support nested teleports in ssr ([595263c](https://github.com/vuejs/core/commit/595263c0e9f5728c3650c6526dbed27cda9ba114)), closes [#5242](https://github.com/vuejs/core/issues/5242)\n* **ssr:** fix hydration error on falsy v-if inside transition/keep-alive ([ee4186e](https://github.com/vuejs/core/commit/ee4186ef9ebbc45827b208f6f5b648dbf4337d1d)), closes [#5352](https://github.com/vuejs/core/issues/5352)\n* **ssr:** fix hydration error when teleport is used as component root ([b60cff0](https://github.com/vuejs/core/commit/b60cff052c880b2965d06007f0ec4d0349ab47c0)), closes [#4293](https://github.com/vuejs/core/issues/4293)\n* **ssr:** fix hydration error when transition contains comment children ([3705b3b](https://github.com/vuejs/core/commit/3705b3b46aa8f3e929014f564f8afa4a663e6375)), closes [#5351](https://github.com/vuejs/core/issues/5351)\n* **ssr:** fix hydration for slot with empty text node ([939209c](https://github.com/vuejs/core/commit/939209c6b554aed6634d9cf2ca10a2aa46ba7673)), closes [#5728](https://github.com/vuejs/core/issues/5728)\n* **ssr:** fix hydration mismatch caused by multi-line comments inside slot ([e1bc268](https://github.com/vuejs/core/commit/e1bc2681ef64aed7975ad38950a478ae53c1abad)), closes [#5355](https://github.com/vuejs/core/issues/5355)\n* **ssr:** inherit scope id on functional component during ssr ([847d7f7](https://github.com/vuejs/core/commit/847d7f782bb6074c6b31378e07d94cb41ad30bd2)), closes [#5817](https://github.com/vuejs/core/issues/5817)\n* **ssr:** render fallthrough attributes for transition-group with tag ([aed10c5](https://github.com/vuejs/core/commit/aed10c507279900f8afc4861dc01ca4f2b95acb8)), closes [#5141](https://github.com/vuejs/core/issues/5141)\n* **ssr:** support client-compiled  v-model with dynamic type during ssr ([#5787](https://github.com/vuejs/core/issues/5787)) ([c03459b](https://github.com/vuejs/core/commit/c03459b9b6d3c18450235bc4074a603677996320)), closes [#5786](https://github.com/vuejs/core/issues/5786)\n* **types:** export ComponentProvideOptions ([#5947](https://github.com/vuejs/core/issues/5947)) ([3e2850f](https://github.com/vuejs/core/commit/3e2850fa6c628284b4a1ab5deba3b11f1d2f66b6))\n* **types:** fix `defineComponent` inference to `Component` ([#5949](https://github.com/vuejs/core/issues/5949)) ([7c8f457](https://github.com/vuejs/core/commit/7c8f4578e9e7178e326cf8e343f7a8b4143ba63b))\n\n\n\n## [3.2.34-beta.1](https://github.com/vuejs/core/compare/v3.2.33...v3.2.34-beta.1) (2022-05-17)\n\n\n### Bug Fixes\n\n* **compiler-core:** normalize v-bind:style with array literal value ([0f00cf4](https://github.com/vuejs/core/commit/0f00cf43cf5eaeeee7f12d523a5f4936f7dc0a84)), closes [#5106](https://github.com/vuejs/core/issues/5106)\n* **compiler-core:** template v-if should never be treated as dev root fragment ([51f3d38](https://github.com/vuejs/core/commit/51f3d386de7f5fcec6eb4c1c223ba824be036648)), closes [#5189](https://github.com/vuejs/core/issues/5189)\n* **compiler-dom:** properly stringify v-html/v-text with constant value ([6283b2e](https://github.com/vuejs/core/commit/6283b2ec413b78fe88775d249d3598cdce977b7a)), closes [#5439](https://github.com/vuejs/core/issues/5439) [#5445](https://github.com/vuejs/core/issues/5445)\n* **compiler-sfc:** `<script>` after `<script setup>` the script content not end with `\\\\n` ([3b7b107](https://github.com/vuejs/core/commit/3b7b107120c6dba70b068312afd594c3575ea9eb))\n* **compiler-sfc:** add test for [#5808](https://github.com/vuejs/core/issues/5808) ([a0290fe](https://github.com/vuejs/core/commit/a0290fe781a0ab2e90239d615d18fdb7ee37cdfe))\n* **compiler-sfc:** async transformer doesn't correctly detect need for semicolon in block [#5808](https://github.com/vuejs/core/issues/5808) ([6c3b681](https://github.com/vuejs/core/commit/6c3b681d235bc70293827c535572f90be1ab6c68))\n* **compiler-sfc:** automatically infer component name from filename when using script setup ([#4997](https://github.com/vuejs/core/issues/4997)) ([1693924](https://github.com/vuejs/core/commit/16939241b0f64cefea254b024a9b5a25caea93d9)), closes [#4993](https://github.com/vuejs/core/issues/4993)\n* **compiler-sfc:** defineProps return binding or rest binding should be considered reactive ([4101441](https://github.com/vuejs/core/commit/410144149fbaaecad2b2d36a9cfe965ab7b2b6e6))\n* **compiler-sfc:** ensure consistent behavior of export default render with script setup ([b7025d2](https://github.com/vuejs/core/commit/b7025d24f1c33023d020d60292319740852d1810)), closes [#4980](https://github.com/vuejs/core/issues/4980)\n* **compiler-sfc:** fix defineEmits() scope reference check error message ([#5404](https://github.com/vuejs/core/issues/5404)) ([f2c48f5](https://github.com/vuejs/core/commit/f2c48f535250d01133a5e49c0bf2c26a46b6d935))\n* **compiler-sfc:** fix object default values for reactive props destructure ([7dfe146](https://github.com/vuejs/core/commit/7dfe146096487a98ba1733598c44407bc89a1b9f))\n* **compiler-sfc:** fix skipped srcset transform when using base option ([41d255b](https://github.com/vuejs/core/commit/41d255ba5ddd40f1a1dd2dd6add01f38e20d6325)), closes [#4835](https://github.com/vuejs/core/issues/4835) [#4819](https://github.com/vuejs/core/issues/4819) [#4834](https://github.com/vuejs/core/issues/4834) [#4835](https://github.com/vuejs/core/issues/4835)\n* **compiler-sfc:** fix template usage check false positives on types ([ccf9256](https://github.com/vuejs/core/commit/ccf92564d339cdee3947aecfba2e861c88864883)), closes [#5414](https://github.com/vuejs/core/issues/5414)\n* **compiler-sfc:** fix treeshaking of namespace import when used in template ([8a123ac](https://github.com/vuejs/core/commit/8a123ac34fd30fc36ac9e0c252dd345d6d7c7f50)), closes [#5209](https://github.com/vuejs/core/issues/5209)\n* **compiler-sfc:** remove the jsx from the babelParserPlugins when not match the case of adding jsx ([#5846](https://github.com/vuejs/core/issues/5846)) ([7d7a241](https://github.com/vuejs/core/commit/7d7a2410e58d3ae59ca3fcf619f332699209fc96)), closes [#5845](https://github.com/vuejs/core/issues/5845)\n* **keep-alive:** fix unmounting late-included components ([da49c86](https://github.com/vuejs/core/commit/da49c863a21fb9d9de4a1b816dcc4faff8046fdb)), closes [#3648](https://github.com/vuejs/core/issues/3648) [#3650](https://github.com/vuejs/core/issues/3650)\n* **keep-alive:** invoke initial activated hook for async components ([20ed16f](https://github.com/vuejs/core/commit/20ed16f68c632a271d4e8cb09087c7ed4e936637)), closes [#5459](https://github.com/vuejs/core/issues/5459) [#5095](https://github.com/vuejs/core/issues/5095) [#5651](https://github.com/vuejs/core/issues/5651)\n* **reactivity-transform:** fix props access codegen for non-identifier prop names ([#5436](https://github.com/vuejs/core/issues/5436)) ([242914d](https://github.com/vuejs/core/commit/242914d938fccad1c09a52a7ed09f15ac509cf6b)), closes [#5425](https://github.com/vuejs/core/issues/5425)\n* **reactivity:** ensure computed is invalidated before other effects ([82bdf86](https://github.com/vuejs/core/commit/82bdf8625475e81c44f0d4db4061b882d2fe7612)), closes [#5720](https://github.com/vuejs/core/issues/5720)\n* **reactivity:** ios10.x compatibility ([#4900](https://github.com/vuejs/core/issues/4900)) ([b87dc06](https://github.com/vuejs/core/commit/b87dc061930e62c78b4cc9a79f385e5880cdf8ae))\n* **runtime-core:** clone root vnode before inheriting directives ([d36ca4d](https://github.com/vuejs/core/commit/d36ca4d80e297056f6c78cd7e3bc2004e0b58660))\n* **runtime-core:** ensure consistent behavior between dev/prod on invalid v-for range ([67099fe](https://github.com/vuejs/core/commit/67099fe20299a51f9974f0e2f9ef19ca05efe92b)), closes [#5867](https://github.com/vuejs/core/issues/5867)\n* **runtime-core:** ensure consistent identity of $forceUpdate and $nextTick instance methods ([d52907f](https://github.com/vuejs/core/commit/d52907f4ebc9bcfd7b3141fbebecd4c5b19aa80f)), closes [#5556](https://github.com/vuejs/core/issues/5556)\n* **runtime-core:** ensure raw slot function is only normalized once ([#5358](https://github.com/vuejs/core/issues/5358)) ([e4dffe9](https://github.com/vuejs/core/commit/e4dffe900a7475c9b4c22c06283b5635e5c2de37)), closes [#5343](https://github.com/vuejs/core/issues/5343)\n* **runtime-core:** fix activated hook when using async component with KeepAlive ([#5459](https://github.com/vuejs/core/issues/5459)) ([f1d1cdb](https://github.com/vuejs/core/commit/f1d1cdbb699e27ac6a0d241209f7e8f8d9ebf2c7)), closes [#5095](https://github.com/vuejs/core/issues/5095) [#5651](https://github.com/vuejs/core/issues/5651)\n* **runtime-core:** fix directive inheritance on dev root fragment ([2bab639](https://github.com/vuejs/core/commit/2bab63968355995a4026cf5cd1ccad7c79e8d89c)), closes [#5523](https://github.com/vuejs/core/issues/5523)\n* **runtime-core:** fix missed updates when passing vnode to <component :is> ([ba17792](https://github.com/vuejs/core/commit/ba17792b7248552ea01a1ca6eca7d49b47d827f0)), closes [#4903](https://github.com/vuejs/core/issues/4903)\n* **runtime-core:** handle NaN identity check in v-memo ([#5852](https://github.com/vuejs/core/issues/5852)) ([a388129](https://github.com/vuejs/core/commit/a3881299e98de6217f05bbd42ac509e8cc8be3d9)), closes [#5853](https://github.com/vuejs/core/issues/5853)\n* **runtime-core:** transition hooks can be arrays of functions ([#5177](https://github.com/vuejs/core/issues/5177)) ([fec12d7](https://github.com/vuejs/core/commit/fec12d7dccc573c016ee2d8e1fa2b67f134c2786))\n* **runtime-dom:** \"el._assign is not a function\" in compat mode ([#4121](https://github.com/vuejs/core/issues/4121)) ([e58277f](https://github.com/vuejs/core/commit/e58277f6eaeaec84cf05b34126bec01b619a1b90))\n* **sfc-playground:** default selected app ([#5370](https://github.com/vuejs/core/issues/5370)) ([04fff05](https://github.com/vuejs/core/commit/04fff05f0043adb753928e806f9d8fb604701a38))\n* **shared:** improve isDate check ([#5803](https://github.com/vuejs/core/issues/5803)) ([eef1447](https://github.com/vuejs/core/commit/eef14471b228e8f3d3c921a0451d268f81a0a74d))\n* **shared:** missed Symbol judge in looseEqual ([#3553](https://github.com/vuejs/core/issues/3553)) ([0aeb4bc](https://github.com/vuejs/core/commit/0aeb4bc9bf68c0006b496142bb5aeb3f06689b7c))\n* **ssr/sfc-css-vars:** fix v-bind css vars codegen for SSR ([efea4a8](https://github.com/vuejs/core/commit/efea4a8b5784f4660836b124d16dc29f7fea41e4)), closes [#5443](https://github.com/vuejs/core/issues/5443) [#5444](https://github.com/vuejs/core/issues/5444)\n* **ssr:** don't warn for missing teleport target if disabled ([#5135](https://github.com/vuejs/core/issues/5135)) ([da10dd7](https://github.com/vuejs/core/commit/da10dd7de91123666152d058f3c18da3e9e7f22a))\n* **ssr:** fix hydration error for slot outlet inside transition ([9309b04](https://github.com/vuejs/core/commit/9309b044bd4f9d0a34e0d702ed4690a529443a41)), closes [#3989](https://github.com/vuejs/core/issues/3989)\n* **ssr:** fix ssr render output for fragment in slots ([70c2d5b](https://github.com/vuejs/core/commit/70c2d5bbc066585febd12536a6ab39c4384b277b)), closes [#5859](https://github.com/vuejs/core/issues/5859)\n* **ssr:** implement empty read() on node stream ([c355c4b](https://github.com/vuejs/core/commit/c355c4b78451708b04e17a7c50680dee507f0c40)), closes [#3846](https://github.com/vuejs/core/issues/3846) [#3867](https://github.com/vuejs/core/issues/3867)\n* **ssr:** render teleport inside async component ([#5187](https://github.com/vuejs/core/issues/5187)) ([4d7803e](https://github.com/vuejs/core/commit/4d7803ed28fb67d45a83d3500f5407754e65bf64))\n* **ssr:** resolve teleports for stream render APIs ([77fef97](https://github.com/vuejs/core/commit/77fef9734496abe1e842d8e4086c497656d1fab2))\n* **ssr:** should de-optimize on vnode with PatchFlags.BAIL ([#4818](https://github.com/vuejs/core/issues/4818)) ([cd659fc](https://github.com/vuejs/core/commit/cd659fc86f74741987bacc351f0d94ef3b80a1ca)), closes [#4679](https://github.com/vuejs/core/issues/4679) [#5771](https://github.com/vuejs/core/issues/5771)\n* **ssr:** should not hoist transformed asset urls in ssr compile ([57bb37b](https://github.com/vuejs/core/commit/57bb37bd64cc6b2aa3099d91585441db6d43e2a2)), closes [#3874](https://github.com/vuejs/core/issues/3874)\n* **transition/v-show:** ensure transition is in persisted mode when used with v-show ([425310e](https://github.com/vuejs/core/commit/425310e8b614ad91660dd93d4e7905fbe572ef31)), closes [#4845](https://github.com/vuejs/core/issues/4845) [#4852](https://github.com/vuejs/core/issues/4852)\n* **transition:** handle edge case of cancel leave before next frame ([59cf295](https://github.com/vuejs/core/commit/59cf2958e7bae5f1e13953373fcdbb4ad988be6c)), closes [#4462](https://github.com/vuejs/core/issues/4462)\n* **types:** add `Set<any>` to checkbox binding type for v-model ([#5713](https://github.com/vuejs/core/issues/5713)) ([e5a9089](https://github.com/vuejs/core/commit/e5a90893a6a25a40464cc9d5484093ec531e8b78))\n* **types:** allow css variables in style binding  ([#5542](https://github.com/vuejs/core/issues/5542)) ([9def7aa](https://github.com/vuejs/core/commit/9def7aa50827b12fdfbef28e5db6f373d5cba279))\n* **types:** allow indeterminate for checkbox ([#3473](https://github.com/vuejs/core/issues/3473)) ([d4fcfdd](https://github.com/vuejs/core/commit/d4fcfddec6170cc1528a285fc8e0b3f3c5590311))\n* **types:** keep the original type when unwrapping `markRaw` ([#3791](https://github.com/vuejs/core/issues/3791)) ([32e53bf](https://github.com/vuejs/core/commit/32e53bfd478af895dd090ea6c8766fa043e179e4))\n* **types:** preserve and expose original options on defineComponent return type ([#5416](https://github.com/vuejs/core/issues/5416)) ([98b821d](https://github.com/vuejs/core/commit/98b821d94a0a0fb4d7701809da6bec331a47e6e5)), closes [#3796](https://github.com/vuejs/core/issues/3796)\n* **v-model:** exclude range from lazy guard logic ([8c51c65](https://github.com/vuejs/core/commit/8c51c6514f99b4c70183f4c1a0eaabd482f88d5b)), closes [#5875](https://github.com/vuejs/core/issues/5875)\n* **v-model:** fix case where .trim and .number modifiers are used together ([#5842](https://github.com/vuejs/core/issues/5842)) ([71066b5](https://github.com/vuejs/core/commit/71066b5afed7d3707b8ec9a6313dbdbd1adad45e)), closes [#5839](https://github.com/vuejs/core/issues/5839)\n* **watch:** fix flush: pre watchers triggered synchronously in setup ([74d2a76](https://github.com/vuejs/core/commit/74d2a76af6e830af5abb8aac8484dc1b3e90a510)), closes [#5721](https://github.com/vuejs/core/issues/5721)\n* **watch:** fix watching multiple sources containing shallowRef ([#5381](https://github.com/vuejs/core/issues/5381)) ([220f255](https://github.com/vuejs/core/commit/220f255fe94d5f1d2ccf3af3a469e9328c916167)), closes [#5371](https://github.com/vuejs/core/issues/5371)\n\n\n### Features\n\n* **types:** avoid props JSDocs loss by `default` option ([#5871](https://github.com/vuejs/core/issues/5871)) ([c901dca](https://github.com/vuejs/core/commit/c901dca5add2c32554403e5896247fdb8aa7cf7d))\n\n\n\n## [3.2.33](https://github.com/vuejs/core/compare/v3.2.32...v3.2.33) (2022-04-14)\n\n\n### Bug Fixes\n\n* **compat:** copy additional properties for functions bound via globalProperties ([#4873](https://github.com/vuejs/core/issues/4873)) ([1612971](https://github.com/vuejs/core/commit/16129714714e19c5c6bfbd05c439ff68bcac00b9)), closes [#4403](https://github.com/vuejs/core/issues/4403)\n* **compiler-sfc:** handle type modifier in import specifiers ([#5498](https://github.com/vuejs/core/issues/5498)) ([8e29ef6](https://github.com/vuejs/core/commit/8e29ef6019d1b9d9c8f67b4ebba0223b8e0f914c))\n* **custom-elements:** work with async component + slots ([#4657](https://github.com/vuejs/core/issues/4657)) ([f4d2c9f](https://github.com/vuejs/core/commit/f4d2c9fc6afea827a081c1eeab78ce5c0cc620ca)), closes [#4639](https://github.com/vuejs/core/issues/4639)\n* **reactivity-transform:** should not rewrite catch param ([#5711](https://github.com/vuejs/core/issues/5711)) ([1f14f19](https://github.com/vuejs/core/commit/1f14f194396bf9296a1046d3f680d6d318cd0e40)), closes [#5709](https://github.com/vuejs/core/issues/5709)\n* **reactivity:** fix ref tracking of self-stopping effects ([154233a](https://github.com/vuejs/core/commit/154233abdb19b8330bbc1ff0d3e007f2558cd81c)), closes [#5707](https://github.com/vuejs/core/issues/5707)\n* **runtime-core:** ensure custom events are not emitted anymore after unmount. ([#5679](https://github.com/vuejs/core/issues/5679)) ([71c9536](https://github.com/vuejs/core/commit/71c953662528c4f0be68e7b412585c6809794528)), closes [#5674](https://github.com/vuejs/core/issues/5674)\n* **runtime-core:** fix use of non-existent-in-prod internal property in defineProperty trap ([f641c4b](https://github.com/vuejs/core/commit/f641c4b2289dfdbbbea87538e36fa35f2a115ddc)), closes [#5710](https://github.com/vuejs/core/issues/5710)\n* **runtime-dom:** catch more cases of DOM property setting error ([#5552](https://github.com/vuejs/core/issues/5552)) ([fa1d14c](https://github.com/vuejs/core/commit/fa1d14c2c82a70743ed837ee91c8966373aa8142)), closes [#5545](https://github.com/vuejs/core/issues/5545)\n* **runtime-dom:** patch translate as an attr ([#5485](https://github.com/vuejs/core/issues/5485)) ([2c09969](https://github.com/vuejs/core/commit/2c09969b1316b88f9a60406ce7c49cf1110bc400)), closes [#5462](https://github.com/vuejs/core/issues/5462)\n* **runtime-dom:** properly handle style properties with undefined values ([#5348](https://github.com/vuejs/core/issues/5348)) ([85af139](https://github.com/vuejs/core/commit/85af1398637ee91c6ebabb73bf42250320311e19)), closes [#5322](https://github.com/vuejs/core/issues/5322)\n* **ssr:** avoid rendering reserved internal keys in output ([#5564](https://github.com/vuejs/core/issues/5564)) ([cc238cd](https://github.com/vuejs/core/commit/cc238cdb8e9e90b700c22dfb0530d395e60c9836)), closes [#5563](https://github.com/vuejs/core/issues/5563)\n* **transition:** fix broken leave transition on dev root fragment ([#5268](https://github.com/vuejs/core/issues/5268)) ([767d212](https://github.com/vuejs/core/commit/767d212d20a9a488d183610d048ba131bbfd067e))\n* **transition:** handle transition for v-if branches with comment ([62eba63](https://github.com/vuejs/core/commit/62eba63172414ae0aa895d4b1927c7889c398f2f)), closes [#5675](https://github.com/vuejs/core/issues/5675)\n\n\n\n## [3.2.32](https://github.com/vuejs/core/compare/v3.2.31...v3.2.32) (2022-04-12)\n\n\n### Bug Fixes\n\n* **devtools:** perf: use high-resolution time ([1070f12](https://github.com/vuejs/core/commit/1070f127a78bfe7da6fe550cc272ef11a1f434a0))\n* **reactivity:** fix currentScope loss when running detached effect scope ([#5575](https://github.com/vuejs/core/issues/5575)) ([0a301d4](https://github.com/vuejs/core/commit/0a301d4dabd667526cbcd96e88b50741b519a812))\n* **runtime-core/template-ref:** named ref in v-for regression fix ([#5118](https://github.com/vuejs/core/issues/5118)) ([cee1eaf](https://github.com/vuejs/core/commit/cee1eafb4d2d5df901c9536ac59c321be72598b5)), closes [#5116](https://github.com/vuejs/core/issues/5116) [#5447](https://github.com/vuejs/core/issues/5447) [#5525](https://github.com/vuejs/core/issues/5525)\n* **runtime-core:** allow spying on proxy methods regression ([#5417](https://github.com/vuejs/core/issues/5417)) ([1574edd](https://github.com/vuejs/core/commit/1574edd490bd5cc0a213bc9f48ff41a1dc43ab22)), closes [#5415](https://github.com/vuejs/core/issues/5415) [#4216](https://github.com/vuejs/core/issues/4216)\n* **runtime-core:** Avoid mutating original options object in createApp ([#4840](https://github.com/vuejs/core/issues/4840)) ([d121a9b](https://github.com/vuejs/core/commit/d121a9bc7e7af59adb2d2803954cfeee95b35270)), closes [#4398](https://github.com/vuejs/core/issues/4398)\n* **runtime-core:** ensure custom directive instance properly exposes properties on closed instances. ([#5022](https://github.com/vuejs/core/issues/5022)) ([f44087e](https://github.com/vuejs/core/commit/f44087e171282cb77f1e23d86516a527e4c5804b)), closes [#5018](https://github.com/vuejs/core/issues/5018)\n* **runtime-core:** fix event listener as dynamicProp is added erroneously to props ([#5517](https://github.com/vuejs/core/issues/5517)) ([8eceabd](https://github.com/vuejs/core/commit/8eceabd14ebab2ba6523f920134b02fdf21e0a1c)), closes [#5520](https://github.com/vuejs/core/issues/5520)\n* **transition:** ensure flattened transition group children inherit parent keys ([4311ddd](https://github.com/vuejs/core/commit/4311dddfa72b405b20f469f8f219ec3027972f55)), closes [#4718](https://github.com/vuejs/core/issues/4718) [#5360](https://github.com/vuejs/core/issues/5360) [#5392](https://github.com/vuejs/core/issues/5392)\n\n\n\n## [3.2.31](https://github.com/vuejs/core/compare/v3.2.30...v3.2.31) (2022-02-12)\n\n\n### Bug Fixes\n\n* **compiler-ssr:** no need to inject resolveDirective calls for setup custom directives ([436c500](https://github.com/vuejs/core/commit/436c500d2c418930652fededc4882540dcd0c987))\n* **runtime-core:** allow spying on proxy methods ([#4216](https://github.com/vuejs/core/issues/4216)) ([8457d8b](https://github.com/vuejs/core/commit/8457d8b980674b09547edb2dae28091306fe6aa8))\n* **ssr:** always hydrate children for HMR ([#5406](https://github.com/vuejs/core/issues/5406)) ([0342fae](https://github.com/vuejs/core/commit/0342fae8ad0e71866e9b9725a1f9c471db775c76)), closes [#5405](https://github.com/vuejs/core/issues/5405)\n\n\n\n## [3.2.30](https://github.com/vuejs/core/compare/v3.2.29...v3.2.30) (2022-02-07)\n\n\n### Features\n\n* **ssr:** support custom directive getSSRProps in optimized compilation ([60cf175](https://github.com/vuejs/core/commit/60cf175d88236db2c2a4a02900c92e26ceea0073)), closes [#5304](https://github.com/vuejs/core/issues/5304)\n\n\n### Performance Improvements\n\n* **reactivity:** optimize effect/effectScope active state tracking ([2993a24](https://github.com/vuejs/core/commit/2993a246181df12e367b7abdfce0954244e8f7ec))\n\n\n\n## [3.2.29](https://github.com/vuejs/vue-next/compare/v3.2.28...v3.2.29) (2022-01-23)\n\n\n### Bug Fixes\n\n* **compiler-sfc:** fix css v-bind inside other css functions ([16fa18d](https://github.com/vuejs/vue-next/commit/16fa18da6dbbc52c89f9ea729816e1e70ab0d388)), closes [#5302](https://github.com/vuejs/vue-next/issues/5302) [#5306](https://github.com/vuejs/vue-next/issues/5306)\n* **reactivity:** ensure readonly refs can be replaced with new refs in reactive objects ([#5310](https://github.com/vuejs/vue-next/issues/5310)) ([4be1037](https://github.com/vuejs/vue-next/commit/4be1037f31e169d667059c44364fc3e43803accb)), closes [#5307](https://github.com/vuejs/vue-next/issues/5307)\n* **runtime-dom:** fix static content re-insertion ([9aa5dfd](https://github.com/vuejs/vue-next/commit/9aa5dfd4bb8efac0041e33ef5fdbebab59cc6516)), closes [#5308](https://github.com/vuejs/vue-next/issues/5308)\n\n\n\n## <small>3.2.28 (2022-01-21)</small>\n\n* build: fix build script ([3d80b15](https://github.com/vuejs/vue-next/commit/3d80b15))\n* fix(compat): convertLegacyVModelProps should merge model option in mixins (#5251) ([72130ac](https://github.com/vuejs/vue-next/commit/72130ac)), closes [#5251](https://github.com/vuejs/vue-next/issues/5251)\n* fix(compat): ensure fallthrough *Native events are not dropped during props update (#5228) ([97f6bd9](https://github.com/vuejs/vue-next/commit/97f6bd9)), closes [#5228](https://github.com/vuejs/vue-next/issues/5228)\n* fix(compat): simulate Vue 2.6.14 version in compat build (#5293) ([d0b9708](https://github.com/vuejs/vue-next/commit/d0b9708)), closes [#5293](https://github.com/vuejs/vue-next/issues/5293)\n* fix(compiler-core): handle v-memo in template v-for (#5291) ([9f55e6f](https://github.com/vuejs/vue-next/commit/9f55e6f)), closes [#5291](https://github.com/vuejs/vue-next/issues/5291) [#5288](https://github.com/vuejs/vue-next/issues/5288)\n* fix(compiler-sfc): support complex expression in CSS v-bind() (#5114) ([95d49bf](https://github.com/vuejs/vue-next/commit/95d49bf)), closes [#5114](https://github.com/vuejs/vue-next/issues/5114) [#5109](https://github.com/vuejs/vue-next/issues/5109)\n* fix(compiler-sfc/reactivity-transform): fix edge case where normal script has ref macros but script  ([4768f26](https://github.com/vuejs/vue-next/commit/4768f26))\n* fix(reactivity-transform): apply transform for labelled variable declarations ([a05b000](https://github.com/vuejs/vue-next/commit/a05b000)), closes [/github.com/vuejs/core/issues/5298#issuecomment-1017970061](https://github.com//github.com/vuejs/core/issues/5298/issues/issuecomment-1017970061)\n* fix(reactivity-transform): apply transform on exported variable declarations ([a81a992](https://github.com/vuejs/vue-next/commit/a81a992)), closes [#5298](https://github.com/vuejs/vue-next/issues/5298)\n* fix(reactivity): differentiate shallow/deep proxies of same target when nested in reactive ([9c304bf](https://github.com/vuejs/vue-next/commit/9c304bf)), closes [#5271](https://github.com/vuejs/vue-next/issues/5271)\n* fix(reactivity): mutating a readonly ref nested in a reactive object should fail. (#5048) ([171f5e9](https://github.com/vuejs/vue-next/commit/171f5e9)), closes [#5048](https://github.com/vuejs/vue-next/issues/5048) [#5042](https://github.com/vuejs/vue-next/issues/5042)\n* fix(runtime-core): ensure mergeProps skips undefined event handlers (#5299) ([c35ec47](https://github.com/vuejs/vue-next/commit/c35ec47)), closes [#5299](https://github.com/vuejs/vue-next/issues/5299) [#5296](https://github.com/vuejs/vue-next/issues/5296)\n* fix(ssr): only cache computed getters during render phase ([2f91872](https://github.com/vuejs/vue-next/commit/2f91872)), closes [#5300](https://github.com/vuejs/vue-next/issues/5300)\n* fix(types): calling readonly() with ref() should return Readonly<Ref<T>> (#5212) ([c64907d](https://github.com/vuejs/vue-next/commit/c64907d)), closes [#5212](https://github.com/vuejs/vue-next/issues/5212)\n* refactor: includes instead of indexOf (#5117) ([63210fe](https://github.com/vuejs/vue-next/commit/63210fe)), closes [#5117](https://github.com/vuejs/vue-next/issues/5117)\n* chore: bump marked ([0c06c74](https://github.com/vuejs/vue-next/commit/0c06c74))\n* chore: comment dom tag config usage [ci skip] ([b2bac9f](https://github.com/vuejs/vue-next/commit/b2bac9f))\n* chore: fix typo (#5261) [ci skip] ([e603fd2](https://github.com/vuejs/vue-next/commit/e603fd2)), closes [#5261](https://github.com/vuejs/vue-next/issues/5261)\n* chore: fix typo (#5282) [ci skip] ([e802275](https://github.com/vuejs/vue-next/commit/e802275)), closes [#5282](https://github.com/vuejs/vue-next/issues/5282)\n* chore: type improvements (#5264) ([92e04a6](https://github.com/vuejs/vue-next/commit/92e04a6)), closes [#5264](https://github.com/vuejs/vue-next/issues/5264)\n* chore: update repo references ([ae4b078](https://github.com/vuejs/vue-next/commit/ae4b078))\n* perf(reactivity): optimize effect run condition ([25bc654](https://github.com/vuejs/vue-next/commit/25bc654))\n* feat(reactivity): add isShallow api ([9fda941](https://github.com/vuejs/vue-next/commit/9fda941))\n* docs(contributing): missing structure info for compiler-sfc (#3559) [ci skip] ([8cbfe09](https://github.com/vuejs/vue-next/commit/8cbfe09)), closes [#3559](https://github.com/vuejs/vue-next/issues/3559)\n\n\n\n## [3.2.27](https://github.com/vuejs/core/compare/v3.2.26...v3.2.27) (2022-01-16)\n\n\n### Bug Fixes\n\n* **KeepAlive:** remove cached VNode properly ([#5260](https://github.com/vuejs/core/issues/5260)) ([2e3e183](https://github.com/vuejs/core/commit/2e3e183b4f19c9e25865e35438653cbc9bf01afc)), closes [#5258](https://github.com/vuejs/core/issues/5258)\n* **reactivity-transform:** should not rewrite for...in / for...of scope variables ([7007ffb](https://github.com/vuejs/core/commit/7007ffb2c796d6d56b9c8e278c54dc1cefd7b58f))\n* **sfc-playground:** hide title to avoid overlap ([#5099](https://github.com/vuejs/core/issues/5099)) ([44b9527](https://github.com/vuejs/core/commit/44b95276f5c086e1d88fa3c686a5f39eb5bb7821))\n* **ssr:** make computed inactive during ssr, fix memory leak ([f4f0966](https://github.com/vuejs/core/commit/f4f0966b33863ac0fca6a20cf9e8ddfbb311ae87)), closes [#5208](https://github.com/vuejs/core/issues/5208)\n* **ssr:** remove missing ssr directive transform error ([55cc4af](https://github.com/vuejs/core/commit/55cc4af25e6f4924b267620bd965e496f260d41a))\n* **types/tsx:** allow ref_for type on tsx elements ([78df8c7](https://github.com/vuejs/core/commit/78df8c78c4539d2408278d1a11612b6bbc47d22f))\n* **types:** fix shallowReadonly type ([92f11d6](https://github.com/vuejs/core/commit/92f11d6740929f5b591740e30ae5fba50940ec82))\n* **types:** handle ToRef<any> ([5ac7030](https://github.com/vuejs/core/commit/5ac703055fa83cb1e8a173bbd6a4d6c33707a3c3)), closes [#5188](https://github.com/vuejs/core/issues/5188)\n* **types:** KeepAlive match pattern should allow mixed array ([3007d5b](https://github.com/vuejs/core/commit/3007d5b4cafed1da445bc498f771bd2c79eda6fc))\n\n\n### Features\n\n* **types:** simplify `ExtractPropTypes` to avoid props JSDocs being removed ([#5166](https://github.com/vuejs/core/issues/5166)) ([a570b38](https://github.com/vuejs/core/commit/a570b38741a7dc259772c5ccce7ea8a1638eb0bd))\n\n\n### Performance Improvements\n\n* improve memory usage for static vnodes ([ed9eb62](https://github.com/vuejs/core/commit/ed9eb62e5992bd575d999c4197330d8bad622cfb))\n\n\n\n## [3.2.26](https://github.com/vuejs/core/compare/v3.2.25...v3.2.26) (2021-12-12)\n\n\n\n## [3.2.25](https://github.com/vuejs/core/compare/v3.2.24...v3.2.25) (2021-12-12)\n\n\n### Bug Fixes\n\n* **compiler-sfc:** generate valid TS in script and script setup co-usage with TS ([7e4f0a8](https://github.com/vuejs/core/commit/7e4f0a869498e7dce601e7c150f402045ea2e79b)), closes [#5094](https://github.com/vuejs/core/issues/5094)\n* **compiler:** force block for custom dirs and inline beforeUpdate hooks ([1c9a481](https://github.com/vuejs/core/commit/1c9a4810fcdd2b6c1c6c3be077aebbecbfcbcf1e))\n* **runtime-core:** disallow recurse in vnode/directive beforeUpdate hooks ([a1167c5](https://github.com/vuejs/core/commit/a1167c57e5514be57505f4bce8d163aa1f92cf14))\n\n\n### Features\n\n* **compiler-core:** support aliasing vue: prefixed events to inline vnode hooks ([4b0ca87](https://github.com/vuejs/core/commit/4b0ca8709a7e2652f4b02665f378d47ba4dbe969))\n* **experimental:** allow const for ref sugar declarations ([9823bd9](https://github.com/vuejs/core/commit/9823bd95d11f22f0ae53f5e0b705a21b6e6e8859))\n* **reactivity-transform/types:** restructure macro types + export types for all shorthand methods ([db729ce](https://github.com/vuejs/core/commit/db729ce99eb13cd18dad600055239c63edd9cfb8))\n* **reactivity-transform:** $$() escape for destructured prop bindings ([198ca14](https://github.com/vuejs/core/commit/198ca14f192f9eb80028153f3d36600e636de3f0))\n* **reactivity-transform:** rename @vue/ref-transform to @vue/reactivity-transform ([d70fd8d](https://github.com/vuejs/core/commit/d70fd8d36b23c987f2ebe3280da785f4d2e7d2ef))\n* **reactivity-transform:** support $-shorthands for all ref-creating APIs ([179fc05](https://github.com/vuejs/core/commit/179fc05a8406eac525c8450153b42fcb5af7d6bb))\n* **reactivity-transform:** support optionally importing macros ([fbd0fe9](https://github.com/vuejs/core/commit/fbd0fe97595f759e12e445c713b732775589fabf))\n* **reactivity-transform:** use toRef() for $() destructure codegen ([93ba6b9](https://github.com/vuejs/core/commit/93ba6b974e4a2ff4ba004fef47ef69cfe980c654))\n* **reactivity:** support default value in toRef() ([2db9c90](https://github.com/vuejs/core/commit/2db9c909c2cf3845f57b2c930c05cd6c17abe3b0))\n* **sfc-playground:** add github link ([#5067](https://github.com/vuejs/core/issues/5067)) ([9ac0dde](https://github.com/vuejs/core/commit/9ac0ddea4beec1a1c4471463d3476ccd019bd84e))\n* **sfc-playground:** prevent ctrl+s default behavior ([#5066](https://github.com/vuejs/core/issues/5066)) ([b027507](https://github.com/vuejs/core/commit/b0275070e4824c5efa868528f610eaced83d8fbc))\n* support ref in v-for, remove compat deprecation warnings ([41c18ef](https://github.com/vuejs/core/commit/41c18effea9dd32ab899b5de3bb0513abdb52ee4))\n\n\n\n## [3.2.24](https://github.com/vuejs/core/compare/v3.2.23...v3.2.24) (2021-12-06)\n\n\n### Bug Fixes\n\n* **compat:** maintain compatConfig option in legacy functional comp ([#4974](https://github.com/vuejs/core/issues/4974)) ([ee97cf5](https://github.com/vuejs/core/commit/ee97cf5a4db9e4f135d8eb25aff725eb37363675))\n* **compiler-dom:** avoid bailing stringification on setup const bindings ([29beda7](https://github.com/vuejs/core/commit/29beda7c6f69f79e65f0111cb2d2b8d57d8257bb))\n* **compiler-sfc:** make asset url imports stringifiable ([87c73e9](https://github.com/vuejs/core/commit/87c73e99d6aed0771f8c955ca9d5188ec22c90e7))\n* **package:** ensure ref-macros export is recognized by vue-tsc ([#5003](https://github.com/vuejs/core/issues/5003)) ([f855269](https://github.com/vuejs/core/commit/f8552697fbbdbd444d8322c6b6adeb48cc0b5617))\n* **runtime-core:** handle initial undefined attrs ([#5017](https://github.com/vuejs/core/issues/5017)) ([6d887aa](https://github.com/vuejs/core/commit/6d887aaf591cfa05d5fea978bbd87e3e502bfa86)), closes [#5016](https://github.com/vuejs/core/issues/5016)\n* **types/reactivity:** export ShallowRef type ([#5026](https://github.com/vuejs/core/issues/5026)) ([523b4b7](https://github.com/vuejs/core/commit/523b4b78f5d2e11f1822e09c324a854c790a7863)), closes [#5205](https://github.com/vuejs/core/issues/5205)\n\n\n### Features\n\n* **types/script-setup:** add generic type to defineExpose ([#5035](https://github.com/vuejs/core/issues/5035)) ([34985fe](https://github.com/vuejs/core/commit/34985fee6b23018b6eb6322239db6165c1b0e273))\n\n\n\n## [3.2.23](https://github.com/vuejs/core/compare/v3.2.22...v3.2.23) (2021-11-26)\n\n\n### Bug Fixes\n\n* **reactivity:** retain readonly proxies when setting as reactive property ([d145128](https://github.com/vuejs/core/commit/d145128ab400f4563eb3727626d0942ea5f4980a)), closes [#4986](https://github.com/vuejs/core/issues/4986)\n* **runtime-core:** fix component public instance has check for accessed non-existent properties ([aac0466](https://github.com/vuejs/core/commit/aac0466cb8819fd132fbcc9c4d3e1014c14e2ad8)), closes [#4962](https://github.com/vuejs/core/issues/4962)\n* **runtime-core:** handle error in async KeepAlive hooks ([#4978](https://github.com/vuejs/core/issues/4978)) ([820a143](https://github.com/vuejs/core/commit/820a14345798edc0ab673bae8ce3181e479d9cca))\n* **runtime-dom:** fix option element value patching edge case ([#4959](https://github.com/vuejs/core/issues/4959)) ([89b2f92](https://github.com/vuejs/core/commit/89b2f924fc82d7f71dcb8ffbacb386fd5cf9ade2)), closes [#4956](https://github.com/vuejs/core/issues/4956)\n* **runtime-dom:** patchDOMProps should not set _value if element is custom element ([#4839](https://github.com/vuejs/core/issues/4839)) ([1701bf3](https://github.com/vuejs/core/commit/1701bf3968f001dd3a2bc9f41e3e7e0f1b13e922))\n* **types:** export ref-macros.d.ts ([1245709](https://github.com/vuejs/core/commit/124570973df4ddfdd38e43bf1e92b9710321e5d9))\n* **types:** fix propType<any> type inference ([#4985](https://github.com/vuejs/core/issues/4985)) ([3c449cd](https://github.com/vuejs/core/commit/3c449cd408840d35987fb32b39737fbf093809d6)), closes [#4983](https://github.com/vuejs/core/issues/4983)\n* **types:** scrip-setup+ts: ensure proper handling of `null` as default prop value. ([#4979](https://github.com/vuejs/core/issues/4979)) ([f2d2d7b](https://github.com/vuejs/core/commit/f2d2d7b2d236f256531ae9ad2048bd939c92d834)), closes [#4868](https://github.com/vuejs/core/issues/4868)\n\n\n### Features\n\n* **compiler-sfc:** export resolveTemplateUsageCheckString for HMR plugin use ([#4908](https://github.com/vuejs/core/issues/4908)) ([c61baac](https://github.com/vuejs/core/commit/c61baac75a03b938bc728a8de961ba93736a0ff6))\n* **compiler-sfc:** expose properties for more accurate HMR ([68c45e7](https://github.com/vuejs/core/commit/68c45e73da902e715df9614800a7ab43d6579198)), closes [#4358](https://github.com/vuejs/core/issues/4358) [#4908](https://github.com/vuejs/core/issues/4908)\n\n\n\n## [3.2.22](https://github.com/vuejs/core/compare/v3.2.21...v3.2.22) (2021-11-15)\n\n\n### Bug Fixes\n\n* **compiler-sfc:** add type for props include Function in prod mode ([#4938](https://github.com/vuejs/core/issues/4938)) ([9c42a1e](https://github.com/vuejs/core/commit/9c42a1e2a3385f3b33faed5cdcc430bf8c1fc4b2))\n* **compiler-sfc:** add type for props's properties in prod mode ([#4790](https://github.com/vuejs/core/issues/4790)) ([090df08](https://github.com/vuejs/core/commit/090df0837eb0aedd8a02fd0107b7668ca5c136a1)), closes [#4783](https://github.com/vuejs/core/issues/4783)\n* **compiler-sfc:** externalRE support automatic http/https prefix url pattern ([#4922](https://github.com/vuejs/core/issues/4922)) ([574070f](https://github.com/vuejs/core/commit/574070f43f804fd855f4ee319936ec770a56cef0)), closes [#4920](https://github.com/vuejs/core/issues/4920)\n* **compiler-sfc:** fix expose codegen edge case ([#4919](https://github.com/vuejs/core/issues/4919)) ([31fd590](https://github.com/vuejs/core/commit/31fd590fd47e2dc89b84687ffe26a5c6f05fea34)), closes [#4917](https://github.com/vuejs/core/issues/4917)\n* **devtool:** improve devtools late injection browser env detection ([#4890](https://github.com/vuejs/core/issues/4890)) ([fa2237f](https://github.com/vuejs/core/commit/fa2237f1d824eac511c4246135318594c48dc121))\n* **runtime-core:** improve dedupe listeners when attr fallthrough ([#4912](https://github.com/vuejs/core/issues/4912)) ([b4eb7e3](https://github.com/vuejs/core/commit/b4eb7e3866d7dc722d93a48f4faae1696d4e7023)), closes [#4859](https://github.com/vuejs/core/issues/4859)\n* **types/sfc:** fix withDefaults type inference when using union types ([#4925](https://github.com/vuejs/core/issues/4925)) ([04e5835](https://github.com/vuejs/core/commit/04e58351965caf489ac68e4961ef70448d954912))\n\n\n\n## [3.2.21](https://github.com/vuejs/core/compare/v3.2.20...v3.2.21) (2021-11-02)\n\n\n### Bug Fixes\n\n* **custom-element:** fix custom element props access on initial render ([4b7f76e](https://github.com/vuejs/core/commit/4b7f76e36a7fc650986a20eca258f7a5d912424f)), closes [#4792](https://github.com/vuejs/core/issues/4792)\n* **custom-element:** fix initial attr type casting for programmtically created elements ([3ca8317](https://github.com/vuejs/core/commit/3ca83179d1a798f65e4e70215c511e2f1b64adb6)), closes [#4772](https://github.com/vuejs/core/issues/4772)\n* **devtools:** avoid open handle in non-browser env ([6916d72](https://github.com/vuejs/core/commit/6916d725a06a57e92ff9d046ccf132c305cd0a51)), closes [#4815](https://github.com/vuejs/core/issues/4815)\n* **devtools:** fix memory leak when devtools is not installed ([#4833](https://github.com/vuejs/core/issues/4833)) ([6b32f0d](https://github.com/vuejs/core/commit/6b32f0d976c0aac8bb2c1b78fedd03e76fb391eb)), closes [#4829](https://github.com/vuejs/core/issues/4829)\n* **runtime-core:** add `v-memo` to built-in directives check ([#4787](https://github.com/vuejs/core/issues/4787)) ([5eb7263](https://github.com/vuejs/core/commit/5eb72630a53a8dd82c2b8a9705c21a8075161a3d))\n* **runtime-dom:** fix behavior regression for v-show + style display binding ([3f38d59](https://github.com/vuejs/core/commit/3f38d599f5aacdd3eeaa9475251a24f74e7ae3b4)), closes [#4768](https://github.com/vuejs/core/issues/4768)\n* **types:** fix ref unwrapping type inference for nested shallowReactive & shallowRef ([20a3615](https://github.com/vuejs/core/commit/20a361541cc5faffa82cbf3f2d49639a97b3b678)), closes [#4771](https://github.com/vuejs/core/issues/4771)\n\n\n\n## [3.2.20](https://github.com/vuejs/core/compare/v3.2.19...v3.2.20) (2021-10-08)\n\n\n### Bug Fixes\n\n* **compiler-sfc:** fix props codegen w/ leading import ([d4c04e9](https://github.com/vuejs/core/commit/d4c04e979934b81a30467aa4b1e717175b9b2d80)), closes [#4764](https://github.com/vuejs/core/issues/4764)\n* **compiler-sfc:** support runtime Enum in normal script ([#4698](https://github.com/vuejs/core/issues/4698)) ([f66d456](https://github.com/vuejs/core/commit/f66d456b7a39db9dae7e70c28bb431ff293d8fef))\n* **devtools:** clear devtools buffer after timeout ([f4639e0](https://github.com/vuejs/core/commit/f4639e0a36abe16828b202d7297e1486653b1217)), closes [#4738](https://github.com/vuejs/core/issues/4738)\n* **hmr:** fix hmr for components with no active instance yet ([9e3d773](https://github.com/vuejs/core/commit/9e3d7731c7839638f49157123c6b372fec9e4d46)), closes [#4757](https://github.com/vuejs/core/issues/4757)\n* **types:** ensure that DeepReadonly handles Ref type properly ([#4714](https://github.com/vuejs/core/issues/4714)) ([ed0071a](https://github.com/vuejs/core/commit/ed0071ac1a6d18439f3212711c6901fbb7193288))\n* **types:** make `toRef` return correct type(fix [#4732](https://github.com/vuejs/core/issues/4732)) ([#4734](https://github.com/vuejs/core/issues/4734)) ([925bc34](https://github.com/vuejs/core/commit/925bc346fe85091467fcd2e40d6c1ff07f3b51c4))\n\n\n### Features\n\n* **compiler-sfc:** `<script setup>` defineProps destructure transform ([#4690](https://github.com/vuejs/core/issues/4690)) ([467e113](https://github.com/vuejs/core/commit/467e113b95a3c9c97f8dc309b61c0b2e3caba66f))\n\n\n\n## [3.2.19](https://github.com/vuejs/core/compare/v3.2.18...v3.2.19) (2021-09-25)\n\n\n### Bug Fixes\n\n* **compiler-core:** should treat attribute key as expression ([#4658](https://github.com/vuejs/core/issues/4658)) ([7aa0ea0](https://github.com/vuejs/core/commit/7aa0ea06c822d84a1d43b40cf5643b983aae6d36))\n* **server-renderer:** respect compilerOptions during runtime template compilation ([#4631](https://github.com/vuejs/core/issues/4631)) ([50d9d34](https://github.com/vuejs/core/commit/50d9d3436079419f91231351f20f69062a01505c))\n\n\n\n## [3.2.18](https://github.com/vuejs/core/compare/v3.2.17...v3.2.18) (2021-09-24)\n\n\n\n## [3.2.17](https://github.com/vuejs/core/compare/v3.2.16...v3.2.17) (2021-09-24)\n\n\n### Bug Fixes\n\n* **build:** avoid importing @babel/parser in esm-bundler build ([fc85ad2](https://github.com/vuejs/core/commit/fc85ad28ae55ea9483c923f7d40373cbe27080fe)), closes [#4665](https://github.com/vuejs/core/issues/4665)\n\n\n\n## [3.2.16](https://github.com/vuejs/core/compare/v3.2.15...v3.2.16) (2021-09-23)\n\n\n### Bug Fixes\n\n* **ssr:** fix ssr runtime helper import in module mode ([8e05b7f](https://github.com/vuejs/core/commit/8e05b7f9fcb0e4c4ece2afe9fb2efbd29a6d1482))\n\n\n\n## [3.2.15](https://github.com/vuejs/core/compare/v3.2.14...v3.2.15) (2021-09-23)\n\n\n### Bug Fixes\n\n* **compiler-ssr:** import ssr helpers from updated path ([d74f21a](https://github.com/vuejs/core/commit/d74f21a42cf067abebb4b170d0818cc5d1c06f8d))\n\n\n\n## [3.2.14](https://github.com/vuejs/core/compare/v3.2.13...v3.2.14) (2021-09-22)\n\n\n### Bug Fixes\n\n* **compiler-core:** generate TS-cast safe assignment code for v-model ([686d014](https://github.com/vuejs/core/commit/686d0149b6a4215603fce00b8a54bc310fd5a781)), closes [#4655](https://github.com/vuejs/core/issues/4655)\n* **compiler-core:** more robust member expression check in Node ([6257ade](https://github.com/vuejs/core/commit/6257adeaac03d1401a67714953909e2e31febed6))\n* **compiler-sfc:** fix local var access check for bindings in normal script ([6d6cc90](https://github.com/vuejs/core/commit/6d6cc9091280ba132d92850f30db31c9152af599)), closes [#4644](https://github.com/vuejs/core/issues/4644)\n* **devtools:** fix prod devtools detection + handle late devtools hook injection ([#4653](https://github.com/vuejs/core/issues/4653)) ([2476eaa](https://github.com/vuejs/core/commit/2476eaad6e9d68f0b75772456775a0a8165631c0))\n\n\n\n## [3.2.13](https://github.com/vuejs/core/compare/v3.2.12...v3.2.13) (2021-09-21)\n\n\n### Bug Fixes\n\n* **compiler-core:** add check when v-else-if is behind v-else ([#4603](https://github.com/vuejs/core/issues/4603)) ([5addef8](https://github.com/vuejs/core/commit/5addef8ecdee58e630e4e80befc28bfef43b6b2d))\n* **compiler-core:** dedupe renderSlot's default props ([#4557](https://github.com/vuejs/core/issues/4557)) ([0448125](https://github.com/vuejs/core/commit/044812525feef125c3a1a8de57bd7d67fb8f3cab))\n* **compiler-core:** ensure hoisted scopeId code can be treeshaken ([cb2d7c0](https://github.com/vuejs/core/commit/cb2d7c0e3c2ccbfd92eb7d19e2cfddad30bcaf62))\n* **compiler-core:** more robust member expression check when running in node ([d23fde3](https://github.com/vuejs/core/commit/d23fde3d3b17b2a8c058749cb28d5b1dd08c8963)), closes [#4640](https://github.com/vuejs/core/issues/4640)\n* **compiler-core:** only merge true handlers ([#4577](https://github.com/vuejs/core/issues/4577)) ([d8a36d0](https://github.com/vuejs/core/commit/d8a36d0198a427d3b6447128a3882287c0003413))\n* **compiler-core:** support ts syntax in expressions when isTS is true ([0dc521b](https://github.com/vuejs/core/commit/0dc521b9e15ce4aa3d5229e90d2173644529e92b))\n* **compiler-dom:** fix transition children check for whitespace nodes ([ed6470c](https://github.com/vuejs/core/commit/ed6470c845efa57d902c50a7b97e4a40331e9621)), closes [#4637](https://github.com/vuejs/core/issues/4637)\n* **hydration:** ensure hydrated event listeners have bound instance ([#4529](https://github.com/vuejs/core/issues/4529)) ([58b1fa5](https://github.com/vuejs/core/commit/58b1fa5ed15edc7264785cd722282a011ea3042c)), closes [#4479](https://github.com/vuejs/core/issues/4479)\n* **runtime-core:** return the exposeProxy from mount ([#4606](https://github.com/vuejs/core/issues/4606)) ([5aa4255](https://github.com/vuejs/core/commit/5aa425580808d0588aef12ead81c91f7147e1042))\n* **types:** incorrect type inference of array ([#4578](https://github.com/vuejs/core/issues/4578)) ([140f089](https://github.com/vuejs/core/commit/140f08991727d7c15db907eea5a101979fe390b2))\n* **watch:** remove redundant parameter default value ([#4565](https://github.com/vuejs/core/issues/4565)) ([11a2098](https://github.com/vuejs/core/commit/11a2098a69f47e0919647de0deabd14022febda1))\n\n\n### Features\n\n* **compiler-sfc:** allow disabling sourcemap when not needed ([585615b](https://github.com/vuejs/core/commit/585615beb1727e6eb32c41f1e0bba6975ff40b28))\n\n\n\n## [3.2.12](https://github.com/vuejs/core/compare/v3.2.11...v3.2.12) (2021-09-17)\n\n\n### Bug Fixes\n\n* **compile-sfc:**  add symbol judge in prop type checks. ([#4594](https://github.com/vuejs/core/issues/4594)) ([fcd5422](https://github.com/vuejs/core/commit/fcd5422b4adaf99627ea0d675d98b2d9530c05ab)), closes [#4592](https://github.com/vuejs/core/issues/4592)\n* **compiler-core:** v-on inline async function expression handler ([#4569](https://github.com/vuejs/core/issues/4569)) ([fc968d6](https://github.com/vuejs/core/commit/fc968d607b181db9d50cd4b30a8d7e4cc5fe9d2b)), closes [#4568](https://github.com/vuejs/core/issues/4568)\n* **compiler-sfc:** fix TLA codegen semicolon insertion ([39cebf5](https://github.com/vuejs/core/commit/39cebf5f7a8f72338030844fca4a75ffc913c518)), closes [#4596](https://github.com/vuejs/core/issues/4596)\n* **compiler-sfc:** handle empty strings during template usage analysis of setup bindings ([#4608](https://github.com/vuejs/core/issues/4608)) ([bdb1a79](https://github.com/vuejs/core/commit/bdb1a7958ba091bb3166f0938e91ebd52facbf03)), closes [#4599](https://github.com/vuejs/core/issues/4599)\n* **compiler-sfc:** properly analyze destructured bindings with dynamic keys ([a6e5f82](https://github.com/vuejs/core/commit/a6e5f82d8ea5fe55432d0277e88300045eca4237)), closes [#4540](https://github.com/vuejs/core/issues/4540)\n* **compiler-sfc:** properly reuse hoisted asset imports ([06c5bf5](https://github.com/vuejs/core/commit/06c5bf53abc8143acb92e25b21394a79e11170d8)), closes [#4581](https://github.com/vuejs/core/issues/4581)\n* **compiler-sfc:** register exported bindings in normal script when using script setup ([#4601](https://github.com/vuejs/core/issues/4601)) ([8055445](https://github.com/vuejs/core/commit/8055445b68b18a73670a9f3e7534af5d31f65c38)), closes [#4600](https://github.com/vuejs/core/issues/4600)\n* **compiler-sfc:** support nested await statements ([#4458](https://github.com/vuejs/core/issues/4458)) ([ae942cd](https://github.com/vuejs/core/commit/ae942cdcd9bd686e7b0394c8e91e63a31ff8fb5d)), closes [#4448](https://github.com/vuejs/core/issues/4448)\n* **compiler-ssr:** handle v-memo in ssr compilation ([dd9a276](https://github.com/vuejs/core/commit/dd9a2760a8f8da94ba634ac984f9f14ac053fe31))\n* **compiler:** fix template ref codegen for setup-maybe-ref binding types ([#4549](https://github.com/vuejs/core/issues/4549)) ([f29d061](https://github.com/vuejs/core/commit/f29d0611246bb619df2e46b30dfd5e43ad4ee6b1)), closes [#4546](https://github.com/vuejs/core/issues/4546)\n* **custom-elements:** fix number prop casting ([0cfa211](https://github.com/vuejs/core/commit/0cfa2112ce2210300cf2edf272c8c8d11b9355e4)), closes [#4370](https://github.com/vuejs/core/issues/4370) [#4393](https://github.com/vuejs/core/issues/4393)\n* **runtime-core:** avoid script setup bindings overwriting reserved ctx properties ([#4570](https://github.com/vuejs/core/issues/4570)) ([14fcced](https://github.com/vuejs/core/commit/14fcced281c5de2f07629a8028653cab1e787b89))\n* **suspense:** fix suspense slot inside deoptimized slot call ([141a5e1](https://github.com/vuejs/core/commit/141a5e188cbf6fbc433173aab922940c7d2471be)), closes [#4556](https://github.com/vuejs/core/issues/4556)\n\n\n\n## [3.2.11](https://github.com/vuejs/core/compare/v3.2.10...v3.2.11) (2021-09-08)\n\n\n### Bug Fixes\n\n* **hmr:** handle possible duplicate component definitions with same id ([aa8908a](https://github.com/vuejs/core/commit/aa8908a8543c5151a2cc06ed4d8fab3a1461692a))\n\n\n\n## [3.2.10](https://github.com/vuejs/core/compare/v3.2.9...v3.2.10) (2021-09-07)\n\n\n### Bug Fixes\n\n* **build:** build vue-compat in default exports mode ([#4460](https://github.com/vuejs/core/issues/4460)) ([7575733](https://github.com/vuejs/core/commit/7575733b8c1345ebdfb010bd4c4e8cf4ed49f5cf))\n* **compiler-core:** avoid runtime dependency on @babel/types ([1045590](https://github.com/vuejs/core/commit/1045590d4bbaf4a2b05311f11b22a0b3d22cf609)), closes [#4531](https://github.com/vuejs/core/issues/4531)\n* **compiler-core:** pick last char when dynamic directive doesn't close ([#4507](https://github.com/vuejs/core/issues/4507)) ([5d262e0](https://github.com/vuejs/core/commit/5d262e08d5d5fb29f48ba5fa5b97a9a3e34b9d4b))\n* **compiler:** condense whitespaces in static class attributes ([#4432](https://github.com/vuejs/core/issues/4432)) ([b8653d3](https://github.com/vuejs/core/commit/b8653d390a555e1ee3f92a1c49cfd8800c67e46a)), closes [#4251](https://github.com/vuejs/core/issues/4251)\n* **runtime-dom:** style patching should always preserve v-show display property ([d534515](https://github.com/vuejs/core/commit/d53451583684c37bda7d30bff912216e1a58126f)), closes [#4424](https://github.com/vuejs/core/issues/4424)\n* **type:** fix prop type infer ([#4530](https://github.com/vuejs/core/issues/4530)) ([4178d5d](https://github.com/vuejs/core/commit/4178d5d7d9549a0a1d19663bc2f92c8ac6a731b2)), closes [#4525](https://github.com/vuejs/core/issues/4525)\n\n\n\n## [3.2.9](https://github.com/vuejs/core/compare/v3.2.8...v3.2.9) (2021-09-05)\n\n\n### Bug Fixes\n\n* **compile-sfc:** generate setup prop type format error ([#4506](https://github.com/vuejs/core/issues/4506)) ([e6fe751](https://github.com/vuejs/core/commit/e6fe751b20dd9c34068b27545cb7459de2d538e6)), closes [#4505](https://github.com/vuejs/core/issues/4505)\n* **compile-sfc:** support  `Date` prop type with defineProps ([#4519](https://github.com/vuejs/core/issues/4519)) ([fac9a29](https://github.com/vuejs/core/commit/fac9a2926d5b825b7daacb7914fd3b34abc02cb7))\n* **compiler-sfc:** fix script setup ref assignment codegen edge case ([#4520](https://github.com/vuejs/core/issues/4520)) ([5594643](https://github.com/vuejs/core/commit/5594643d7b49b77e60f6d4682a3a71db0b1c6552)), closes [#4514](https://github.com/vuejs/core/issues/4514)\n* **compiler-sfc:** support using declared interface in normal script with defineProps() ([#4522](https://github.com/vuejs/core/issues/4522)) ([14d6518](https://github.com/vuejs/core/commit/14d65181f1610079f0d9969c214720624056106b)), closes [#4423](https://github.com/vuejs/core/issues/4423)\n* **ref-transform:** not transform the prototype attributes. ([#4503](https://github.com/vuejs/core/issues/4503)) ([0178f4e](https://github.com/vuejs/core/commit/0178f4ed3187dff439ed3097c8c89555b2a6749f)), closes [#4502](https://github.com/vuejs/core/issues/4502)\n* **types/ref-transform:** fix $$() type ([5852cc8](https://github.com/vuejs/core/commit/5852cc8d825b0746bbf5e4c324afa02280046005))\n* **types:** fix ref macro types ([815bfcf](https://github.com/vuejs/core/commit/815bfcffae7a9f04ee996367a731e6e072af6bd2)), closes [#4499](https://github.com/vuejs/core/issues/4499)\n\n\n\n## [3.2.8](https://github.com/vuejs/core/compare/v3.2.7...v3.2.8) (2021-09-02)\n\n\n### Bug Fixes\n\n* **compiler-sfc:** ensure script setup generates type-valid ts output ([bacb201](https://github.com/vuejs/core/commit/bacb2012acb4045a2db6988ba4545a7655d6ca14)), closes [#4455](https://github.com/vuejs/core/issues/4455)\n* **compiler-sfc:** generate matching prop types when withDefaults is used ([#4466](https://github.com/vuejs/core/issues/4466)) ([8580796](https://github.com/vuejs/core/commit/85807967dc874e6ea6b20f341875beda938e3058)), closes [#4455](https://github.com/vuejs/core/issues/4455)\n* **compiler:** generate function ref for script setup if inline is true. ([#4492](https://github.com/vuejs/core/issues/4492)) ([4cd282b](https://github.com/vuejs/core/commit/4cd282b0a17589ef9ca2649e7beb0bdee4a73c57))\n* **compiler:** report invalid directive name error ([#4494](https://github.com/vuejs/core/issues/4494)) ([#4495](https://github.com/vuejs/core/issues/4495)) ([c00925e](https://github.com/vuejs/core/commit/c00925ed5c409b57a1540b79c595b7f8117e2d4c))\n* **types:** include ref-macros.d.ts in npm dist files ([d7f1b77](https://github.com/vuejs/core/commit/d7f1b771f80ab9014a4701913b50458fd251a117)), closes [#4433](https://github.com/vuejs/core/issues/4433)\n\n\n\n## [3.2.7](https://github.com/vuejs/core/compare/v3.2.6...v3.2.7) (2021-09-01)\n\n\n### Bug Fixes\n\n* **compiler-core:** remove no longer necessary withScopeId import in generated code ([935b4e2](https://github.com/vuejs/core/commit/935b4e221041c8ae34c5821d90db90f07e622a9f))\n* **compiler-sfc:** ensure script setup lang=ts output is tree-shakable ([b89ff92](https://github.com/vuejs/core/commit/b89ff9291e70c64f7098cc110161a75eb7c465a4))\n* **compiler:** only generate non-static ref for script setup if the binding exists ([3628991](https://github.com/vuejs/core/commit/362899190666a2d1f9fe23c92e9b6007721ad69f)), closes [#4431](https://github.com/vuejs/core/issues/4431)\n* **ref-transform:** should transform $ref when used with generic arguments ([#4446](https://github.com/vuejs/core/issues/4446)) ([33cf6c8](https://github.com/vuejs/core/commit/33cf6c88664137e8c9d6e75a3b4c5f5cce763c12)), closes [#4442](https://github.com/vuejs/core/issues/4442)\n* **runtime-core:** properly merge unmounted and beforeUnmount options ([#4447](https://github.com/vuejs/core/issues/4447)) ([741d3b3](https://github.com/vuejs/core/commit/741d3b36f21582e682009114961b5cd3146e8dad))\n* **suspense:** misusing DOM Comment element constructor as a vnode type ([#4451](https://github.com/vuejs/core/issues/4451)) ([ef5b731](https://github.com/vuejs/core/commit/ef5b73159d7221c36c25e32f643669d789a33c2c))\n\n\n\n## [3.2.6](https://github.com/vuejs/core/compare/v3.2.5...v3.2.6) (2021-08-24)\n\n\n### Bug Fixes\n\n* **build:** avoid imports to @babel/types in client build of compiler-core ([4c468eb](https://github.com/vuejs/core/commit/4c468eb30a87f726d43c94476b75063640c3ff1c))\n\n\n\n## [3.2.5](https://github.com/vuejs/core/compare/v3.2.4...v3.2.5) (2021-08-24)\n\n\n### Bug Fixes\n\n* **compiler-core:** fix duplicated component identifier for names with non-ascii chars ([#4429](https://github.com/vuejs/core/issues/4429)) ([3282750](https://github.com/vuejs/core/commit/32827506ff2b6174d63525e7713830838840c671)), closes [#4422](https://github.com/vuejs/core/issues/4422)\n* **compiler-sfc:**   fix 'export default' rewrite with extra whitespaces ([#4375](https://github.com/vuejs/core/issues/4375)) ([4792ebd](https://github.com/vuejs/core/commit/4792ebd6879115f887e393c7ed0a8475a705b6b0))\n* **compiler-sfc:** fix `<script>` and `<script setup>` co-usage ordering edge case ([#4419](https://github.com/vuejs/core/issues/4419)) ([9826382](https://github.com/vuejs/core/commit/98263821f8c42abcff46fae2b0375219c84fb6a4)), closes [#4395](https://github.com/vuejs/core/issues/4395) [#4376](https://github.com/vuejs/core/issues/4376)\n* **compiler-sfc:** should also expose regular script block bindings when `<script setup>` is used ([872b3f7](https://github.com/vuejs/core/commit/872b3f7ec5e1a41c60018bb1f64d841c309b8939)), closes [#4369](https://github.com/vuejs/core/issues/4369)\n* **types:** improve the type of createElementBlock ([#4406](https://github.com/vuejs/core/issues/4406)) ([ebd0bac](https://github.com/vuejs/core/commit/ebd0baca98b618945fba223b94833c2b34cdf6a2)), closes [#4391](https://github.com/vuejs/core/issues/4391)\n\n\n### Features\n\n* **experimental:** expose ref macro types using separate d.ts file ([b408451](https://github.com/vuejs/core/commit/b40845153cd4dbdd76bfb74816f4e6b109c9f049))\n* **experimental:** shouldTransform for ref-transform ([e565831](https://github.com/vuejs/core/commit/e565831c98ac5110bf3550f15575ee6d01961992))\n* **experimental:** standalone ref transform ([db8dc75](https://github.com/vuejs/core/commit/db8dc753c0647edfb878d3b0f7b5b16bcfd2c23c))\n* **experimental:** support ref transform for sfc normal `<script>` ([06051c4](https://github.com/vuejs/core/commit/06051c4bf207ff9ac09292b8a5a73b254608cf0e))\n* **ref-transform:** auto infer parser plugins ([6453359](https://github.com/vuejs/core/commit/6453359852d4c93fe436bb94d73181eaa218b527))\n\n\n\n## [3.2.4](https://github.com/vuejs/core/compare/v3.2.3...v3.2.4) (2021-08-17)\n\n\n### Bug Fixes\n\n* **compiler-sfc:** fix import usage check for lowercase imported components ([57f1081](https://github.com/vuejs/core/commit/57f10812cc7f1e9f6c92736c36aba577943996fd)), closes [#4358](https://github.com/vuejs/core/issues/4358)\n* **runtime-core:** ensure consistent arguments for template and render function slot usage ([644971e](https://github.com/vuejs/core/commit/644971ec06642817cf7e720ad4980182d2140f53)), closes [#4367](https://github.com/vuejs/core/issues/4367)\n* **runtime-core:** fix child component double update on props change ([c1f564e](https://github.com/vuejs/core/commit/c1f564e1dc40eda9af657c30cd787a8d770dde0f)), closes [#4365](https://github.com/vuejs/core/issues/4365)\n\n\n### Reverts\n\n* Revert \"chore: add missing space in warning message (#4359) [ci skip]\" ([951fbb1](https://github.com/vuejs/core/commit/951fbb197b63c2bd1528e78601c28424211ba6b8)), closes [#4359](https://github.com/vuejs/core/issues/4359)\n\n\n\n## [3.2.3](https://github.com/vuejs/core/compare/v3.2.2...v3.2.3) (2021-08-16)\n\n\n### Bug Fixes\n\n* **compiler-core:** fix hoisting logic for elements with cached handlers + other bindings ([a6c1db2](https://github.com/vuejs/core/commit/a6c1db2728cd3c72b897cb7b245d532e63485b07)), closes [#4327](https://github.com/vuejs/core/issues/4327)\n* **compiler-core:** fix style binding edge case ([#4319](https://github.com/vuejs/core/issues/4319)) ([092bdcd](https://github.com/vuejs/core/commit/092bdcdf58643d77da8d564fbc3c5c6647f6bfc5)), closes [#4317](https://github.com/vuejs/core/issues/4317)\n* **compiler-sfc:** bail on import usage check when template has custom lang ([aae3725](https://github.com/vuejs/core/commit/aae3725e574e0182a1b41aa3dc38b11e596570ad)), closes [#4312](https://github.com/vuejs/core/issues/4312)\n* **compiler-sfc:** fix import usage check in template strings in expressions ([f855ccb](https://github.com/vuejs/core/commit/f855ccb2c1a8ea05ae71cfab92f5a18be31a1f14)), closes [#4340](https://github.com/vuejs/core/issues/4340)\n* **defineProps:** defineProps generates unnecessary array of same types ([#4353](https://github.com/vuejs/core/issues/4353)) ([ad66295](https://github.com/vuejs/core/commit/ad66295cb363f6409b8321f258aaf29b3758c53c)), closes [#4352](https://github.com/vuejs/core/issues/4352)\n* **runtime-core:** patchChildren first in patchElement ([#4313](https://github.com/vuejs/core/issues/4313)) ([5b3f1e8](https://github.com/vuejs/core/commit/5b3f1e8424d40d2b7b1e07f53ec11570dd546d66))\n* **runtime-core:** vnode hooks should not be called on async wrapper ([#4349](https://github.com/vuejs/core/issues/4349)) ([cd2d984](https://github.com/vuejs/core/commit/cd2d98499ed646c85f81faa1f9241b0585654b86)), closes [#4346](https://github.com/vuejs/core/issues/4346)\n* **runtime-dom:** consistently remove boolean attributes for falsy values ([#4348](https://github.com/vuejs/core/issues/4348)) ([620a69b](https://github.com/vuejs/core/commit/620a69b871a017dfe0ba81d380fd933d997c8a00))\n* **shared:** fix toDisplayString on object with null prototype ([#4335](https://github.com/vuejs/core/issues/4335)) ([42a334e](https://github.com/vuejs/core/commit/42a334e12ee1462ccefc73fd7f24dc6b4ae48403)), closes [#4334](https://github.com/vuejs/core/issues/4334)\n* **types:** fix tsx ref component instance type ([#2486](https://github.com/vuejs/core/issues/2486)) ([84d4357](https://github.com/vuejs/core/commit/84d4357f6f2b2eb03ca56abfb3cac17fa7dfa85e))\n\n\n\n## [3.2.2](https://github.com/vuejs/core/compare/v3.2.1...v3.2.2) (2021-08-11)\n\n\n### Bug Fixes\n\n* **runtime-dom:** patch `textContent` on svg properly ([#4301](https://github.com/vuejs/core/issues/4301)) ([e7b0a9d](https://github.com/vuejs/core/commit/e7b0a9d3cffc938d3add7dcde02d0991f60c6ec9)), closes [#4296](https://github.com/vuejs/core/issues/4296)\n* **server-renderer:** pipeToWebWritable CF worker compat ([2224610](https://github.com/vuejs/core/commit/2224610b0b390d82d7b5436df1f78b0569a199a9)), closes [#4287](https://github.com/vuejs/core/issues/4287)\n* **types:** allow symbol in JSX ReservedProps.key ([#4306](https://github.com/vuejs/core/issues/4306)) ([6e5801f](https://github.com/vuejs/core/commit/6e5801f8a8cc23d05817ee94fd98cb1889cc8413))\n* **types:** fix forceUpdate type ([#4302](https://github.com/vuejs/core/issues/4302)) ([380608b](https://github.com/vuejs/core/commit/380608bd44eb385ec085eec4355e6fdc01ca09cd))\n* **types:** fix tsx emit-mapped handler return type ([#4290](https://github.com/vuejs/core/issues/4290)) ([1ce34e2](https://github.com/vuejs/core/commit/1ce34e25d56e73591acc5bbe6e52ec8ef026cc6c)), closes [#4288](https://github.com/vuejs/core/issues/4288)\n\n\n### Features\n\n* **sfc:** support $shallowRef ref sugar ([00b76d3](https://github.com/vuejs/core/commit/00b76d3dc192138514ae6464ded34be5b0c730bb))\n\n\n\n## [3.2.1](https://github.com/vuejs/core/compare/v3.2.0...v3.2.1) (2021-08-09)\n\n\n### Bug Fixes\n\n* **compiler-sfc:** fix import usage check for last expression ([1e1682f](https://github.com/vuejs/core/commit/1e1682f060883ee11e802834adb273159d8e84cc))\n\n\n\n# [3.2.0](https://github.com/vuejs/core/compare/v3.2.0-beta.8...v3.2.0) (2021-08-09)\n\n### Compatibility Notes\n\nThis release contains no public API breakage. However, there are a few compatibility related notes:\n\n- Due to usage of new runtime helpers, code generated by the template compiler in >= 3.2 will not be compatible with runtime < 3.2.\n\n  This only affects cases where there is a version mismatch between the compiler and the runtime. The most common case is libraries that ship pre-compiled Vue components. If you are a library author and ship code pre-compiled by Vue >= 3.2, your library will be only compatible Vue >= 3.2.\n\n- This release ships TypeScript typings that rely on [Template Literal Types](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-1.html#template-literal-types) and requires TS >= 4.1.\n\n### Features\n\n#### SFC\n\n- remove experimental status of `<script setup>` ([27104ea](https://github.com/vuejs/core/commit/27104eaaf0f929a4c08b53877b495c5813157232)) ([Docs](https://v3.vuejs.org/api/sfc-script-setup.html)) ([RFC](https://github.com/vuejs/rfcs/blob/master/active-rfcs/0040-script-setup.md))\n- remove experimental status for sfc `<style>` v-bind ([3b38c9a](https://github.com/vuejs/core/commit/3b38c9ae9b08c41ee3a70c8ef94fd078f05a8925)) ([Docs](https://v3.vuejs.org/api/sfc-style.html#state-driven-dynamic-css)) ([RFC](https://github.com/vuejs/rfcs/blob/master/active-rfcs/0043-sfc-style-variables.md))\n- support non-explicit type imports in `<script setup>` by avoiding exposing unused imports to template during dev ([5a3ccfd](https://github.com/vuejs/core/commit/5a3ccfd9143700c7ca82d2911fe592d0658c5393)), closes [#3183](https://github.com/vuejs/core/issues/3183)\n- support namespaced component tags when using `<script setup>` ([e5a4412](https://github.com/vuejs/core/commit/e5a4412764f6db255afe01b8a7e6e40ebf707412))\n- **(experimental)** new ref sugar ([562bddb](https://github.com/vuejs/core/commit/562bddb3ce76a0e98e499e199e96fa4271e5d1b4)) ([RFC](https://github.com/vuejs/rfcs/discussions/369))\n\n#### Custom Elements\n\n- `defineCustomElement` ([8610e1c](https://github.com/vuejs/core/commit/8610e1c9e23a4316f76fb35eebbab4ad48566fbf)) ([Docs](https://v3.vuejs.org/guide/web-components.html))\n\n#### Reactivity\n\n- new `effectScope` API ([#2195](https://github.com/vuejs/core/issues/2195)) ([f5617fc](https://github.com/vuejs/core/commit/f5617fc3bb8fd33927b2567622ac4f8b43f9b5d5)) ([RFC](https://github.com/vuejs/rfcs/blob/master/active-rfcs/0041-reactivity-effect-scope.md))\n- support `onTrack/onTrigger` debug options for `computed` ([5cea9a1](https://github.com/vuejs/core/commit/5cea9a1d4e846f60515ef76ebab4800228645601))\n\n#### SSR\n\n- **server-renderer:** decouple esm build from Node + improve stream API ([0867222](https://github.com/vuejs/core/commit/08672222c611a61f6359543aa202f0841d199bcb)), closes [#3467](https://github.com/vuejs/core/issues/3467) [#3111](https://github.com/vuejs/core/issues/3111) [#3460](https://github.com/vuejs/core/issues/3460) ([Docs](https://github.com/vuejs/core/tree/main/packages/server-renderer#readme))\n\n#### Generic\n\n- New `v-memo` directive ([3b64508](https://github.com/vuejs/core/commit/3b64508e3b2d648e346cbf34e1641f4022be61b6)) ([Docs](https://v3.vuejs.org/api/directives.html#v-memo))\n- support `v-bind` .prop & .attr modifiers ([1c7d737](https://github.com/vuejs/core/commit/1c7d737cc8ed0384b334d0b3e2dc8ede44906dc4)) ([Docs](https://v3.vuejs.org/api/directives.html#v-bind))\n- add `watchPostEffect` API ([42ace95](https://github.com/vuejs/core/commit/42ace9577da49477ff189950a83d6eead73d0efe)) ([Docs](https://v3.vuejs.org/api/computed-watch-api.html#watchposteffect))\n- add `watchSyncEffect` API ([d87d059](https://github.com/vuejs/core/commit/d87d059ac120ed0496f85474344ef76e40fa9bc7)) ([Docs](https://v3.vuejs.org/api/computed-watch-api.html#watchsynceffect))\n- unwrap refs in toDisplayString ([f994b97](https://github.com/vuejs/core/commit/f994b974c0a1ac95d313c8ccfc258c6ba3910b6e))\n- allow `compilerOptions.comments` to affect comment inclusion in dev ([#4115](https://github.com/vuejs/core/issues/4115)) ([dd0f9d1](https://github.com/vuejs/core/commit/dd0f9d1ce6b0de59c84d334c7190fa9d2cc17a04)), closes [#3392](https://github.com/vuejs/core/issues/3392) [#3395](https://github.com/vuejs/core/issues/3395)\n\n#### Types\n\n- map declared emits to onXXX props in inferred prop types ([#3926](https://github.com/vuejs/core/issues/3926)) ([69344ff](https://github.com/vuejs/core/commit/69344ff1ae724beb648c34ede8050b3b70ddf4b7))\n\n### Performance Improvements\n\n- **reactivity:** improve reactive effect memory usage ([#4001](https://github.com/vuejs/core/issues/4001)) ([87f69fd](https://github.com/vuejs/core/commit/87f69fd0bb67508337fb95cb98135fd5d6ebca7d)), closes [#2345](https://github.com/vuejs/core/issues/2345)\n- **reactivity:** ref-specific track/trigger and miscellaneous optimizations ([#3995](https://github.com/vuejs/core/issues/3995)) ([6431040](https://github.com/vuejs/core/commit/64310405acaccabc24985ade95fb1b5c9c06ef76))\n- **reactivity:** use bitwise dep markers to optimize re-tracking ([#4017](https://github.com/vuejs/core/issues/4017)) ([6cf2377](https://github.com/vuejs/core/commit/6cf2377cd49d24814bdff136bf78c77d50d5b41a))\n- **compiler-core/runtime-core:** improve VNode creation performance with compiler hints ([#3334](https://github.com/vuejs/core/issues/3334)) ([ceff899](https://github.com/vuejs/core/commit/ceff89905b05381d3d73c480e08c7aff9271b074))\n- **compiler-core:** also hoist all-static children array ([b7ea7c1](https://github.com/vuejs/core/commit/b7ea7c148552874e8bce399eec9fbe565efa2f4d))\n- **compiler-core:** hoist dynamic props lists ([02339b6](https://github.com/vuejs/core/commit/02339b67d8c6fab6ee701a7c4f2773139ed007f5))\n- **compiler-sfc:** ignore empty blocks ([#3520](https://github.com/vuejs/core/issues/3520)) ([b771fdb](https://github.com/vuejs/core/commit/b771fdbef9a8dadd4c9cc939cc104f7764e40373))\n\n### Bug Fixes\n\nPlease refer to changelogs of previous beta releases for bug fixes included in this release.\n\n# [3.2.0-beta.8](https://github.com/vuejs/core/compare/v3.2.0-beta.7...v3.2.0-beta.8) (2021-08-07)\n\n### Bug Fixes\n\n- **compiler-core:** detected forwarded slots in nested components ([#4268](https://github.com/vuejs/core/issues/4268)) ([abb3a81](https://github.com/vuejs/core/commit/abb3a81e871e271db8dd882f9323551e753cc00f)), closes [#4244](https://github.com/vuejs/core/issues/4244)\n- **compiler-sfc:** fix ref sugar rewrite for identifiers in ts casting expressions ([865b84b](https://github.com/vuejs/core/commit/865b84bfe81622626152e9c571cd26f30ba37bd5)), closes [#4254](https://github.com/vuejs/core/issues/4254)\n- **core:** typing of key in VNodeProps ([#4242](https://github.com/vuejs/core/issues/4242)) ([d045055](https://github.com/vuejs/core/commit/d045055b475f76624830ed594dd138ac71eccd4e)), closes [#4240](https://github.com/vuejs/core/issues/4240)\n- **runtime-core:** component effect scopes should be detached ([6aa871e](https://github.com/vuejs/core/commit/6aa871e5658f79369ae4022b2c73319444bd1cca))\n- **runtime-dom:** fix shadowRoot instanceof check in unsupported browsers ([#4238](https://github.com/vuejs/core/issues/4238)) ([bc7dd93](https://github.com/vuejs/core/commit/bc7dd93f9223e8c5809ad7b95fcf8b2414181b91))\n- **types:** remove explicit return type annotation requirement for `this` inference in computed options ([#4221](https://github.com/vuejs/core/issues/4221)) ([d3d5ad2](https://github.com/vuejs/core/commit/d3d5ad204d17e18f6a038c7f6c3cc2a5c2271a08))\n- **v-memo:** ensure track block when returning cached vnode ([#4270](https://github.com/vuejs/core/issues/4270)) ([a211e27](https://github.com/vuejs/core/commit/a211e271ee8c328e68afc0fe5ab86fabd7e4a320)), closes [#4253](https://github.com/vuejs/core/issues/4253)\n- **v-memo:** should work on v-for with constant expression ([#4272](https://github.com/vuejs/core/issues/4272)) ([3b60358](https://github.com/vuejs/core/commit/3b60358d0e0289298df7937983b3e06123f8eb3d)), closes [#4246](https://github.com/vuejs/core/issues/4246)\n\n### Features\n\n- **runtime-dom:** support async component in defineCustomElement ([c421fb9](https://github.com/vuejs/core/commit/c421fb91b2bec047e665f8269e231bf89f9bfc93)), closes [#4261](https://github.com/vuejs/core/issues/4261)\n\n# [3.2.0-beta.7](https://github.com/vuejs/core/compare/v3.2.0-beta.6...v3.2.0-beta.7) (2021-07-29)\n\n### Bug Fixes\n\n- **reactivity:** dereference nested effect scopes on manual stop ([1867591](https://github.com/vuejs/core/commit/1867591e7c54406e92575753dd77fffba17606a2))\n- **sfc/style-vars:** improve ignore style variable bindings in comments ([#4202](https://github.com/vuejs/core/issues/4202)) ([771635b](https://github.com/vuejs/core/commit/771635b72af598c4dd5c3a034b31613fe208e4b3))\n- **shared:** support custom .toString() in text interpolation again ([#4210](https://github.com/vuejs/core/issues/4210)) ([9d5fd33](https://github.com/vuejs/core/commit/9d5fd33d6dadf3186f7979d811dedf092f3ddcb7)), closes [#3944](https://github.com/vuejs/core/issues/3944)\n- **suspense:** fix dynamicChildren tracking when suspense root is a block itself ([51ee84f](https://github.com/vuejs/core/commit/51ee84fc6a5a1ab83cd02f17154803c47e65ae16)), closes [#4183](https://github.com/vuejs/core/issues/4183) [#4198](https://github.com/vuejs/core/issues/4198)\n\n### Features\n\n- **server-renderer:** decouple esm build from Node + improve stream API ([0867222](https://github.com/vuejs/core/commit/08672222c611a61f6359543aa202f0841d199bcb)), closes [#3467](https://github.com/vuejs/core/issues/3467) [#3111](https://github.com/vuejs/core/issues/3111) [#3460](https://github.com/vuejs/core/issues/3460)\n- **sfc:** remove experimental status for sfc style v-bind ([3b38c9a](https://github.com/vuejs/core/commit/3b38c9ae9b08c41ee3a70c8ef94fd078f05a8925))\n\n# [3.2.0-beta.6](https://github.com/vuejs/core/compare/v3.2.0-beta.5...v3.2.0-beta.6) (2021-07-27)\n\n### Bug Fixes\n\n- **inject:** should auto unwrap injected refs ([561e210](https://github.com/vuejs/core/commit/561e210157874b216efc1c17be701a6a81c4383b)), closes [#4196](https://github.com/vuejs/core/issues/4196)\n- **runtime-core:** expose ssrUtils in esm-bundler build ([ee4cbae](https://github.com/vuejs/core/commit/ee4cbaeec917362c571ce95352adccd6ec2d1f47)), closes [#4199](https://github.com/vuejs/core/issues/4199)\n- **sfc/style-vars:** should ignore style variable bindings in comments ([#4188](https://github.com/vuejs/core/issues/4188)) ([3a75d5d](https://github.com/vuejs/core/commit/3a75d5d6942a1743789192dca9161f7c30a71e58)), closes [#4185](https://github.com/vuejs/core/issues/4185)\n\n### Features\n\n- unwrap refs in toDisplayString ([f994b97](https://github.com/vuejs/core/commit/f994b974c0a1ac95d313c8ccfc258c6ba3910b6e))\n\n# [3.2.0-beta.5](https://github.com/vuejs/core/compare/v3.2.0-beta.4...v3.2.0-beta.5) (2021-07-23)\n\n### Bug Fixes\n\n- **hmr:** fix custom elements hmr edge cases ([bff4ea7](https://github.com/vuejs/core/commit/bff4ea74c545ccc7e39f45d4db4e7c471f248b13))\n- **hmr:** fix hmr when global mixins are used ([db3f57a](https://github.com/vuejs/core/commit/db3f57a39206eb33946a42bc230eb972bde61368)), closes [#4174](https://github.com/vuejs/core/issues/4174)\n- **types:** fix types for readonly ref ([2581cfb](https://github.com/vuejs/core/commit/2581cfb707f90bdf4128e5d481b99e7c39e198d3)), closes [#4180](https://github.com/vuejs/core/issues/4180)\n- **v-model:** avoid resetting value of in-focus & lazy input ([ac74e1d](https://github.com/vuejs/core/commit/ac74e1dd33a45874a96fc13efdaade613c44dd70)), closes [#4182](https://github.com/vuejs/core/issues/4182)\n\n### Features\n\n- **compiler-sfc:** avoid exposing imports not used in template ([5a3ccfd](https://github.com/vuejs/core/commit/5a3ccfd9143700c7ca82d2911fe592d0658c5393)), closes [#3183](https://github.com/vuejs/core/issues/3183)\n- **runtime-dom:** hmr for custom elements ([7a7e1d8](https://github.com/vuejs/core/commit/7a7e1d8e9fed27bc2dbf24076642e83d0c80d9af))\n- **runtime-dom:** support passing initial props to custom element constructor ([5b76843](https://github.com/vuejs/core/commit/5b76843b693d6477ae44b4bd238c2c892d8f4c77))\n- **runtime-dom:** support specifying shadow dom styles in defineCustomElement ([a7fa4ac](https://github.com/vuejs/core/commit/a7fa4ac28afb73be00503be87f35e8724fe25443))\n\n# [3.2.0-beta.4](https://github.com/vuejs/core/compare/v3.2.0-beta.3...v3.2.0-beta.4) (2021-07-21)\n\n### Bug Fixes\n\n- **runtime-core:** ensure setupContext.attrs reactivity when used in child slots ([8560005](https://github.com/vuejs/core/commit/85600056015fcf5c922dc0b5b07aa03a5ba53245)), closes [#4161](https://github.com/vuejs/core/issues/4161)\n- **runtime-dom:** defer setting value ([ff0c810](https://github.com/vuejs/core/commit/ff0c810300f7182f717f130fe5e382d9c0c99838)), closes [#2325](https://github.com/vuejs/core/issues/2325) [#4024](https://github.com/vuejs/core/issues/4024)\n\n### Performance Improvements\n\n- skip patch on same vnode ([d13774b](https://github.com/vuejs/core/commit/d13774b881b297f2cd1a8d3193183d241dee625b))\n\n# [3.2.0-beta.3](https://github.com/vuejs/core/compare/v3.2.0-beta.2...v3.2.0-beta.3) (2021-07-20)\n\n### Bug Fixes\n\n- **reactivity:** revert computed scheduler change ([33c2fbf](https://github.com/vuejs/core/commit/33c2fbfdc80c6f17c7e8435b7a152a4d9ed5c6ed)), closes [#4157](https://github.com/vuejs/core/issues/4157)\n- **runtime-core:** fix v-bind class/style merging regression ([2bdee50](https://github.com/vuejs/core/commit/2bdee50a598456392541a8a4b451501e5df2d363)), closes [#4155](https://github.com/vuejs/core/issues/4155)\n- **sfc-playground:** Transform named default exports without altering scope ([#4154](https://github.com/vuejs/core/issues/4154)) ([acb2a4d](https://github.com/vuejs/core/commit/acb2a4d285bfdee6437970b3dc9435abfe1c4ddf))\n- **watch:** ensure watchers respect detached scope ([bc7f976](https://github.com/vuejs/core/commit/bc7f9767f502b808d1c74e2cafaafbf8aa568045)), closes [#4158](https://github.com/vuejs/core/issues/4158)\n\n### Features\n\n- **reactivity:** deferredComputed ([14ca881](https://github.com/vuejs/core/commit/14ca881a1ba6ad887d5ffc6ce3b7f8461252afee))\n- **runtime-core:** watchSyncEffect ([d87d059](https://github.com/vuejs/core/commit/d87d059ac120ed0496f85474344ef76e40fa9bc7))\n\n# [3.2.0-beta.2](https://github.com/vuejs/core/compare/v3.2.0-beta.1...v3.2.0-beta.2) (2021-07-19)\n\n### Bug Fixes\n\n- **compiler-core:** fix self-closing tags with v-pre ([a21ca3d](https://github.com/vuejs/core/commit/a21ca3dccc6a0c3822d15b6b2b1d22a2d1a4dd67))\n- **compiler-sfc:** defineProps infer TSParenthesizedType ([#4147](https://github.com/vuejs/core/issues/4147)) ([f7607d3](https://github.com/vuejs/core/commit/f7607d3a15683745b21585baa18cf2871447580e))\n- **compiler-sfc:** expose correct range for empty blocks ([b274b08](https://github.com/vuejs/core/commit/b274b08f5ff56d153d3dd46fa740dd6b156bf26f))\n- **compiler-sfc:** fix whitespace preservation when block contains single self-closing tag ([ec6abe8](https://github.com/vuejs/core/commit/ec6abe8d5e0c85e9c884e9c2525d5181213a8e64))\n- **compiler-sfc:** support const enum ([93a950d](https://github.com/vuejs/core/commit/93a950d60d347321df4196d22f64c4810840a3bb))\n- **reactivity:** computed should not trigger scheduler if stopped ([6eb47f0](https://github.com/vuejs/core/commit/6eb47f000a1b54b2419c031979502d2793c5189d)), closes [#4149](https://github.com/vuejs/core/issues/4149)\n- **runtime-core:** fix null type in required + multi-type prop declarations ([bbf6ca9](https://github.com/vuejs/core/commit/bbf6ca9bca942df639ff0357d713413c9a1c4c05)), closes [#4146](https://github.com/vuejs/core/issues/4146) [#4147](https://github.com/vuejs/core/issues/4147)\n- **scheduler:** fix insertion for id-less job ([d810a1a](https://github.com/vuejs/core/commit/d810a1a56943aeba5160b42bc917187e99cdfb8e)), closes [#4148](https://github.com/vuejs/core/issues/4148)\n- **shared:** normalizeStyle should handle strings ([a8c3a8a](https://github.com/vuejs/core/commit/a8c3a8ad61b16a31f6754066838440a59ee9db8b)), closes [#4138](https://github.com/vuejs/core/issues/4138)\n- **ssr:** update initial old value to watch callback in ssr usage ([#4103](https://github.com/vuejs/core/issues/4103)) ([20b6619](https://github.com/vuejs/core/commit/20b6619793702d265fcc3a7c099f5764fa9d8685))\n- **v-model:** properly detect input type=number ([3056e9b](https://github.com/vuejs/core/commit/3056e9b3dcb1ab0bd18227c6fa7bf283f98f6ef6)), closes [#3813](https://github.com/vuejs/core/issues/3813)\n\n### Features\n\n- **compiler:** allow 'comments' option to affect comment inclusion in dev ([#4115](https://github.com/vuejs/core/issues/4115)) ([dd0f9d1](https://github.com/vuejs/core/commit/dd0f9d1ce6b0de59c84d334c7190fa9d2cc17a04)), closes [#3392](https://github.com/vuejs/core/issues/3392) [#3395](https://github.com/vuejs/core/issues/3395)\n- **compiler-sfc:** add ignoreEmpty option for sfc parse method ([8dbecfc](https://github.com/vuejs/core/commit/8dbecfcbb3d597a644d0f263dfd6d7fcfd23a9fb))\n- **types:** map declared emits to onXXX props in inferred prop types ([#3926](https://github.com/vuejs/core/issues/3926)) ([69344ff](https://github.com/vuejs/core/commit/69344ff1ae724beb648c34ede8050b3b70ddf4b7))\n\n### Performance Improvements\n\n- **compiler-sfc:** ignore empty blocks ([#3520](https://github.com/vuejs/core/issues/3520)) ([b771fdb](https://github.com/vuejs/core/commit/b771fdbef9a8dadd4c9cc939cc104f7764e40373))\n\n# [3.2.0-beta.1](https://github.com/vuejs/core/compare/v3.1.5...v3.2.0-beta.1) (2021-07-16)\n\n### Bug Fixes\n\n- **sfc/style-vars:** properly re-apply style vars on component root elements change ([49dc2dd](https://github.com/vuejs/core/commit/49dc2dd1e4a56d0d2ad28003240c99e99ef469e4)), closes [#3894](https://github.com/vuejs/core/issues/3894)\n- ensure customElements API ssr compatibility ([de32cfa](https://github.com/vuejs/core/commit/de32cfa43e94276c60f93ac4c560cb7b84534cfe)), closes [#4129](https://github.com/vuejs/core/issues/4129)\n- **runtime-core:** fix default shapeFlag for fragments ([2a310df](https://github.com/vuejs/core/commit/2a310df7531a693be706a96d4191a5bfbf24692d))\n- ignore .prop/.attr modifiers in ssr ([29732c2](https://github.com/vuejs/core/commit/29732c2c8681cc3e58251c19149ba3a0ce31cdaf))\n\n### Code Refactoring\n\n- remove deprecated scopeId codegen ([f596e00](https://github.com/vuejs/core/commit/f596e008efd97fe8f9b28f536fbb0fd48b9b6333))\n\n### Features\n\n- **sfc:** (experimental) new ref sugar ([562bddb](https://github.com/vuejs/core/commit/562bddb3ce76a0e98e499e199e96fa4271e5d1b4))\n- **sfc:** support namespaced component tags when using `<script setup>` ([e5a4412](https://github.com/vuejs/core/commit/e5a4412764f6db255afe01b8a7e6e40ebf707412))\n- custom element reflection, casting and edge cases ([00f0b3c](https://github.com/vuejs/core/commit/00f0b3c46552626cd7c5ec73ffd0a918c3e1a5fb))\n- remove experimental status of `<script setup>` ([27104ea](https://github.com/vuejs/core/commit/27104eaaf0f929a4c08b53877b495c5813157232))\n- support v-bind .prop & .attr modifiers ([1c7d737](https://github.com/vuejs/core/commit/1c7d737cc8ed0384b334d0b3e2dc8ede44906dc4))\n- **runtime-dom:** defineCustomElement ([8610e1c](https://github.com/vuejs/core/commit/8610e1c9e23a4316f76fb35eebbab4ad48566fbf))\n- v-memo ([3b64508](https://github.com/vuejs/core/commit/3b64508e3b2d648e346cbf34e1641f4022be61b6))\n- watchPostEffect ([42ace95](https://github.com/vuejs/core/commit/42ace9577da49477ff189950a83d6eead73d0efe))\n- **reactivity:** new effectScope API ([#2195](https://github.com/vuejs/core/issues/2195)) ([f5617fc](https://github.com/vuejs/core/commit/f5617fc3bb8fd33927b2567622ac4f8b43f9b5d5))\n- **reactivity:** support onTrack/onTrigger debug options for computed ([5cea9a1](https://github.com/vuejs/core/commit/5cea9a1d4e846f60515ef76ebab4800228645601))\n\n### Performance Improvements\n\n- also hoist all-static children array ([b7ea7c1](https://github.com/vuejs/core/commit/b7ea7c148552874e8bce399eec9fbe565efa2f4d))\n- hoist dynamic props lists ([02339b6](https://github.com/vuejs/core/commit/02339b67d8c6fab6ee701a7c4f2773139ed007f5))\n- **reactivity:** avoid triggering re-render if computed value did not change ([ebaac9a](https://github.com/vuejs/core/commit/ebaac9a56d82d266e333d077b6457543d7cab9ae))\n- **reactivity:** improve reactive effect memory usage ([#4001](https://github.com/vuejs/core/issues/4001)) ([87f69fd](https://github.com/vuejs/core/commit/87f69fd0bb67508337fb95cb98135fd5d6ebca7d)), closes [#2345](https://github.com/vuejs/core/issues/2345)\n- **reactivity:** ref-specific track/trigger and miscellaneous optimizations ([#3995](https://github.com/vuejs/core/issues/3995)) ([6431040](https://github.com/vuejs/core/commit/64310405acaccabc24985ade95fb1b5c9c06ef76))\n- **reactivity:** use bitwise dep markers to optimize re-tracking ([#4017](https://github.com/vuejs/core/issues/4017)) ([6cf2377](https://github.com/vuejs/core/commit/6cf2377cd49d24814bdff136bf78c77d50d5b41a))\n- improve VNode creation performance with compiler hints ([#3334](https://github.com/vuejs/core/issues/3334)) ([ceff899](https://github.com/vuejs/core/commit/ceff89905b05381d3d73c480e08c7aff9271b074))\n\n### BREAKING CHANGES\n\n- Output of SFC using `<style scoped>` generated by 3.2+\n  will be incompatible w/ runtime <3.2.\n"
  },
  {
    "path": "changelogs/CHANGELOG-3.3.md",
    "content": "## [3.3.13](https://github.com/vuejs/core/compare/v3.3.12...v3.3.13) (2023-12-19)\n\n\n### Bug Fixes\n\n* **compiler-core:** fix v-on with modifiers on inline expression of undefined ([#9866](https://github.com/vuejs/core/issues/9866)) ([bae79dd](https://github.com/vuejs/core/commit/bae79ddf8564a2da4a5365cfeb8d811990f42335)), closes [#9865](https://github.com/vuejs/core/issues/9865)\n* **runtime-dom:** cache event handlers by key/modifiers ([#9851](https://github.com/vuejs/core/issues/9851)) ([04d2c05](https://github.com/vuejs/core/commit/04d2c05054c26b02fbc1d84839b0ed5cd36455b6)), closes [#9849](https://github.com/vuejs/core/issues/9849)\n* **types:** extract properties from extended collections ([#9854](https://github.com/vuejs/core/issues/9854)) ([24b1c1d](https://github.com/vuejs/core/commit/24b1c1dd57fd55d998aa231a147500e010b10219)), closes [#9852](https://github.com/vuejs/core/issues/9852)\n\n\n\n## [3.3.12](https://github.com/vuejs/core/compare/v3.3.11...v3.3.12) (2023-12-16)\n\n\n### Bug Fixes\n\n* **hydration:** handle appear transition before patch props ([#9837](https://github.com/vuejs/core/issues/9837)) ([e70f4c4](https://github.com/vuejs/core/commit/e70f4c47c553b6e16d8fad70743271ca23802fe7)), closes [#9832](https://github.com/vuejs/core/issues/9832)\n* **sfc/cssVars:** fix loss of CSS v-bind variables when setting inline style with string value ([#9824](https://github.com/vuejs/core/issues/9824)) ([0a387df](https://github.com/vuejs/core/commit/0a387dfb1d04afb6eae4296b6da76dfdaca77af4)), closes [#9821](https://github.com/vuejs/core/issues/9821)\n* **ssr:** fix suspense hydration of fallback content ([#7188](https://github.com/vuejs/core/issues/7188)) ([60415b5](https://github.com/vuejs/core/commit/60415b5d67df55f1fd6b176615299c08640fa142))\n* **types:** add `xmlns:xlink` to `SVGAttributes` ([#9300](https://github.com/vuejs/core/issues/9300)) ([0d61b42](https://github.com/vuejs/core/commit/0d61b429ecf63591d31e09702058fa4c7132e1a7)), closes [#9299](https://github.com/vuejs/core/issues/9299)\n* **types:** fix `shallowRef` type error ([#9839](https://github.com/vuejs/core/issues/9839)) ([9a57158](https://github.com/vuejs/core/commit/9a571582b53220270e498d8712ea59312c0bef3a))\n* **types:** support for generic keyof slots ([#8374](https://github.com/vuejs/core/issues/8374)) ([213eba4](https://github.com/vuejs/core/commit/213eba479ce080efc1053fe636f6be4a4c889b44))\n\n\n\n## [3.3.11](https://github.com/vuejs/core/compare/v3.3.10...v3.3.11) (2023-12-08)\n\n\n### Bug Fixes\n\n* **custom-element:** correctly handle number type props in prod ([#8989](https://github.com/vuejs/core/issues/8989)) ([d74d364](https://github.com/vuejs/core/commit/d74d364d62db8e48881af6b5a75ce4fb5f36cc35))\n* **reactivity:** fix mutation on user proxy of reactive Array ([6ecbd5c](https://github.com/vuejs/core/commit/6ecbd5ce2a7f59314a8326a1d193874b87f4d8c8)), closes [#9742](https://github.com/vuejs/core/issues/9742) [#9751](https://github.com/vuejs/core/issues/9751) [#9750](https://github.com/vuejs/core/issues/9750)\n* **runtime-dom:** fix width and height prop check condition ([5b00286](https://github.com/vuejs/core/commit/5b002869c533220706f9788b496b8ca8d8e98609)), closes [#9762](https://github.com/vuejs/core/issues/9762)\n* **shared:** handle Map with symbol keys in toDisplayString ([#9731](https://github.com/vuejs/core/issues/9731)) ([364821d](https://github.com/vuejs/core/commit/364821d6bdb1775e2f55a69bcfb9f40f7acf1506)), closes [#9727](https://github.com/vuejs/core/issues/9727)\n* **shared:** handle more Symbol cases in toDisplayString ([983d45d](https://github.com/vuejs/core/commit/983d45d4f8eb766b5a16b7ea93b86d3c51618fa6))\n* **Suspense:** properly get anchor when mount fallback vnode ([#9770](https://github.com/vuejs/core/issues/9770)) ([b700328](https://github.com/vuejs/core/commit/b700328342e17dc16b19316c2e134a26107139d2)), closes [#9769](https://github.com/vuejs/core/issues/9769)\n* **types:** ref() return type should not be any when initial value is any ([#9768](https://github.com/vuejs/core/issues/9768)) ([cdac121](https://github.com/vuejs/core/commit/cdac12161ec27b45ded48854c3d749664b6d4a6d))\n* **watch:** should not fire pre watcher on child component unmount ([#7181](https://github.com/vuejs/core/issues/7181)) ([6784f0b](https://github.com/vuejs/core/commit/6784f0b1f8501746ea70d87d18ed63a62cf6b76d)), closes [#7030](https://github.com/vuejs/core/issues/7030)\n\n\n\n## [3.3.10](https://github.com/vuejs/core/compare/v3.3.9...v3.3.10) (2023-12-04)\n\n\n### Bug Fixes\n\n* **app:** prevent template from being cached between apps with different options ([#9724](https://github.com/vuejs/core/issues/9724)) ([ec71585](https://github.com/vuejs/core/commit/ec715854ca12520b2afc9e9b3981cbae05ae5206)), closes [#9618](https://github.com/vuejs/core/issues/9618)\n* **compiler-sfc:** avoid passing forEach index to genMap ([f12db7f](https://github.com/vuejs/core/commit/f12db7fb564a534cef2e5805cc9f54afe5d72fbf))\n* **compiler-sfc:** deindent pug/jade templates ([6345197](https://github.com/vuejs/core/commit/634519720a21fb5a6871454e1cadad7053a568b8)), closes [#3231](https://github.com/vuejs/core/issues/3231) [#3842](https://github.com/vuejs/core/issues/3842) [#7723](https://github.com/vuejs/core/issues/7723)\n* **compiler-sfc:** fix :where and :is selector in scoped mode with multiple selectors ([#9735](https://github.com/vuejs/core/issues/9735)) ([c3e2c55](https://github.com/vuejs/core/commit/c3e2c556b532656b50b8ab5cd2d9eabc26622d63)), closes [#9707](https://github.com/vuejs/core/issues/9707)\n* **compiler-sfc:** generate more treeshaking friendly code ([#9507](https://github.com/vuejs/core/issues/9507)) ([8d74ca0](https://github.com/vuejs/core/commit/8d74ca0e6fa2738ca6854b7e879ff59419f948c7)), closes [#9500](https://github.com/vuejs/core/issues/9500)\n* **compiler-sfc:** support inferring generic types ([#8511](https://github.com/vuejs/core/issues/8511)) ([eb5e307](https://github.com/vuejs/core/commit/eb5e307c0be62002e62c4c800d0dfacb39b0d4ca)), closes [#8482](https://github.com/vuejs/core/issues/8482)\n* **compiler-sfc:** support resolving components from props ([#8785](https://github.com/vuejs/core/issues/8785)) ([7cbcee3](https://github.com/vuejs/core/commit/7cbcee3d831241a8bd3588ae92d3f27e3641e25f))\n* **compiler-sfc:** throw error when failing to load TS during type resolution ([#8883](https://github.com/vuejs/core/issues/8883)) ([4936d2e](https://github.com/vuejs/core/commit/4936d2e11a8d0ca3704bfe408548cb26bb3fd5e9))\n* **cssVars:** cssVar names should be double-escaped when generating code for ssr ([#8824](https://github.com/vuejs/core/issues/8824)) ([5199a12](https://github.com/vuejs/core/commit/5199a12f8855cd06f24bf355708b5a2134f63176)), closes [#7823](https://github.com/vuejs/core/issues/7823)\n* **deps:** update compiler to ^7.23.4 ([#9681](https://github.com/vuejs/core/issues/9681)) ([31f6ebc](https://github.com/vuejs/core/commit/31f6ebc4df84490ed29fb75e7bf4259200eb51f0))\n* **runtime-core:** Suspense get anchor properly in Transition ([#9309](https://github.com/vuejs/core/issues/9309)) ([65f3fe2](https://github.com/vuejs/core/commit/65f3fe273127a8b68e1222fbb306d28d85f01757)), closes [#8105](https://github.com/vuejs/core/issues/8105)\n* **runtime-dom:** set width/height with units as attribute ([#8781](https://github.com/vuejs/core/issues/8781)) ([bfc1838](https://github.com/vuejs/core/commit/bfc1838f31199de3f189198a3c234fa7bae91386))\n* **ssr:** avoid computed being accidentally cached before server render ([#9688](https://github.com/vuejs/core/issues/9688)) ([30d5d93](https://github.com/vuejs/core/commit/30d5d93a92b2154406ec04f8aca6b217fa01177c)), closes [#5300](https://github.com/vuejs/core/issues/5300)\n* **types:** expose emits as props in functional components ([#9234](https://github.com/vuejs/core/issues/9234)) ([887e54c](https://github.com/vuejs/core/commit/887e54c347ea9eac4c721b5e2288f054873d1d30))\n* **types:** fix reactive collection types ([#8960](https://github.com/vuejs/core/issues/8960)) ([ad27473](https://github.com/vuejs/core/commit/ad274737015c36906d76f3189203093fa3a2e4e7)), closes [#8904](https://github.com/vuejs/core/issues/8904)\n* **types:** improve return type withKeys and withModifiers ([#9734](https://github.com/vuejs/core/issues/9734)) ([43c3cfd](https://github.com/vuejs/core/commit/43c3cfdec5ae5d70fa2a21e857abc2d73f1a0d07))\n\n\n### Performance Improvements\n\n* optimize on* prop check ([38aaa8c](https://github.com/vuejs/core/commit/38aaa8c88648c54fe2616ad9c0961288092fcb44))\n* **runtime-dom:** cache modifier wrapper functions ([da4a4fb](https://github.com/vuejs/core/commit/da4a4fb5e8eee3c6d31f24ebd79a9d0feca56cb2)), closes [#8882](https://github.com/vuejs/core/issues/8882)\n* **v-on:** constant handlers with modifiers should not be treated as dynamic ([4d94ebf](https://github.com/vuejs/core/commit/4d94ebfe75174b340d2b794e699cad1add3600a9))\n\n\n\n## [3.3.9](https://github.com/vuejs/core/compare/v3.3.8...v3.3.9) (2023-11-25)\n\n\n### Bug Fixes\n\n* **compiler-core:** avoid rewriting scope variables in inline for loops ([#7245](https://github.com/vuejs/core/issues/7245)) ([a2d810e](https://github.com/vuejs/core/commit/a2d810eb40cef631f61991ca68b426ee9546aba0)), closes [#7238](https://github.com/vuejs/core/issues/7238)\n* **compiler-core:** fix `resolveParserPlugins` decorators check ([#9566](https://github.com/vuejs/core/issues/9566)) ([9d0eba9](https://github.com/vuejs/core/commit/9d0eba916f3bf6fb5c03222400edae1a2db7444f)), closes [#9560](https://github.com/vuejs/core/issues/9560)\n* **compiler-sfc:** consistently escape type-only prop names ([#8654](https://github.com/vuejs/core/issues/8654)) ([3e08d24](https://github.com/vuejs/core/commit/3e08d246dfd8523c54fb8e7a4a6fd5506ffb1bcc)), closes [#8635](https://github.com/vuejs/core/issues/8635) [#8910](https://github.com/vuejs/core/issues/8910) [vitejs/vite-plugin-vue#184](https://github.com/vitejs/vite-plugin-vue/issues/184)\n* **compiler-sfc:** malformed filename on windows using path.posix.join() ([#9478](https://github.com/vuejs/core/issues/9478)) ([f18a174](https://github.com/vuejs/core/commit/f18a174979626b3429db93c5d5b7ae5448917c70)), closes [#8671](https://github.com/vuejs/core/issues/8671) [#9583](https://github.com/vuejs/core/issues/9583) [#9446](https://github.com/vuejs/core/issues/9446) [#9473](https://github.com/vuejs/core/issues/9473)\n* **compiler-sfc:** support `:is` and `:where` selector in scoped css rewrite ([#8929](https://github.com/vuejs/core/issues/8929)) ([3227e50](https://github.com/vuejs/core/commit/3227e50b32105f8893f7dff2f29278c5b3a9f621))\n* **compiler-sfc:** support resolve extends interface for defineEmits ([#8470](https://github.com/vuejs/core/issues/8470)) ([9e1b74b](https://github.com/vuejs/core/commit/9e1b74bcd5fa4151f5d1bc02c69fbbfa4762f577)), closes [#8465](https://github.com/vuejs/core/issues/8465)\n* **hmr/transition:** fix kept-alive component inside transition disappearing after hmr ([#7126](https://github.com/vuejs/core/issues/7126)) ([d11e978](https://github.com/vuejs/core/commit/d11e978fc98dcc83526c167e603b8308f317f786)), closes [#7121](https://github.com/vuejs/core/issues/7121)\n* **hydration:** force hydration for v-bind with .prop modifier ([364f319](https://github.com/vuejs/core/commit/364f319d214226770d97c98d8fcada80c9e8dde3)), closes [#7490](https://github.com/vuejs/core/issues/7490)\n* **hydration:** properly hydrate indeterminate prop ([34b5a5d](https://github.com/vuejs/core/commit/34b5a5da4ae9c9faccac237acd7acc8e7e017571)), closes [#7476](https://github.com/vuejs/core/issues/7476)\n* **reactivity:** clear method on readonly collections should return undefined ([#7316](https://github.com/vuejs/core/issues/7316)) ([657476d](https://github.com/vuejs/core/commit/657476dcdb964be4fbb1277c215c073f3275728e))\n* **reactivity:** onCleanup also needs to be cleaned ([#8655](https://github.com/vuejs/core/issues/8655)) ([73fd810](https://github.com/vuejs/core/commit/73fd810eebdd383a2b4629f67736c4db1f428abd)), closes [#5151](https://github.com/vuejs/core/issues/5151) [#7695](https://github.com/vuejs/core/issues/7695)\n* **ssr:** hydration `__vnode` missing for devtools ([#9328](https://github.com/vuejs/core/issues/9328)) ([5156ac5](https://github.com/vuejs/core/commit/5156ac5b38cfa80d3db26f2c9bf40cb22a7521cb))\n* **types:** allow falsy value types in `StyleValue` ([#7954](https://github.com/vuejs/core/issues/7954)) ([17aa92b](https://github.com/vuejs/core/commit/17aa92b79b31d8bb8b5873ddc599420cb9806db8)), closes [#7955](https://github.com/vuejs/core/issues/7955)\n* **types:** defineCustomElement using defineComponent return type with emits ([#7937](https://github.com/vuejs/core/issues/7937)) ([5d932a8](https://github.com/vuejs/core/commit/5d932a8e6d14343c9d7fc7c2ecb58ac618b2f938)), closes [#7782](https://github.com/vuejs/core/issues/7782)\n* **types:** fix `unref` and `toValue` when input union type contains ComputedRef ([#8748](https://github.com/vuejs/core/issues/8748)) ([176d476](https://github.com/vuejs/core/commit/176d47671271b1abc21b1508e9a493c7efca6451)), closes [#8747](https://github.com/vuejs/core/issues/8747) [#8857](https://github.com/vuejs/core/issues/8857)\n* **types:** fix instance type when props type is incompatible with setup returned type ([#7338](https://github.com/vuejs/core/issues/7338)) ([0e1e8f9](https://github.com/vuejs/core/commit/0e1e8f919e5a74cdaadf9c80ee135088b25e7fa3)), closes [#5885](https://github.com/vuejs/core/issues/5885)\n* **types:** fix shallowRef return type with union value type ([#7853](https://github.com/vuejs/core/issues/7853)) ([7c44800](https://github.com/vuejs/core/commit/7c448000b0def910c2cfabfdf7ff20a3d6bc844f)), closes [#7852](https://github.com/vuejs/core/issues/7852)\n* **types:** more precise types for class bindings ([#8012](https://github.com/vuejs/core/issues/8012)) ([46e3374](https://github.com/vuejs/core/commit/46e33744c890bd49482c5e5c5cdea44e00ec84d5))\n* **types:** remove optional properties from defineProps return type ([#6421](https://github.com/vuejs/core/issues/6421)) ([94c049d](https://github.com/vuejs/core/commit/94c049d930d922069e38ea8700d7ff0970f71e61)), closes [#6420](https://github.com/vuejs/core/issues/6420)\n* **types:** return type of withDefaults should be readonly ([#8601](https://github.com/vuejs/core/issues/8601)) ([f15debc](https://github.com/vuejs/core/commit/f15debc01acb22d23f5acee97e6f02db88cef11a))\n* **types:** revert class type restrictions ([5d077c8](https://github.com/vuejs/core/commit/5d077c8754cc14f85d2d6d386df70cf8c0d93842)), closes [#8012](https://github.com/vuejs/core/issues/8012)\n* **types:** update jsx type definitions ([#8607](https://github.com/vuejs/core/issues/8607)) ([58e2a94](https://github.com/vuejs/core/commit/58e2a94871ae06a909c5f8bad07fb401193e6a38))\n* **types:** widen ClassValue type ([2424013](https://github.com/vuejs/core/commit/242401305944422d0c361b16101a4d18908927af))\n* **v-model:** avoid overwriting number input with same value ([#7004](https://github.com/vuejs/core/issues/7004)) ([40f4b77](https://github.com/vuejs/core/commit/40f4b77bb570868cb6e47791078767797e465989)), closes [#7003](https://github.com/vuejs/core/issues/7003)\n* **v-model:** unnecessary value binding error should apply to dynamic instead of static binding ([2859b65](https://github.com/vuejs/core/commit/2859b653c9a22460e60233cac10fe139e359b046)), closes [#3596](https://github.com/vuejs/core/issues/3596)\n\n\n\n## [3.3.8](https://github.com/vuejs/core/compare/v3.3.7...v3.3.8) (2023-11-06)\n\n\n### Bug Fixes\n\n* **compile-sfc:** support `Error` type in `defineProps` ([#5955](https://github.com/vuejs/core/issues/5955)) ([a989345](https://github.com/vuejs/core/commit/a9893458ec519aae442e1b99e64e6d74685cd22c))\n* **compiler-core:** known global should be shadowed by local variables in expression rewrite ([#9492](https://github.com/vuejs/core/issues/9492)) ([a75d1c5](https://github.com/vuejs/core/commit/a75d1c5c6242e91a73cc5ba01e6da620dea0b3d9)), closes [#9482](https://github.com/vuejs/core/issues/9482)\n* **compiler-sfc:** fix dynamic directive arguments usage check for slots ([#9495](https://github.com/vuejs/core/issues/9495)) ([b39fa1f](https://github.com/vuejs/core/commit/b39fa1f8157647859331ce439c42ae016a49b415)), closes [#9493](https://github.com/vuejs/core/issues/9493)\n* **deps:** update dependency @vue/repl to ^2.6.2 ([#9536](https://github.com/vuejs/core/issues/9536)) ([5cef325](https://github.com/vuejs/core/commit/5cef325f41e3b38657c72fa1a38dedeee1c7a60a))\n* **deps:** update dependency @vue/repl to ^2.6.3 ([#9540](https://github.com/vuejs/core/issues/9540)) ([176d590](https://github.com/vuejs/core/commit/176d59058c9aecffe9da4d4311e98496684f06d4))\n* **hydration:** fix tagName access error on comment/text node hydration mismatch ([dd8a0cf](https://github.com/vuejs/core/commit/dd8a0cf5dcde13d2cbd899262a0e07f16e14e489)), closes [#9531](https://github.com/vuejs/core/issues/9531)\n* **types:** avoid exposing lru-cache types in generated dts ([462aeb3](https://github.com/vuejs/core/commit/462aeb3b600765e219ded2ee9a0ed1e74df61de0)), closes [#9521](https://github.com/vuejs/core/issues/9521)\n* **warn:** avoid warning on empty children with Suspense ([#3962](https://github.com/vuejs/core/issues/3962)) ([405f345](https://github.com/vuejs/core/commit/405f34587a63a5f1e3d147b9848219ea98acc22d))\n\n\n\n## [3.3.7](https://github.com/vuejs/core/compare/v3.3.6...v3.3.7) (2023-10-24)\n\n\n### Bug Fixes\n\n* **compiler-sfc:** avoid gen useCssVars when targeting SSR ([#6979](https://github.com/vuejs/core/issues/6979)) ([c568778](https://github.com/vuejs/core/commit/c568778ea3265d8e57f788b00864c9509bf88a4e)), closes [#6926](https://github.com/vuejs/core/issues/6926)\n* **compiler-ssr:**  proper scope analysis for ssr vnode slot fallback ([#7184](https://github.com/vuejs/core/issues/7184)) ([e09c26b](https://github.com/vuejs/core/commit/e09c26bc9bc4394c2c2d928806d382515c2676f3)), closes [#7095](https://github.com/vuejs/core/issues/7095)\n* correctly resolve types from relative paths on Windows ([#9446](https://github.com/vuejs/core/issues/9446)) ([089d36d](https://github.com/vuejs/core/commit/089d36d167dc7834065b03ca689f9b6a44eead8a)), closes [#8671](https://github.com/vuejs/core/issues/8671)\n* **hmr:** fix hmr error for hoisted children array in v-for ([7334376](https://github.com/vuejs/core/commit/733437691f70ebca8dd6cc3bc8356f5b57d4d5d8)), closes [#6978](https://github.com/vuejs/core/issues/6978) [#7114](https://github.com/vuejs/core/issues/7114)\n* **reactivity:** assigning array.length while observing a symbol property ([#7568](https://github.com/vuejs/core/issues/7568)) ([e9e2778](https://github.com/vuejs/core/commit/e9e2778e9ec5cca07c1df5f0c9b7b3595a1a3244))\n* **scheduler:** ensure jobs are in the correct order ([#7748](https://github.com/vuejs/core/issues/7748)) ([a8f6638](https://github.com/vuejs/core/commit/a8f663867b8cd2736b82204bc58756ef02441276)), closes [#7576](https://github.com/vuejs/core/issues/7576)\n* **ssr:** fix hydration mismatch for disabled teleport at component root ([#9399](https://github.com/vuejs/core/issues/9399)) ([d8990fc](https://github.com/vuejs/core/commit/d8990fc6182d1c2cf0a8eab7b35a9d04df668507)), closes [#6152](https://github.com/vuejs/core/issues/6152)\n* **Suspense:** calling hooks before the transition finishes ([#9388](https://github.com/vuejs/core/issues/9388)) ([00de3e6](https://github.com/vuejs/core/commit/00de3e61ed7a55e7d6c2e1987551d66ad0f909ff)), closes [#5844](https://github.com/vuejs/core/issues/5844) [#5952](https://github.com/vuejs/core/issues/5952)\n* **transition/ssr:** make transition appear work with SSR ([#8859](https://github.com/vuejs/core/issues/8859)) ([5ea8a8a](https://github.com/vuejs/core/commit/5ea8a8a4fab4e19a71e123e4d27d051f5e927172)), closes [#6951](https://github.com/vuejs/core/issues/6951)\n* **types:** fix ComponentCustomProps augmentation ([#9468](https://github.com/vuejs/core/issues/9468)) ([7374e93](https://github.com/vuejs/core/commit/7374e93f0281f273b90ab5a6724cc47332a01d6c)), closes [#8376](https://github.com/vuejs/core/issues/8376)\n* **types:** improve `h` overload to support union of string and component ([#5432](https://github.com/vuejs/core/issues/5432)) ([16ecb44](https://github.com/vuejs/core/commit/16ecb44c89cd8299a3b8de33cccc2e2cc36f065b)), closes [#5431](https://github.com/vuejs/core/issues/5431)\n\n\n\n## [3.3.6](https://github.com/vuejs/core/compare/v3.3.5...v3.3.6) (2023-10-20)\n\n\n### Bug Fixes\n\n* **compiler-sfc:** model name conflict ([#8798](https://github.com/vuejs/core/issues/8798)) ([df81da8](https://github.com/vuejs/core/commit/df81da8be97c8a1366563c7e3e01076ef02eb8f7))\n* **compiler-sfc:** support asset paths containing spaces ([#8752](https://github.com/vuejs/core/issues/8752)) ([36c99a9](https://github.com/vuejs/core/commit/36c99a9c6bb6bc306be054c3c8a85ff8ce50605a))\n* **compiler-ssr:** fix missing scopeId on server-rendered TransitionGroup ([#7557](https://github.com/vuejs/core/issues/7557)) ([61c1357](https://github.com/vuejs/core/commit/61c135742795aa5e3189a79c7dec6afa21bbc8d9)), closes [#7554](https://github.com/vuejs/core/issues/7554)\n* **compiler-ssr:** fix ssr compile error for select with non-option children ([#9442](https://github.com/vuejs/core/issues/9442)) ([cdb2e72](https://github.com/vuejs/core/commit/cdb2e725e7ea297f1f4180fb04889a3b757bc84e)), closes [#9440](https://github.com/vuejs/core/issues/9440)\n* **runtime-core:** delete stale slots which are present but undefined ([#6484](https://github.com/vuejs/core/issues/6484)) ([75b8722](https://github.com/vuejs/core/commit/75b872213574cb37e2c9e8a15f65613f867ca9a6)), closes [#9109](https://github.com/vuejs/core/issues/9109)\n* **runtime-core:** fix error when using cssvars with disabled teleport ([#7341](https://github.com/vuejs/core/issues/7341)) ([8f0472c](https://github.com/vuejs/core/commit/8f0472c9abedb337dc256143b69d8ab8759dbf5c)), closes [#7342](https://github.com/vuejs/core/issues/7342)\n* **teleport:** ensure descendent component would be unmounted correctly ([#6529](https://github.com/vuejs/core/issues/6529)) ([4162311](https://github.com/vuejs/core/commit/4162311efdb0db5ca458542e1604b19efa2fae0e)), closes [#6347](https://github.com/vuejs/core/issues/6347)\n* **types:** support contenteditable=\"plaintext-only\" ([#8796](https://github.com/vuejs/core/issues/8796)) ([26ca89e](https://github.com/vuejs/core/commit/26ca89e5cf734fbef81e182050d2a215ec8a437b))\n\n\n### Performance Improvements\n\n* replace Map/Set with WeakMap/WeakSet ([#8549](https://github.com/vuejs/core/issues/8549)) ([712f96d](https://github.com/vuejs/core/commit/712f96d6ac4d3d984732cba448cb84624daba850))\n\n\n\n## [3.3.5](https://github.com/vuejs/core/compare/v3.3.4...v3.3.5) (2023-10-20)\n\n\n### Bug Fixes\n\n* add isGloballyWhitelisted back, but deprecated ([#8556](https://github.com/vuejs/core/issues/8556)) ([63dfe8e](https://github.com/vuejs/core/commit/63dfe8eab499979bcc2f7829e82464e13899c895)), closes [#8416](https://github.com/vuejs/core/issues/8416)\n* **build:** disable useDefineForClassFields in esbuild ([#9252](https://github.com/vuejs/core/issues/9252)) ([6d14fa8](https://github.com/vuejs/core/commit/6d14fa88e85d4c9e264be394ddb37a54ca6738a8))\n* **compat:** return value of vue compat set() ([#9377](https://github.com/vuejs/core/issues/9377)) ([e3c2d69](https://github.com/vuejs/core/commit/e3c2d699f694d9500ddee78571172a24f0e3b17a))\n* **compiler-sfc:** don't hoist props and emit ([#8535](https://github.com/vuejs/core/issues/8535)) ([24db951](https://github.com/vuejs/core/commit/24db9516d8b4857182ec1a3af86cb7346691679b)), closes [#7805](https://github.com/vuejs/core/issues/7805) [#7812](https://github.com/vuejs/core/issues/7812)\n* **compiler-sfc:** don't registerTS when bundling for browsers ([#8582](https://github.com/vuejs/core/issues/8582)) ([6f45f76](https://github.com/vuejs/core/commit/6f45f76df2c43796b35067ef8f8b9a7bca454040))\n* **compiler-sfc:** fix using imported ref as template ref during dev ([#7593](https://github.com/vuejs/core/issues/7593)) ([776ebf2](https://github.com/vuejs/core/commit/776ebf25b2e7570e78ac1c148fc45c823c21a542)), closes [#7567](https://github.com/vuejs/core/issues/7567)\n* **compiler-sfc:** handle dynamic directive arguments in template usage check ([#8538](https://github.com/vuejs/core/issues/8538)) ([e404a69](https://github.com/vuejs/core/commit/e404a699f48ae5c5a5da947f42679343192158c7)), closes [#8537](https://github.com/vuejs/core/issues/8537)\n* **compiler-sfc:** ignore style v-bind in double slash comments ([#5409](https://github.com/vuejs/core/issues/5409)) ([381b497](https://github.com/vuejs/core/commit/381b4977af25ba5392704f72ec6b3f2394d87ae7))\n* **compiler-sfc:** pass options directly to stylus ([#3848](https://github.com/vuejs/core/issues/3848)) ([d6446a6](https://github.com/vuejs/core/commit/d6446a6d40774b79045a9ddba7b5fd5201d51450))\n* **compiler-sfc:** support resolve multiple re-export /w same source type name ([#8365](https://github.com/vuejs/core/issues/8365)) ([4fa8da8](https://github.com/vuejs/core/commit/4fa8da8576717c619e1e8c04d19038488c75fbea)), closes [#8364](https://github.com/vuejs/core/issues/8364)\n* **compiler-sfc:** typo in experimental feature warnings ([#8513](https://github.com/vuejs/core/issues/8513)) ([fd1a3f9](https://github.com/vuejs/core/commit/fd1a3f95990d7c372fa1c0c40c55caca761a33a4))\n* **deps:** update dependency monaco-editor to ^0.44.0 ([#9237](https://github.com/vuejs/core/issues/9237)) ([8611874](https://github.com/vuejs/core/commit/8611874e09a827b6491173836c8942284d5de22c))\n* **deps:** update playground ([#9154](https://github.com/vuejs/core/issues/9154)) ([c8566a2](https://github.com/vuejs/core/commit/c8566a22b7cf37e6aefab7bad7b97ce2db9fae4c))\n* **playground:** fix github button style ([#7722](https://github.com/vuejs/core/issues/7722)) ([5ee992c](https://github.com/vuejs/core/commit/5ee992cfeabc6c4b871980c6057d0ac7140ad2fa))\n* **runtime-core:** swap client/server debug labels ([#9089](https://github.com/vuejs/core/issues/9089)) ([8f311c6](https://github.com/vuejs/core/commit/8f311c6f823f6776ca1c49bfbbbf8c7d9dea9cf1))\n* **ssr:** render correct initial selected state for select with v-model ([#7432](https://github.com/vuejs/core/issues/7432)) ([201c46d](https://github.com/vuejs/core/commit/201c46df07a38f3c2b73f384e8e6846dc62f224e)), closes [#7392](https://github.com/vuejs/core/issues/7392)\n* **ssr:** reset current instance if setting up options component errors ([#7743](https://github.com/vuejs/core/issues/7743)) ([020851e](https://github.com/vuejs/core/commit/020851e57d9a9f727c6ea07e9c1575430af02b73)), closes [#7733](https://github.com/vuejs/core/issues/7733)\n* **teleport:** handle target change while disabled ([#7837](https://github.com/vuejs/core/issues/7837)) ([140a89b](https://github.com/vuejs/core/commit/140a89b833bceed60838182b875d2953c70af114)), closes [#7835](https://github.com/vuejs/core/issues/7835)\n* **transition:** handle possible auto value for transition/animation durations ([96c76fa](https://github.com/vuejs/core/commit/96c76facb7de37fc241ccd55e121fd60a49a1452)), closes [#8409](https://github.com/vuejs/core/issues/8409)\n* **types/jsx:** add `inert` attribute and missing `hidden` values ([#8090](https://github.com/vuejs/core/issues/8090)) ([ceb0732](https://github.com/vuejs/core/commit/ceb0732e0b1bb4c8c505d80e97ff6fc89035fa90))\n* **types/jsx:** add missing loading attr for img element ([#6160](https://github.com/vuejs/core/issues/6160)) ([68d6b43](https://github.com/vuejs/core/commit/68d6b43f7e29b76aab2c6c1882885380a43fa3e3))\n* **types:** correct withDefaults return type for boolean prop with undefined default value ([#8602](https://github.com/vuejs/core/issues/8602)) ([f07cb18](https://github.com/vuejs/core/commit/f07cb18fedf9a446545aadf76bcdfb957c7ebcbd))\n* **types:** ensure nextTick return type reflect correct Promise value ([#8406](https://github.com/vuejs/core/issues/8406)) ([6a22b1f](https://github.com/vuejs/core/commit/6a22b1f6c287b60eda385df8a514335af8e040ea))\n* **types:** support correct types for style on svg elements ([#6322](https://github.com/vuejs/core/issues/6322)) ([364dc53](https://github.com/vuejs/core/commit/364dc53c7cc6f97d812ad175199c698faa92538e))\n\n\n### Performance Improvements\n\n* **compiler-sfc:** lazy require typescript ([d2c3d8b](https://github.com/vuejs/core/commit/d2c3d8b70b2df6e16f053a7ac58e6b04e7b2078f))\n* **custom-element:** cancel `MutationObserver` listener when disconnected ([#8666](https://github.com/vuejs/core/issues/8666)) ([24d98f0](https://github.com/vuejs/core/commit/24d98f03276de5b0fbced5a4c9d61b24e7d9d084))\n* mark `defineComponent` as side-effects-free ([#8512](https://github.com/vuejs/core/issues/8512)) ([438027c](https://github.com/vuejs/core/commit/438027cf9ecb63260f59d3027e0b188717694795))\n\n\n\n## [3.3.4](https://github.com/vuejs/core/compare/v3.3.3...v3.3.4) (2023-05-18)\n\n\n### Bug Fixes\n\n* **build:** ensure correct typing for node esm ([d621d4c](https://github.com/vuejs/core/commit/d621d4c646b2d7b190fbd44ad1fd04512b3de300))\n* **build:** fix __DEV__ flag replacement edge case ([8b7c04b](https://github.com/vuejs/core/commit/8b7c04b18f73aad9a08dd57eba90101b5b2aef28)), closes [#8353](https://github.com/vuejs/core/issues/8353)\n* **compiler-sfc:** handle imported types from default exports ([5aec717](https://github.com/vuejs/core/commit/5aec717a2402652306085f58432ba3ab91848a74)), closes [#8355](https://github.com/vuejs/core/issues/8355)\n\n\n\n## [3.3.3](https://github.com/vuejs/core/compare/v3.3.2...v3.3.3) (2023-05-18)\n\n\n### Bug Fixes\n\n* avoid regex s flag for old browsers ([91f1c62](https://github.com/vuejs/core/commit/91f1c62e6384a8b09f90e7e43b8d347901e529a0)), closes [#8316](https://github.com/vuejs/core/issues/8316)\n* **build:** fix dev flag replacement in esm-builder builds ([#8314](https://github.com/vuejs/core/issues/8314)) ([003836f](https://github.com/vuejs/core/commit/003836f90e1f00ebd04b77ec07ccfa4e649a2ff4)), closes [#8312](https://github.com/vuejs/core/issues/8312)\n* **compiler-sfc:** don't hoist regexp literial ([#8300](https://github.com/vuejs/core/issues/8300)) ([8ec73a3](https://github.com/vuejs/core/commit/8ec73a3aea7a52e9479f107ae5737761166ddae6))\n* **compiler-sfc:** fix props destructing default value type checking with unresolved type ([#8340](https://github.com/vuejs/core/issues/8340)) ([f69dbab](https://github.com/vuejs/core/commit/f69dbabf8794426c3e9ed33ae77dd8ce655eafd2)), closes [#8326](https://github.com/vuejs/core/issues/8326)\n* **compiler-sfc:** fix type import from path aliased vue file ([fab9c72](https://github.com/vuejs/core/commit/fab9c727805c6186c490f99023e8cf5401b0b5a9)), closes [#8348](https://github.com/vuejs/core/issues/8348)\n* **compiler-sfc:** handle ts files with relative imports with .js extension ([b36addd](https://github.com/vuejs/core/commit/b36addd3bde07467e9ff5641bd1c2bdc3085944c)), closes [#8339](https://github.com/vuejs/core/issues/8339)\n* **compiler-sfc:** parses correctly when inline mode is off ([#8337](https://github.com/vuejs/core/issues/8337)) ([ecbd42a](https://github.com/vuejs/core/commit/ecbd42a1444e3c599e464dec002e43d548d99669)), closes [#6088](https://github.com/vuejs/core/issues/6088)\n* **compiler-sfc:** support defineEmits type reference with unions ([#8299](https://github.com/vuejs/core/issues/8299)) ([b133e0f](https://github.com/vuejs/core/commit/b133e0fd97b0b4fabbb43151c19031b8fb47c05b)), closes [#7943](https://github.com/vuejs/core/issues/7943)\n* **types:** support generic usage with withDefaults + defineProps ([#8335](https://github.com/vuejs/core/issues/8335)) ([216f269](https://github.com/vuejs/core/commit/216f26995b63c2df26ca0f39f390fe8d59cdabfa)), closes [#8310](https://github.com/vuejs/core/issues/8310) [#8331](https://github.com/vuejs/core/issues/8331) [#8325](https://github.com/vuejs/core/issues/8325)\n\n\n\n## [3.3.2](https://github.com/vuejs/core/compare/v3.3.1...v3.3.2) (2023-05-12)\n\n\n### Bug Fixes\n\n* **compiler-core:** treat floating point numbers as constants ([8dc8cf8](https://github.com/vuejs/core/commit/8dc8cf852bf8057aa5c4b5670f09e8c28a168b73)), closes [#8295](https://github.com/vuejs/core/issues/8295)\n* **compiler-dom:** do not throw in production on side effect tags ([c454b9d](https://github.com/vuejs/core/commit/c454b9d7f431d57abedb7184d1e4059914c4463f)), closes [#8287](https://github.com/vuejs/core/issues/8287) [#8292](https://github.com/vuejs/core/issues/8292)\n* **compiler-sfc:** fix regression on props destructure when transform is not enabled ([f25bd37](https://github.com/vuejs/core/commit/f25bd37c6707fde19d164d90a38de41168941f4b)), closes [#8289](https://github.com/vuejs/core/issues/8289)\n* **compiler-sfc:** handle prop keys that need escaping ([#7803](https://github.com/vuejs/core/issues/7803)) ([690ef29](https://github.com/vuejs/core/commit/690ef296357c7fc09f66ba9408df548e117f686f)), closes [#8291](https://github.com/vuejs/core/issues/8291)\n* **compiler-sfc:** properly parse d.ts files when resolving types ([aa1e77d](https://github.com/vuejs/core/commit/aa1e77d532b951ea5d3a5e26214a8b0c9c02fb6f)), closes [#8285](https://github.com/vuejs/core/issues/8285)\n* **compiler-sfc:** raise specific warning for failed extends and allow ignoring extends ([8235072](https://github.com/vuejs/core/commit/82350721a408e1f552c613c05971439d6c218d87)), closes [#8286](https://github.com/vuejs/core/issues/8286)\n\n\n\n## [3.3.1](https://github.com/vuejs/core/compare/v3.3.0...v3.3.1) (2023-05-11)\n\n\n### Bug Fixes\n\n* **suspense:** handle nested sync suspense for hydration ([a3f5485](https://github.com/vuejs/core/commit/a3f54857858c8ca0e6b9f12618d151ab255fb040))\n\n\n\n# [3.3.0 Rurouni Kenshin](https://github.com/vuejs/core/compare/v3.3.0-beta.5...v3.3.0) (2023-05-11)\n\n- For a detailed walkthrough of the new features in 3.3, please read the [release blog post](https://blog.vuejs.org/posts/vue-3-3).\n\n- Features and deprecations listed here are aggregated from the beta and alpha releases. For full chronological history, bug fixes, and other minor features, please consult the individual logs of the 3.3 beta and alpha releases.\n\n## Features\n\n* **sfc:** support imported types in SFC macros ([#8083](https://github.com/vuejs/core/pull/8083))\n* **types/slots:** support slot presence / props type checks via `defineSlots` macro and `slots` option ([#7982](https://github.com/vuejs/core/issues/7982)) ([5a2f5d5](https://github.com/vuejs/core/commit/5a2f5d59cffa36a99e6f2feab6b3ba7958b7362f))\n* **sfc:** support more ergonomic defineEmits type syntax ([#7992](https://github.com/vuejs/core/issues/7992)) ([8876dcc](https://github.com/vuejs/core/commit/8876dccf42a7f05375d97cb18c1afdfd0fc51c94))\n* **sfc:** introduce `defineModel` macro and `useModel` helper ([#8018](https://github.com/vuejs/core/issues/8018)) ([14f3d74](https://github.com/vuejs/core/commit/14f3d747a34d45415b0036b274517d70a27ec0d3))\n* **reactivity:** improve support of getter usage in reactivity APIs ([#7997](https://github.com/vuejs/core/issues/7997)) ([59e8284](https://github.com/vuejs/core/commit/59e828448e7f37643cd0eaea924a764e9d314448))\n* **compiler-sfc:** add defineOptions macro ([#5738](https://github.com/vuejs/core/issues/5738)) ([bcf5841](https://github.com/vuejs/core/commit/bcf5841ddecc64d0bdbd56ce1463eb8ebf01bb9d))\n* **types/jsx:** support jsxImportSource, avoid global JSX conflict ([#7958](https://github.com/vuejs/core/issues/7958)) ([d0b7ef3](https://github.com/vuejs/core/commit/d0b7ef3b61d5f83e35e5854b3c2c874e23463102))\n* **dx:** improve readability of displayed types for props ([4c9bfd2](https://github.com/vuejs/core/commit/4c9bfd2b999ce472f7481aae4f9dc5bb9f76628e))\n* **app:** app.runWithContext() ([#7451](https://github.com/vuejs/core/issues/7451)) ([869f3fb](https://github.com/vuejs/core/commit/869f3fb93e61400be4fd925e0850c2b1564749e2))\n* hasInjectionContext() for libraries ([#8111](https://github.com/vuejs/core/issues/8111)) ([5510ce3](https://github.com/vuejs/core/commit/5510ce385abfa151c07a5253cccf4abccabdd01d))\n* allow accessing console in template ([#6508](https://github.com/vuejs/core/issues/6508)) ([fe76224](https://github.com/vuejs/core/commit/fe762247f8035d28d543bc5602ad01b0c258f6d6)), closes [#7939](https://github.com/vuejs/core/issues/7939)\n* **suspense:** introduce suspensible option for `<Suspense>` ([#6736](https://github.com/vuejs/core/issues/6736)) ([cb37d0b](https://github.com/vuejs/core/commit/cb37d0b9ffb5d4bb81a0367d84295dec8dd4448c)), closes [#5513](https://github.com/vuejs/core/issues/5513)\n* **compiler-dom:** treat inert as boolean attribute ([#8209](https://github.com/vuejs/core/issues/8209)) ([918ec8a](https://github.com/vuejs/core/commit/918ec8a5cbc825a3947cd35fe966671c245af087)), closes [#8208](https://github.com/vuejs/core/issues/8208)\n* **types:** add slots types for built-in components ([#6033](https://github.com/vuejs/core/issues/6033)) ([3cb4dc9](https://github.com/vuejs/core/commit/3cb4dc9e5538e1c2bde9fa691b001615a848c546))\n* **types:** provide ExtractPublicPropTypes utility type ([bff63c5](https://github.com/vuejs/core/commit/bff63c5498f5fa098689c18defe48ae08d47eadb)), closes [#5272](https://github.com/vuejs/core/issues/5272) [#8168](https://github.com/vuejs/core/issues/8168)\n* **compiler-sfc:** expose parseCache ([4576548](https://github.com/vuejs/core/commit/45765488d498d94f8760c9e82f1177070057b17c)), closes [#8202](https://github.com/vuejs/core/issues/8202)\n\n## Deprecations\n\n* **deprecation:** deprecate [@vnode](https://github.com/vnode) hooks in favor of vue: prefix ([5f0394a](https://github.com/vuejs/core/commit/5f0394a5ab88c82c74e240161499721f63d5462e))\n* **deprecation:** deprecate v-is directive ([bbd8301](https://github.com/vuejs/core/commit/bbd8301a1344b02de635ea16d4822db1c343bd12))\n* **deprecation:** unwrap injected refs in Options API by default, deprecate app.config.unwrapInjectedRefs ([526fa3b](https://github.com/vuejs/core/commit/526fa3b2ccf038375e76f8af2f1ddf79a7388878))\n\n# [3.3.0-beta.5](https://github.com/vuejs/core/compare/v3.3.0-beta.4...v3.3.0-beta.5) (2023-05-08)\n\n\n### Bug Fixes\n\n* **build:** retain defineComponent() treeshakability in Rollup ([c2172f3](https://github.com/vuejs/core/commit/c2172f3a0ebbd7153e209dd8df6d9724bc524d9a)), closes [#8236](https://github.com/vuejs/core/issues/8236)\n* **compiler-sfc:** enable props destructure when reactivity transform option is enabled ([862edfd](https://github.com/vuejs/core/commit/862edfd91a2c2f6b75f943cb1a9682c4be5d7fa8))\n* **compiler-sfc:** fix built-in type resolving in external files ([6b194bc](https://github.com/vuejs/core/commit/6b194bcf3b8143895c2a472cd87998ebf9856146)), closes [#8244](https://github.com/vuejs/core/issues/8244)\n* **compiler-sfc:** transform destructured props when reactivity transform option is enabled ([#8252](https://github.com/vuejs/core/issues/8252)) ([287bd99](https://github.com/vuejs/core/commit/287bd999942e58925377f50540c7134cff2a9279))\n* **runtime-core:** ensure defineComponent name in extraOptions takes higher priority ([b2be75b](https://github.com/vuejs/core/commit/b2be75bad4ba70da1da6930eb914e51ce2c630b2))\n* **runtime-dom:** check attribute value when setting option value ([#8246](https://github.com/vuejs/core/issues/8246)) ([4495373](https://github.com/vuejs/core/commit/4495373d28d9fa4479eedd224adb16248ae0b9f4)), closes [#8227](https://github.com/vuejs/core/issues/8227)\n* **suspense:** fix nested suspensible suspense with no asyn deps ([e147512](https://github.com/vuejs/core/commit/e1475129fc6f8c086c2ec667476900b8c8f46774)), closes [#8206](https://github.com/vuejs/core/issues/8206)\n* **types:** remove short syntax support in defineSlots() ([1279b17](https://github.com/vuejs/core/commit/1279b1730079f77692a0817d51bbba57eb2b871b))\n\n\n\n# [3.3.0-beta.4](https://github.com/vuejs/core/compare/v3.3.0-beta.3...v3.3.0-beta.4) (2023-05-05)\n\n\n### Bug Fixes\n\n* **runtime-core:** handle template ref with number values ([#8233](https://github.com/vuejs/core/issues/8233)) ([1b1242f](https://github.com/vuejs/core/commit/1b1242f4d1349e361335b2815f41742d41283a94)), closes [#8230](https://github.com/vuejs/core/issues/8230)\n* **types:** retain compatibility for provide() usage with explicit type parameter ([038cd83](https://github.com/vuejs/core/commit/038cd830d5b34b47d7e7e1c61f0973d27cd8b915))\n\n\n### Features\n\n* **compiler-dom:** treat inert as boolean attribute ([#8209](https://github.com/vuejs/core/issues/8209)) ([918ec8a](https://github.com/vuejs/core/commit/918ec8a5cbc825a3947cd35fe966671c245af087)), closes [#8208](https://github.com/vuejs/core/issues/8208)\n* **types:** add slots types for built-in components ([#6033](https://github.com/vuejs/core/issues/6033)) ([3cb4dc9](https://github.com/vuejs/core/commit/3cb4dc9e5538e1c2bde9fa691b001615a848c546))\n* **types:** provide ExtractPublicPropTypes utility type ([bff63c5](https://github.com/vuejs/core/commit/bff63c5498f5fa098689c18defe48ae08d47eadb)), closes [#5272](https://github.com/vuejs/core/issues/5272) [#8168](https://github.com/vuejs/core/issues/8168)\n\n\n\n# [3.3.0-beta.3](https://github.com/vuejs/core/compare/v3.3.0-beta.2...v3.3.0-beta.3) (2023-05-01)\n\n\n### Bug Fixes\n\n* **compiler-core:** handle slot argument parsing edge case ([b434d12](https://github.com/vuejs/core/commit/b434d12bf6cbd49a7c99b1646d9517d8393ea49f))\n* **hmr:** keep slots proxy mutable for hmr ([c117d9c](https://github.com/vuejs/core/commit/c117d9c257820481b85304db26ce5c77af5d050c)), closes [#8188](https://github.com/vuejs/core/issues/8188)\n* **types:** fix provide type checking for ref value ([de87e6e](https://github.com/vuejs/core/commit/de87e6e405dfaf9a917d7eb423fcee35237c2020)), closes [#8201](https://github.com/vuejs/core/issues/8201)\n\n\n### Features\n\n* **compiler-sfc:** expose parseCache ([4576548](https://github.com/vuejs/core/commit/45765488d498d94f8760c9e82f1177070057b17c)), closes [#8202](https://github.com/vuejs/core/issues/8202)\n\n\n\n# [3.3.0-beta.2](https://github.com/vuejs/core/compare/v3.3.0-beta.1...v3.3.0-beta.2) (2023-04-25)\n\n\n### Bug Fixes\n\n* **compiler-sfc:** avoid all hard errors when inferring runtime type ([2d9f6f9](https://github.com/vuejs/core/commit/2d9f6f926453c46f542789927bcd30d15da9c24b))\n* **compiler-sfc:** normalize windows paths when resolving types ([#8136](https://github.com/vuejs/core/issues/8136)) ([29da504](https://github.com/vuejs/core/commit/29da50468770fcee16ba5d5bec7166dd5bc120ee))\n* **compiler-sfc:** props bindings should not override user declared bindings ([433a58c](https://github.com/vuejs/core/commit/433a58ccb61c25512dcc3df155b8e285256917ef)), closes [#8148](https://github.com/vuejs/core/issues/8148)\n\n\n### Features\n\n* **compiler-sfc:** support project references when resolving types ([1c0be5c](https://github.com/vuejs/core/commit/1c0be5c7444966fa444460e87633cf44ec60292a)), closes [#8140](https://github.com/vuejs/core/issues/8140)\n\n\n### Performance Improvements\n\n* **compiler-sfc:** infer ref binding type for more built-in methods ([a370e80](https://github.com/vuejs/core/commit/a370e8006a70ea49a7d04c8c1a42d0947eba5dea))\n\n\n\n# [3.3.0-beta.1](https://github.com/vuejs/core/compare/v3.3.0-alpha.13...v3.3.0-beta.1) (2023-04-21)\n\n\n### Features\n\n* allow accessing console in template ([#6508](https://github.com/vuejs/core/issues/6508)) ([fe76224](https://github.com/vuejs/core/commit/fe762247f8035d28d543bc5602ad01b0c258f6d6)), closes [#7939](https://github.com/vuejs/core/issues/7939)\n* **compiler-sfc:** improve utility type Partial and Required ([#8103](https://github.com/vuejs/core/issues/8103)) ([1d1d728](https://github.com/vuejs/core/commit/1d1d72894995fde14bd09e2990462c19d5176bf9))\n* **deprecation:** deprecate [@vnode](https://github.com/vnode) hooks in favor of vue: prefix ([5f0394a](https://github.com/vuejs/core/commit/5f0394a5ab88c82c74e240161499721f63d5462e))\n* **deprecation:** deprecate v-is directive ([bbd8301](https://github.com/vuejs/core/commit/bbd8301a1344b02de635ea16d4822db1c343bd12))\n* **deprecation:** unwrap injected refs in Options API by default, deprecate app.config.unwrapInjectedRefs ([526fa3b](https://github.com/vuejs/core/commit/526fa3b2ccf038375e76f8af2f1ddf79a7388878))\n* **suspense:** introduce suspensible option for `<Suspense>` ([#6736](https://github.com/vuejs/core/issues/6736)) ([cb37d0b](https://github.com/vuejs/core/commit/cb37d0b9ffb5d4bb81a0367d84295dec8dd4448c)), closes [#5513](https://github.com/vuejs/core/issues/5513)\n\n\n\n# [3.3.0-alpha.13](https://github.com/vuejs/core/compare/v3.3.0-alpha.12...v3.3.0-alpha.13) (2023-04-20)\n\n\n### Bug Fixes\n\n* **compiler-sfc:** handle type merging + fix namespace access when inferring type ([d53e157](https://github.com/vuejs/core/commit/d53e157805678db7a3b9ca2fccc74530e1dfbc48)), closes [#8102](https://github.com/vuejs/core/issues/8102)\n* **compiler-sfc:** normalize filename when invalidating cache ([9b5a34b](https://github.com/vuejs/core/commit/9b5a34bf8c0d1b4c6ec3cf1434076b7e25065f84))\n* **hmr:** always traverse static children in dev ([f17a82c](https://github.com/vuejs/core/commit/f17a82c769cfb60ee6785ef5d34d91191d153542)), closes [#7921](https://github.com/vuejs/core/issues/7921) [#8100](https://github.com/vuejs/core/issues/8100)\n* **hmr:** force update cached slots during HMR ([94fa67a](https://github.com/vuejs/core/commit/94fa67a4f73b3646c8c1e29512a71b17bd56efc3)), closes [#7155](https://github.com/vuejs/core/issues/7155) [#7158](https://github.com/vuejs/core/issues/7158)\n\n\n### Features\n\n* **compiler-sfc:** support dynamic imports when resolving types ([4496456](https://github.com/vuejs/core/commit/4496456d7d9947560ef1e35ccb176b97a27bd8f4))\n* **compiler-sfc:** support export * when resolving types ([7c3ca3c](https://github.com/vuejs/core/commit/7c3ca3cc3e122fe273e80a950c57d492a7f0bf4a))\n* **compiler-sfc:** support ExtractPropTypes when resolving types ([50c0bbe](https://github.com/vuejs/core/commit/50c0bbe5221dbc1dc353d4960e69ec7c8ba12905)), closes [#8104](https://github.com/vuejs/core/issues/8104)\n* hasInjectionContext() for libraries ([#8111](https://github.com/vuejs/core/issues/8111)) ([5510ce3](https://github.com/vuejs/core/commit/5510ce385abfa151c07a5253cccf4abccabdd01d))\n\n\n\n# [3.3.0-alpha.12](https://github.com/vuejs/core/compare/v3.3.0-alpha.11...v3.3.0-alpha.12) (2023-04-18)\n\n\n### Bug Fixes\n\n* **compiler:** fix expression codegen for literal const bindings in non-inline mode ([0f77a2b](https://github.com/vuejs/core/commit/0f77a2b1d1047d66ccdfda70382d1a223886130c))\n\n\n\n# [3.3.0-alpha.11](https://github.com/vuejs/core/compare/v3.3.0-alpha.10...v3.3.0-alpha.11) (2023-04-17)\n\n\n### Bug Fixes\n\n* **compiler-sfc:** normalize windows paths when resolving types ([271df09](https://github.com/vuejs/core/commit/271df09470c61d073185ba6cf3cf50358713c500))\n\n\n\n# [3.3.0-alpha.10](https://github.com/vuejs/core/compare/v3.3.0-alpha.9...v3.3.0-alpha.10) (2023-04-17)\n\n\n### Bug Fixes\n\n* **hmr:** invalidate cached props/emits options on hmr ([4b5b384](https://github.com/vuejs/core/commit/4b5b384485cf8f6124f6738b89e3d047358f3a11))\n* **runtime-core:** properly merge props and emits options from mixins ([#8052](https://github.com/vuejs/core/issues/8052)) ([c94ef02](https://github.com/vuejs/core/commit/c94ef02421d7422bc59d10cf2eee9f4e7dcea6c8)), closes [#7989](https://github.com/vuejs/core/issues/7989)\n\n\n### Features\n\n* **compiler-sfc:** expose type import deps on compiled script block ([8d8ddd6](https://github.com/vuejs/core/commit/8d8ddd686c832b2ea29b87ef47666b13c4ad5d4c))\n* **compiler-sfc:** expose type resolve APIs ([f22e32e](https://github.com/vuejs/core/commit/f22e32e365bf6292cb606cb7289609e82da8b790))\n* **compiler-sfc:** mark props destructure as experimental and require explicit opt-in ([6b13e04](https://github.com/vuejs/core/commit/6b13e04b4c83fcdbb180dc1d59f536a1309c2960))\n* **compiler-sfc:** support intersection and union types in macros ([d1f973b](https://github.com/vuejs/core/commit/d1f973bff82581fb335d6fc05623d1ad3d84fb7c)), closes [#7553](https://github.com/vuejs/core/issues/7553)\n* **compiler-sfc:** support limited built-in utility types in macros ([1cfab4c](https://github.com/vuejs/core/commit/1cfab4c695b0c28f549f8c97faee5099581792a7))\n* **compiler-sfc:** support mapped types, string types & template type in macros ([fb8ecc8](https://github.com/vuejs/core/commit/fb8ecc803e58bfef0971346c63fefc529812daa7))\n* **compiler-sfc:** support namespace members type in macros ([5ff40bb](https://github.com/vuejs/core/commit/5ff40bb0dc2918b7db15fe9f49db2a135a925572))\n* **compiler-sfc:** support relative imported types in macros ([8aa4ea8](https://github.com/vuejs/core/commit/8aa4ea81d6e4d3110aa1619cca594543da4c9b63))\n* **compiler-sfc:** support resolving type imports from modules ([3982bef](https://github.com/vuejs/core/commit/3982bef533b451d1b59fa243560184a13fe8c18c))\n* **compiler-sfc:** support specifying global types for sfc macros ([4e028b9](https://github.com/vuejs/core/commit/4e028b966991937c83fb2529973fd3d41080bb61)), closes [/github.com/vuejs/core/pull/8083#issuecomment-1508468713](https://github.com//github.com/vuejs/core/pull/8083/issues/issuecomment-1508468713)\n* **compiler-sfc:** support string indexed type in macros ([3f779dd](https://github.com/vuejs/core/commit/3f779ddbf85054c8915fa4537f8a79baab392d5c))\n* **compiler-sfc:** support string/number indexed types in macros ([760755f](https://github.com/vuejs/core/commit/760755f4f83680bee13ad546cdab2e48ade38dff))\n\n\n### Performance Improvements\n\n* **compiler:** use source-map-js ([19e17a9](https://github.com/vuejs/core/commit/19e17a951c3387cbd6a1597e6cd9048a4aad4528))\n\n\n\n# [3.3.0-alpha.9](https://github.com/vuejs/core/compare/v3.3.0-alpha.8...v3.3.0-alpha.9) (2023-04-08)\n\n\n### Bug Fixes\n\n* **compiler-sfc:** accept `StringLiteral` node in `defineEmit` tuple syntax ([#8041](https://github.com/vuejs/core/issues/8041)) ([3ccbea0](https://github.com/vuejs/core/commit/3ccbea08e09217b50a410d7b49ebb138e0c4c1e7)), closes [#8040](https://github.com/vuejs/core/issues/8040)\n* **compiler-sfc:** fix binding type for constants when hoistStatic is disabled ([#8029](https://github.com/vuejs/core/issues/8029)) ([f7f4624](https://github.com/vuejs/core/commit/f7f4624191bbdc09600dbb0eb048b947c3a4f761))\n* **compiler-sfc:** skip empty `defineOptions` and support TypeScript type assertions ([#8028](https://github.com/vuejs/core/issues/8028)) ([9557529](https://github.com/vuejs/core/commit/955752951e1d31b90d817bd20830fe3f89018771))\n* **compiler-ssr:** disable v-once transform in ssr vdom fallback branch ([05f94cf](https://github.com/vuejs/core/commit/05f94cf7b01dd05ed7d3170916a38b175d5df292)), closes [#7644](https://github.com/vuejs/core/issues/7644)\n* **types:** improve defineProps return type with generic arguments ([91a931a](https://github.com/vuejs/core/commit/91a931ae8707b8d43f10216e1ce8e18b12158f99))\n* **types:** more public type argument order fix ([af563bf](https://github.com/vuejs/core/commit/af563bf428200367b6f5bb7944f690c85d810202))\n* **types:** retain type parameters order for public types ([bdf557f](https://github.com/vuejs/core/commit/bdf557f6f233c039fff8007b1b16aec00c4e68aa))\n\n\n### Features\n\n* **app:** app.runWithContext() ([#7451](https://github.com/vuejs/core/issues/7451)) ([869f3fb](https://github.com/vuejs/core/commit/869f3fb93e61400be4fd925e0850c2b1564749e2))\n* **sfc:** introduce `defineModel` macro and `useModel` helper ([#8018](https://github.com/vuejs/core/issues/8018)) ([14f3d74](https://github.com/vuejs/core/commit/14f3d747a34d45415b0036b274517d70a27ec0d3))\n\n\n### Reverts\n\n* Revert \"chore: remove unused args passed to ssrRender\" ([b117b88](https://github.com/vuejs/core/commit/b117b8844881a732a021432066230ff2215049ea))\n\n\n\n# [3.3.0-alpha.8](https://github.com/vuejs/core/compare/v3.3.0-alpha.7...v3.3.0-alpha.8) (2023-04-04)\n\n\n### Bug Fixes\n\n* **compiler-sfc:** check binding is prop before erroring ([f3145a9](https://github.com/vuejs/core/commit/f3145a915aaec11c915f1df258c5209ae4782bcc)), closes [#8017](https://github.com/vuejs/core/issues/8017)\n\n\n\n# [3.3.0-alpha.7](https://github.com/vuejs/core/compare/v3.3.0-alpha.6...v3.3.0-alpha.7) (2023-04-03)\n\n\n### Bug Fixes\n\n* **compiler-dom:** handle newlines when evaluating constants during stringification ([#7995](https://github.com/vuejs/core/issues/7995)) ([5261085](https://github.com/vuejs/core/commit/52610851137b9c5f6f57d771fd604fba309b3c97)), closes [#7994](https://github.com/vuejs/core/issues/7994)\n* **compiler-sfc:** use dynamic defaults merging for methods with computed keys ([482f2e3](https://github.com/vuejs/core/commit/482f2e3434a1edc47a181890354838e206d08922)), closes [#7113](https://github.com/vuejs/core/issues/7113)\n\n\n### Features\n\n* **compiler-sfc:** codegen support for defineEmits() short syntax (followup of [#7992](https://github.com/vuejs/core/issues/7992)) ([ef73ea5](https://github.com/vuejs/core/commit/ef73ea53eaf853d43e70946d2d448ae8c0a83e4f))\n* **compiler-sfc:** support arbitrary expression as withDefaults argument ([fe61944](https://github.com/vuejs/core/commit/fe619443d2e99301975de120685dbae8d66c03a6)), closes [#6459](https://github.com/vuejs/core/issues/6459)\n* **reactivity:** improve support of getter usage in reactivity APIs ([#7997](https://github.com/vuejs/core/issues/7997)) ([59e8284](https://github.com/vuejs/core/commit/59e828448e7f37643cd0eaea924a764e9d314448))\n* **sfc:** revert withDefaults() deprecation ([4af5d1b](https://github.com/vuejs/core/commit/4af5d1b0754035058436f9e4e5c12aedef199177))\n* **sfc:** support more ergonomic defineEmits type syntax ([#7992](https://github.com/vuejs/core/issues/7992)) ([8876dcc](https://github.com/vuejs/core/commit/8876dccf42a7f05375d97cb18c1afdfd0fc51c94))\n* **types/slots:** support slot presence / props type checks via `defineSlots` macro and `slots` option ([#7982](https://github.com/vuejs/core/issues/7982)) ([5a2f5d5](https://github.com/vuejs/core/commit/5a2f5d59cffa36a99e6f2feab6b3ba7958b7362f))\n\n\n\n# [3.3.0-alpha.6](https://github.com/vuejs/core/compare/v3.3.0-alpha.5...v3.3.0-alpha.6) (2023-03-30)\n\n\n### Bug Fixes\n\n* **compiler-core:** check if expression is constant ([#7974](https://github.com/vuejs/core/issues/7974)) ([77686cf](https://github.com/vuejs/core/commit/77686cf4765e7e345bef364c0b03739e3c2da91d)), closes [#7973](https://github.com/vuejs/core/issues/7973)\n* **compiler-core:** fix codegen for literal const in non-inline mode ([6bda4b6](https://github.com/vuejs/core/commit/6bda4b66886240b28993c88b7ecd4640a199be65))\n* **compiler-sfc:** allow `<script>` with lang='js' ([#7398](https://github.com/vuejs/core/issues/7398)) ([9f5e20c](https://github.com/vuejs/core/commit/9f5e20ccff235946159f0e50519f5be09bc89d5b))\n* **compiler-sfc:** avoid codegen conflict with user variable named `expose` ([#7949](https://github.com/vuejs/core/issues/7949)) ([c839129](https://github.com/vuejs/core/commit/c839129ab9d46f56a019b0ff234b35f27cac1e35)), closes [#7890](https://github.com/vuejs/core/issues/7890)\n* **compiler-sfc:** disallow `expose` property in `defineOptions` ([#7967](https://github.com/vuejs/core/issues/7967)) ([93f7729](https://github.com/vuejs/core/commit/93f77292c9f2c4dcc83aae6b5943a8b1d7443092))\n* **compiler-sfc:** fix defineExpose() codegen regression from [#7949](https://github.com/vuejs/core/issues/7949) ([a94072d](https://github.com/vuejs/core/commit/a94072dd2ca1aca4ce1fbe5da51ca2a9a07a4637))\n* **compiler-sfc:** fix edge case of default export call with no args ([#7536](https://github.com/vuejs/core/issues/7536)) ([d60e58c](https://github.com/vuejs/core/commit/d60e58c9f62ae7bd1f9c888cd2e55982a64d9e96)), closes [#7534](https://github.com/vuejs/core/issues/7534)\n* **compiler-sfc:** fix function default value handling w/ props destructure ([e10a89e](https://github.com/vuejs/core/commit/e10a89e608d3486c0c9a0457ee7c56d208e0aa91))\n* **compiler-sfc:** handle more TS built-in utilities in defineProps inference ([4355d24](https://github.com/vuejs/core/commit/4355d2492dccdb175b18d083e20f3ec39a52801f))\n* **compiler-sfc:** infer function prop type from type literal w/ callable signature ([#7119](https://github.com/vuejs/core/issues/7119)) ([3a7572c](https://github.com/vuejs/core/commit/3a7572cdb2074c5cac2231e4525296104141411c))\n* **compiler-sfc:** infer object type for empty type literal ([1a04fba](https://github.com/vuejs/core/commit/1a04fba10b6462303c65f1095da86ce05c14f1f4))\n* **compiler-sfc:** infer runtime type in defineProps ([#7972](https://github.com/vuejs/core/issues/7972)) ([ba4cec3](https://github.com/vuejs/core/commit/ba4cec31b91da60555892c381b00c2fa5b3e0e39))\n* **compiler-sfc:** infer TS Extract&Exclude runtime type ([#7339](https://github.com/vuejs/core/issues/7339)) ([6391daf](https://github.com/vuejs/core/commit/6391daf6586e49e165b3195863b602c3cbb92ace)), closes [#7337](https://github.com/vuejs/core/issues/7337) [#6252](https://github.com/vuejs/core/issues/6252)\n* **compiler-sfc:** infer TSIntersectionType in defineProps ([#7394](https://github.com/vuejs/core/issues/7394)) ([151a8ad](https://github.com/vuejs/core/commit/151a8ad6b9288784c3b2514820a112b93ecf2dca))\n* **compiler-sfc:** properly handle unknown types in runtime prop inference ([5fb406e](https://github.com/vuejs/core/commit/5fb406e3e1d585076779e9ce4a588a4f9a61ef23)), closes [#7511](https://github.com/vuejs/core/issues/7511)\n* **compiler-sfc:** properly remove comma of multiple macros in the same declaration ([#7423](https://github.com/vuejs/core/issues/7423)) ([336a3d7](https://github.com/vuejs/core/commit/336a3d7b9199aeda19672832ce173de298b1105a)), closes [#7422](https://github.com/vuejs/core/issues/7422) [#6778](https://github.com/vuejs/core/issues/6778)\n* **compiler-sfc:** rewrite default export with AST analysis instead of regex ([#7068](https://github.com/vuejs/core/issues/7068)) ([701b95f](https://github.com/vuejs/core/commit/701b95ff3d2bad0284c03865a0b052fc8324beec)), closes [#7038](https://github.com/vuejs/core/issues/7038) [#7041](https://github.com/vuejs/core/issues/7041) [#7078](https://github.com/vuejs/core/issues/7078)\n* **compiler-sfc:** unwrap TS node for defineProps ([#7340](https://github.com/vuejs/core/issues/7340)) ([1b69d5f](https://github.com/vuejs/core/commit/1b69d5f2f49ee60af4b10137c7833a76420dbba1))\n* **compiler-sfc:** use prependLeft to handle CSSVars ([#7760](https://github.com/vuejs/core/issues/7760)) ([139104b](https://github.com/vuejs/core/commit/139104ba2695eecae672db98f978de78e17ab7e1))\n* **jsx-runtime:** fix automatic runtime implementation ([#7959](https://github.com/vuejs/core/issues/7959)) ([5838950](https://github.com/vuejs/core/commit/5838950ecf7e4e17dd5a23acd621077390666b76))\n* **jsx-runtime:** handle keys ([#7976](https://github.com/vuejs/core/issues/7976)) ([ff60b93](https://github.com/vuejs/core/commit/ff60b933ae4e02422393664ee7818cffadf9b58b))\n* **types/jsx:** jsx-runtime types for global JSX namespace registration ([#7978](https://github.com/vuejs/core/issues/7978)) ([0f73f39](https://github.com/vuejs/core/commit/0f73f394dafd709298bd8c71107a323bf322a1d2))\n* **types/jsx:** move JSX DOM types back to `@vue/runtime-dom` ([#7979](https://github.com/vuejs/core/issues/7979)) ([ffe679c](https://github.com/vuejs/core/commit/ffe679c490986b69956daec7166f1ab6d9f23073))\n* **types/jsx:** remove $slots children override ([28e30c8](https://github.com/vuejs/core/commit/28e30c819df5e4fc301c98f7be938fa13e8be3bc))\n* **types:** revert jsx global removal (to be removed in 3.4) ([e224922](https://github.com/vuejs/core/commit/e224922e972e78b4fb6cbd129d685c2317018ad1))\n\n\n### Features\n\n* **compiler-core:** support parsing `const` modifier in type parameters ([#7912](https://github.com/vuejs/core/issues/7912)) ([b7bd50f](https://github.com/vuejs/core/commit/b7bd50f5059e8755c0204f01a8c55b1724688e7e))\n* **compiler-sfc:** add defineOptions macro ([#5738](https://github.com/vuejs/core/issues/5738)) ([bcf5841](https://github.com/vuejs/core/commit/bcf5841ddecc64d0bdbd56ce1463eb8ebf01bb9d))\n* **compiler-sfc:** enable reactive props destructure by default ([#7986](https://github.com/vuejs/core/issues/7986)) ([ba9c2ae](https://github.com/vuejs/core/commit/ba9c2ae247fcc3960b238a04cb635158daa82004))\n* **compiler-sfc:** improve runtime props inference for enum ([eded947](https://github.com/vuejs/core/commit/eded94712e37856f258dc8c85f98a26fa41ae05f))\n* **compiler-sfc:** support generating variable instead of default export in compileScript ([71635be](https://github.com/vuejs/core/commit/71635be68d25887f91d624bb7f78281a851bc0cb))\n* **compiler-sfc:** support module string names syntax ([#7428](https://github.com/vuejs/core/issues/7428)) ([0002567](https://github.com/vuejs/core/commit/000256772816d54976e462330a7be342c49c7304))\n* **compiler-sfc:** hoist literal constants for script ([#5752](https://github.com/vuejs/core/issues/5752)) ([7def8b1](https://github.com/vuejs/core/commit/7def8b15b89aa78accd9a00927db91e8091a12b7)), closes [#5750](https://github.com/vuejs/core/issues/5750)\n* **runtime-core:** add skipCheck for prop ([#7548](https://github.com/vuejs/core/issues/7548)) ([63ad77f](https://github.com/vuejs/core/commit/63ad77f6f65751780aa52f817387165b4773cfe4))\n* **sfc:** deprecate reactivity transform ([efb54e7](https://github.com/vuejs/core/commit/efb54e7315e93f4be7004d1c0a4de8c523dab334))\n* **types:** `defineComponent()` with generics support ([#7963](https://github.com/vuejs/core/issues/7963)) ([d77557c](https://github.com/vuejs/core/commit/d77557c4038f88a676903b379505b280a88cc774)), closes [#3102](https://github.com/vuejs/core/issues/3102)\n\n\n### BREAKING CHANGES\n\n* **types:** The type of `defineComponent()` when passing in a function has changed. This overload signature is rarely used in practice and the breakage will be minimal, so repurposing it to something more useful should be worth it.\n\n\n\n# [3.3.0-alpha.5](https://github.com/vuejs/core/compare/v3.3.0-alpha.4...v3.3.0-alpha.5) (2023-03-26)\n\n### Bug Fixes\n\n* **runtime-core:** support `getCurrentInstance` across multiple builds of Vue ([8d2d5bf](https://github.com/vuejs/core/commit/8d2d5bf48a24dab44e5b03cb8fa0c5faa4b696e3))\n* **types:** ensure defineProps with generics return correct types ([c288c7b](https://github.com/vuejs/core/commit/c288c7b0bd6077d690f42153c3fc49a45454a66a))\n\n\n### Features\n\n* **dx:** improve readability of displayed types for props ([4c9bfd2](https://github.com/vuejs/core/commit/4c9bfd2b999ce472f7481aae4f9dc5bb9f76628e))\n* **types/jsx:** support jsxImportSource, avoid global JSX conflict ([#7958](https://github.com/vuejs/core/issues/7958)) ([d0b7ef3](https://github.com/vuejs/core/commit/d0b7ef3b61d5f83e35e5854b3c2c874e23463102))\n\n### Note on JSX Types Change\n\n* In the next minor (3.4), Vue no longer registers the global `JSX` namespace by default. This is necessary to avoid global namespace collision with React so that TSX of both libs can co-exist in the same project. This should not affect SFC-only users with latest version of Volar.\n\n  For TSX users, it is suggested to set [jsxImportSource](https://www.typescriptlang.org/tsconfig#jsxImportSource) to `'vue'` in `tsconfig.json` after upgrading to 3.3, or opt-in per file with `/* @jsxImportSource vue */`. This will allow you to opt-in to the new behavior now and upgrade seamlessly when 3.4 releases.\n\n  If there is code that depends on the presence of the global `JSX` namespace,  you can retain the exact pre-3.4 global behavior by explicitly referencing `vue/jsx`, which registers the global `JSX` namespace.\n\n  Note that the planned change in 3.4 is a type-only breaking change in a minor release, which adheres to our [release policy](https://vuejs.org/about/releases.html#semantic-versioning-edge-cases).\n\n# [3.3.0-alpha.4](https://github.com/vuejs/core/compare/v3.3.0-alpha.3...v3.3.0-alpha.4) (2023-02-06)\n\n\n### Bug Fixes\n\n* **build:** fix const enum w/ number values ([92bb189](https://github.com/vuejs/core/commit/92bb189ca7ecae221ebf5411da87c715780d2de3))\n\n\n\n# [3.3.0-alpha.3](https://github.com/vuejs/core/compare/v3.3.0-alpha.2...v3.3.0-alpha.3) (2023-02-06)\n\n\n### Bug Fixes\n\n* **build:** avoid const enum conflicts ([d1181ad](https://github.com/vuejs/core/commit/d1181ad692861c140e687372efbc67a1d65d642a))\n\n\n\n# [3.3.0-alpha.2](https://github.com/vuejs/core/compare/v3.3.0-alpha.1...v3.3.0-alpha.2) (2023-02-05)\n\n\n### Bug Fixes\n\n* **build:** fix dev flag replacement in esm-bundler builds ([5851eaa](https://github.com/vuejs/core/commit/5851eaa9339364d41860a277a99f2352de2a3834))\n\n\n\n# [3.3.0-alpha.1](https://github.com/vuejs/core/compare/v3.2.47...v3.3.0-alpha.1) (2023-02-05)\n\n\n### Bug Fixes\n\n* **build:** ensure BaseTransition functions can be tree-shaken ([3a6f5eb](https://github.com/vuejs/core/commit/3a6f5eb0f7d60dc87d17a69c66e88ae5688b11a5))\n"
  },
  {
    "path": "changelogs/CHANGELOG-3.4.md",
    "content": "## [3.4.38](https://github.com/vuejs/core/compare/v3.4.37...v3.4.38) (2024-08-15)\n\n\n### Bug Fixes\n\n* **build:** revert entities to 4.5 to avoid runtime resolution errors ([f349af7](https://github.com/vuejs/core/commit/f349af7b65b9f8605d8b7bafcc06c25ab1f2daf0)), closes [#11603](https://github.com/vuejs/core/issues/11603)\n* **compiler-core:** use ast-based check for function expressions when possible ([236cac3](https://github.com/vuejs/core/commit/236cac3ff285890b8468dc827c463d87a91e516f)), closes [#11615](https://github.com/vuejs/core/issues/11615)\n* **compiler-sfc:** handle keyof operator with index object ([#11581](https://github.com/vuejs/core/issues/11581)) ([74d26db](https://github.com/vuejs/core/commit/74d26dbbe3cf2f70d1b772284eec6743ea946f6d))\n* **types:** add fallback stub for DOM types when DOM lib is absent ([#11598](https://github.com/vuejs/core/issues/11598)) ([4db0085](https://github.com/vuejs/core/commit/4db0085de316e1b773f474597915f9071d6ae6c6))\n\n\n\n## [3.4.37](https://github.com/vuejs/core/compare/v3.4.36...v3.4.37) (2024-08-08)\n\n\n### Bug Fixes\n\n* **compiler-core:** use `isProp.arg.loc` instead of `isProp.loc` ([#11547](https://github.com/vuejs/core/issues/11547)) ([236fb7a](https://github.com/vuejs/core/commit/236fb7abebe567b73826a3ddc2120f3273377ba0))\n* **custom-element:** fix custom-element double render on immediate prop change ([978ff3c](https://github.com/vuejs/core/commit/978ff3c1dbff9c93ec284c1804d3c77331ea33f8)), closes [#9885](https://github.com/vuejs/core/issues/9885) [#11335](https://github.com/vuejs/core/issues/11335)\n* **defineModel:** detect changes respect custom getter and setter ([#11543](https://github.com/vuejs/core/issues/11543)) ([e042888](https://github.com/vuejs/core/commit/e0428884b57ac834274045bd33841263aeae259e)), closes [#11541](https://github.com/vuejs/core/issues/11541) [#11526](https://github.com/vuejs/core/issues/11526) [#11527](https://github.com/vuejs/core/issues/11527)\n* **keep-alive:** avoid cache suspense comment root ([#11479](https://github.com/vuejs/core/issues/11479)) ([a917c05](https://github.com/vuejs/core/commit/a917c0539cdc55c0188ca91f70b6ff79fee13ed9))\n* **keep-alive:** fix render error in cached is undefined ([#11496](https://github.com/vuejs/core/issues/11496)) ([81351dc](https://github.com/vuejs/core/commit/81351dc7fbdabcfa0f545f7d924c31a3c367e496)), closes [#11427](https://github.com/vuejs/core/issues/11427) [#11431](https://github.com/vuejs/core/issues/11431)\n* Revert \"fix(types/ref): allow getter and setter types to be unrelated ([#11442](https://github.com/vuejs/core/issues/11442))\" ([b1abac0](https://github.com/vuejs/core/commit/b1abac06cdb198bd72f8e614b1f68b92e1c78339))\n* Revert \"fix(types/ref): correct type inference for nested refs ([#11536](https://github.com/vuejs/core/issues/11536))\" ([3a56315](https://github.com/vuejs/core/commit/3a56315f94bc0e11cfbb288b65482ea8fc3a39b4))\n* **runtime-core:** fix warning for missing event handler ([#11489](https://github.com/vuejs/core/issues/11489)) ([e359ff0](https://github.com/vuejs/core/commit/e359ff0046286aee03fe31656c023677be457e07)), closes [#4803](https://github.com/vuejs/core/issues/4803) [#8268](https://github.com/vuejs/core/issues/8268)\n* **runtime-core:** prioritize using the provides from currentApp in nested createApp ([#11502](https://github.com/vuejs/core/issues/11502)) ([7e75de0](https://github.com/vuejs/core/commit/7e75de002f08076a02c9361a58fa1d0af1772964)), closes [#11488](https://github.com/vuejs/core/issues/11488)\n   * Note: this change will break `inject` calls inside Pinia stores that expects to be able to inject provided values from the component using the store. This is expected because the usage is relying on previously incorrect behavior.\n* **runtime-dom:** apply css vars before mount ([#11538](https://github.com/vuejs/core/issues/11538)) ([fdc2a31](https://github.com/vuejs/core/commit/fdc2a31dbd4196d6432be16767a1bfdab1240d49)), closes [#11533](https://github.com/vuejs/core/issues/11533)\n* **ssr:** ensure content is valid when rendering normal slot ([#11491](https://github.com/vuejs/core/issues/11491)) ([6c90324](https://github.com/vuejs/core/commit/6c903248703e2413c6197b9ad4d535f31c8eac39)), closes [#11326](https://github.com/vuejs/core/issues/11326)\n* **types/ref:** correct type inference for nested refs ([#11536](https://github.com/vuejs/core/issues/11536)) ([536f623](https://github.com/vuejs/core/commit/536f62332c455ba82ef2979ba634b831f91928ba)), closes [#11532](https://github.com/vuejs/core/issues/11532) [#11537](https://github.com/vuejs/core/issues/11537)\n* **types:** allow `DirectiveArguments` third parameter to accept undefined ([#11540](https://github.com/vuejs/core/issues/11540)) ([1058ce8](https://github.com/vuejs/core/commit/1058ce8e747ce606e5e86fca5a2acce3c12a0846))\n\n\n\n## [3.4.36](https://github.com/vuejs/core/compare/v3.4.35...v3.4.36) (2024-08-06)\n\n### Bug Fixes\n\n* **compiler-core:** fix expression transform for try...catch block params ([077a1ae](https://github.com/vuejs/core/commit/077a1aeb3c222b729a7e190f46864656ecc65325)), closes [#11465](https://github.com/vuejs/core/issues/11465) [#11467](https://github.com/vuejs/core/issues/11467)\n* **compiler-core:** properly handle for loop variable declarations in expression transforms ([67bb820](https://github.com/vuejs/core/commit/67bb820904d53480fa37536fc3cb4109a4c6d3e2)), ref [#11467](https://github.com/vuejs/core/issues/11467)\n* **compiler-ssr:** don't render v-if comments in TransitionGroup + static tag ([#11515](https://github.com/vuejs/core/issues/11515)) ([275354c](https://github.com/vuejs/core/commit/275354caba295a6fb50695b70e97888a33c504e0)), closes [#11514](https://github.com/vuejs/core/issues/11514)\n* **hydration:** force hydrate custom element dynamic props ([7d473b7](https://github.com/vuejs/core/commit/7d473b7721b423050dba62823b16f3d39e640567)), closes [#7203](https://github.com/vuejs/core/issues/7203) [#8038](https://github.com/vuejs/core/issues/8038)\n* **ssr:** respect textContent/innerHTML from getSSRProps in optimized SSR output ([79602f9](https://github.com/vuejs/core/commit/79602f9ecd9559954f844774a90286305b13e056)), closes [#8112](https://github.com/vuejs/core/issues/8112)\n* **types/withDefaults:** ensure default values of type `any` do not include `undefined` ([#11490](https://github.com/vuejs/core/issues/11490)) ([4592b63](https://github.com/vuejs/core/commit/4592b63c6a8a3d69bfe4ac1f9458b4a86a9676a4))\n\n\n\n## [3.4.35](https://github.com/vuejs/core/compare/v3.4.34...v3.4.35) (2024-07-31)\n\n\n### Bug Fixes\n\n* **teleport/ssr:** fix Teleport hydration regression due to targetStart anchor addition ([7b18cdb](https://github.com/vuejs/core/commit/7b18cdb0b53a94007ca6a3675bf41b5d3153fec6))\n* **teleport/ssr:** ensure targetAnchor and targetStart not null during hydration ([#11456](https://github.com/vuejs/core/issues/11456)) ([12667da](https://github.com/vuejs/core/commit/12667da4879f980dcf2c50e36f3642d085a87d71)), closes [#11400](https://github.com/vuejs/core/issues/11400)\n* **types/ref:** allow getter and setter types to be unrelated ([#11442](https://github.com/vuejs/core/issues/11442)) ([e0b2975](https://github.com/vuejs/core/commit/e0b2975ef65ae6a0be0aa0a0df43fb887c665251))\n\n\n### Performance Improvements\n\n* **runtime-core:** improve efficiency of normalizePropsOptions ([#11409](https://github.com/vuejs/core/issues/11409)) ([5680142](https://github.com/vuejs/core/commit/5680142e68096c42e66da9f4c6220d040d7c56ba)), closes [#9739](https://github.com/vuejs/core/issues/9739)\n\n\n\n## [3.4.34](https://github.com/vuejs/core/compare/v3.4.33...v3.4.34) (2024-07-24)\n\n* **defineModel:** correct update with multiple changes in same tick ([#11430](https://github.com/vuejs/core/issues/11430)) ([a18f1ec](https://github.com/vuejs/core/commit/a18f1ecf05842337f1eb39a6871adb8cb4024093)), closes [#11429](https://github.com/vuejs/core/issues/11429)\n\n\n\n## [3.4.33](https://github.com/vuejs/core/compare/v3.4.32...v3.4.33) (2024-07-19)\n\n\n### Bug Fixes\n\n* **runtime-dom:** handle undefined values in v-html ([#11403](https://github.com/vuejs/core/issues/11403)) ([5df67e3](https://github.com/vuejs/core/commit/5df67e36756639ea7b923d1b139d6cb14450123b))\n\n\n\n## [3.4.32](https://github.com/vuejs/core/compare/v3.4.31...v3.4.32) (2024-07-17)\n\n\n### Bug Fixes\n\n* **build:** use consistent minify options from previous terser config ([789675f](https://github.com/vuejs/core/commit/789675f65d2b72cf979ba6a29bd323f716154a4b))\n* **compiler-sfc:** correctly resolve type annotation for declared function ([#11279](https://github.com/vuejs/core/issues/11279)) ([b287aee](https://github.com/vuejs/core/commit/b287aeec3ea85f20e4b1fc3d907c901bdc2a0176)), closes [#11266](https://github.com/vuejs/core/issues/11266)\n* **defineModel:** force local update when setter results in same emitted value ([de174e1](https://github.com/vuejs/core/commit/de174e1aa756508c7542605a448e55a373afb1ed)), closes [#10279](https://github.com/vuejs/core/issues/10279) [#10301](https://github.com/vuejs/core/issues/10301)\n* **hmr:** hmr reload should work with async component ([#11248](https://github.com/vuejs/core/issues/11248)) ([c8b9794](https://github.com/vuejs/core/commit/c8b97945759e869c997d60c3350d2451c5ff7887))\n* **hydration:** fix tracking of reactive style objects in production ([c10e40a](https://github.com/vuejs/core/commit/c10e40a217b89ab7e0f7f3515242d4246ecffbdd)), closes [#11372](https://github.com/vuejs/core/issues/11372)\n* **hydration:** handle consectuvie text nodes during hydration ([f44c3b3](https://github.com/vuejs/core/commit/f44c3b37d446d5f8e34539029dae0d806b25bb47)), closes [#7285](https://github.com/vuejs/core/issues/7285) [#7301](https://github.com/vuejs/core/issues/7301)\n* **reactivity:** ensure `unref` correctly resolves type for `ShallowRef` ([#11360](https://github.com/vuejs/core/issues/11360)) ([a509e30](https://github.com/vuejs/core/commit/a509e30f059fcdd158f39fdf34670b1019eaf2d1)), closes [#11356](https://github.com/vuejs/core/issues/11356)\n* **reactivity:** shallowReactive map \"unwraps\" the nested refs ([#8503](https://github.com/vuejs/core/issues/8503)) ([50ddafe](https://github.com/vuejs/core/commit/50ddafe91b9195cf94124466239f82c9794699fb)), closes [#8501](https://github.com/vuejs/core/issues/8501) [#11249](https://github.com/vuejs/core/issues/11249)\n* **runtime-core:** avoid recursive warning ([3ee7b4c](https://github.com/vuejs/core/commit/3ee7b4c7b1374c5bdc50a579b49f6bc15022b085)), closes [#8074](https://github.com/vuejs/core/issues/8074)\n* **runtime-core:** bail manually rendered compiler slot fragments in all cases ([3d34f40](https://github.com/vuejs/core/commit/3d34f406ac7497dafd2f4e62ab23579b78a0e08a)), closes [#10870](https://github.com/vuejs/core/issues/10870)\n* **runtime-core:** do not emit when defineModel ref is set with same value ([#11162](https://github.com/vuejs/core/issues/11162)) ([f1bb0ae](https://github.com/vuejs/core/commit/f1bb0aef084b5cdd4d49aecfed01ec106d9b6897)), closes [#11125](https://github.com/vuejs/core/issues/11125)\n* **runtime-core:** errors during component patch should be caught by error handlers ([ee0248a](https://github.com/vuejs/core/commit/ee0248accff589a94688e177e5e3af10c18288cb))\n* **runtime-core:** force diff slot fallback content and provided content ([d76dd9c](https://github.com/vuejs/core/commit/d76dd9c58de24b273bc55af3a8ed81ba693e9683)), closes [#7256](https://github.com/vuejs/core/issues/7256) [#9200](https://github.com/vuejs/core/issues/9200) [#9308](https://github.com/vuejs/core/issues/9308) [#7266](https://github.com/vuejs/core/issues/7266) [#9213](https://github.com/vuejs/core/issues/9213)\n* **runtime-core:** more edge case fix for manually rendered compiled slot ([685e3f3](https://github.com/vuejs/core/commit/685e3f381c024b9f4023e60fe0545dc60d90d984)), closes [#11336](https://github.com/vuejs/core/issues/11336)\n* **runtime-core:** use separate prop caches for components and mixins ([#11350](https://github.com/vuejs/core/issues/11350)) ([b0aa234](https://github.com/vuejs/core/commit/b0aa234e5e7a611c018de68bc31e0cf55518d5ce)), closes [#7998](https://github.com/vuejs/core/issues/7998)\n* **runtime-dom:** properly handle innerHTML unmount into new children ([#11159](https://github.com/vuejs/core/issues/11159)) ([3e9e32e](https://github.com/vuejs/core/commit/3e9e32ee0a6d0fbf67e9098a66ff0a1ea6647806)), closes [#9135](https://github.com/vuejs/core/issues/9135)\n* **teleport:** skip teleported nodes when locating patch anchor ([8655ced](https://github.com/vuejs/core/commit/8655ced480ea0fe453ff5fe445cecf97b91ec260)), closes [#9071](https://github.com/vuejs/core/issues/9071) [#9134](https://github.com/vuejs/core/issues/9134) [#9313](https://github.com/vuejs/core/issues/9313) [#9313](https://github.com/vuejs/core/issues/9313)\n* **v-model:** component v-model modifiers trim and number when cases don't match ([#9609](https://github.com/vuejs/core/issues/9609)) ([7fb6eb8](https://github.com/vuejs/core/commit/7fb6eb882b64bf99a99d00606e54b0e050674206)), closes [#4848](https://github.com/vuejs/core/issues/4848) [#4850](https://github.com/vuejs/core/issues/4850) [#4850](https://github.com/vuejs/core/issues/4850)\n* **v-once:** properly unmount v-once cached trees ([d343a0d](https://github.com/vuejs/core/commit/d343a0dc01663f91db42b4ddb693e6fffcb45873)), closes [#5154](https://github.com/vuejs/core/issues/5154) [#8809](https://github.com/vuejs/core/issues/8809)\n\n\n### Performance Improvements\n\n* **server-renderer:** avoid unnecessary checks in `createBuffer` ([#11364](https://github.com/vuejs/core/issues/11364)) ([fc205bf](https://github.com/vuejs/core/commit/fc205bf4decde5ce0f4a61394ffa3914b502c287))\n* **server-renderer:** optimize `unrollBuffer` by avoiding promises ([#11340](https://github.com/vuejs/core/issues/11340)) ([05779a7](https://github.com/vuejs/core/commit/05779a70bd0b567ae458a07636d229bd07c44c4e))\n\n\n\n## [3.4.31](https://github.com/vuejs/core/compare/v3.4.30...v3.4.31) (2024-06-28)\n\n\n### Bug Fixes\n\n* **compiler-core:** handle inline comments with undefined bindings ([#11217](https://github.com/vuejs/core/issues/11217)) ([746352a](https://github.com/vuejs/core/commit/746352a14d62e9d3d9a38c359d2c54d418c1e0ac)), closes [#11216](https://github.com/vuejs/core/issues/11216)\n* **shared:** unwrap refs in toDisplayString ([#7306](https://github.com/vuejs/core/issues/7306)) ([0126cff](https://github.com/vuejs/core/commit/0126cfff9d93bcec70e5745519f6378e3cd3f39c)), closes [#5578](https://github.com/vuejs/core/issues/5578) [#5593](https://github.com/vuejs/core/issues/5593) [#11199](https://github.com/vuejs/core/issues/11199) [#11201](https://github.com/vuejs/core/issues/11201)\n\n\n### Reverts\n\n* Revert \"fix(reactivity): avoid infinite loop when render access a side effect computed ([#11135](https://github.com/vuejs/core/issues/11135))\" ([e0df985](https://github.com/vuejs/core/commit/e0df985f0317fb65c5b461bf224375c7763f0269))\n* Revert \"fix(reactivity): fix side effect computed dirty level (#11183)\" ([6c303ea](https://github.com/vuejs/core/commit/6c303eacd14b7b0de0accc228f6abeb43d706f63)), closes [#11183](https://github.com/vuejs/core/issues/11183)\n\n\n\n## [3.4.30](https://github.com/vuejs/core/compare/v3.4.29...v3.4.30) (2024-06-22)\n\n**Note: this release contains a fix (#11150) that requires `vue-tsc` to also be updated in sync to ^2.0.22. See #11196**\n\n### Bug Fixes\n\n* **compiler-core:** should not remove slot node with `v-else` ([#11150](https://github.com/vuejs/core/issues/11150)) ([e102670](https://github.com/vuejs/core/commit/e102670bde00417c3a5b0262c855b297c0e4169e))\n* **hydration:** fix css vars hydration mismatch false positive on attr-fallthrough ([#11190](https://github.com/vuejs/core/issues/11190)) ([7ad67ce](https://github.com/vuejs/core/commit/7ad67ced26e5f53a47cb42f4834496e4958cb53b)), closes [#11188](https://github.com/vuejs/core/issues/11188)\n* **hydration:** skip prop mismatch check for directives that mutate DOM in created ([3169c91](https://github.com/vuejs/core/commit/3169c914939d02a013b2938aff30dac8525923f8)), closes [#11189](https://github.com/vuejs/core/issues/11189)\n* **reactivity:** fix side effect computed dirty level ([#11183](https://github.com/vuejs/core/issues/11183)) ([3bd79e3](https://github.com/vuejs/core/commit/3bd79e3e5ed960fc42cbf77bc61a97d2c03557c0)), closes [#11181](https://github.com/vuejs/core/issues/11181) [#11169](https://github.com/vuejs/core/issues/11169)\n* **runtime-core:** ensure unmount dynamic components in optimized mode ([#11171](https://github.com/vuejs/core/issues/11171)) ([220fe24](https://github.com/vuejs/core/commit/220fe247484209e62c7f4991902c5335e29c5007)), closes [#11168](https://github.com/vuejs/core/issues/11168)\n* **runtime-core:** update devtool __vnode on patch, avoid memory leak during dev ([a959781](https://github.com/vuejs/core/commit/a959781dd6f609dcb6f16dd7fa47d3b16895e5ca)), closes [#11192](https://github.com/vuejs/core/issues/11192)\n* **runtime-dom:** ensure only symbols are explicitly stringified during attribute patching ([#11182](https://github.com/vuejs/core/issues/11182)) ([a2e35d6](https://github.com/vuejs/core/commit/a2e35d682db15a592f4270bb0cde70a0e7bdc4a6)), closes [#11177](https://github.com/vuejs/core/issues/11177)\n* **runtime-dom:** prevent setting state as attribute for custom elements ([#11165](https://github.com/vuejs/core/issues/11165)) ([8ae4c29](https://github.com/vuejs/core/commit/8ae4c293adcec28f18114cb6016230a86787e6a9)), closes [#11163](https://github.com/vuejs/core/issues/11163)\n\n\n### Performance Improvements\n\n* **reactivity:** cache tracking value ([#11145](https://github.com/vuejs/core/issues/11145)) ([7936dae](https://github.com/vuejs/core/commit/7936daebceab2ae9461c3b8f256e51020fb7d3ed))\n\n\n\n## [3.4.29](https://github.com/vuejs/core/compare/v3.4.28...v3.4.29) (2024-06-14)\n\n\n### Bug Fixes\n\n* **build:** fix accidental inclusion of runtime-core in server-renderer cjs build ([11cc12b](https://github.com/vuejs/core/commit/11cc12b915edfe0e4d3175e57464f73bc2c1cb04)), closes [#11137](https://github.com/vuejs/core/issues/11137)\n* **compiler-sfc:** fix missing scope for extends error message ([4ec387b](https://github.com/vuejs/core/commit/4ec387b100985b008cdcc4cd883a5b6328c05766))\n* **compiler-sfc:** fix parsing of mts, d.mts, and mtsx files ([a476692](https://github.com/vuejs/core/commit/a476692ed2d7308f2742d8ff3554cf97a392b0b7))\n* **compiler-sfc:** support [@vue-ignore](https://github.com/vue-ignore) comment on more type sources ([a23e99b](https://github.com/vuejs/core/commit/a23e99bedf1d65841d162951f10ce35b907a5680))\n* **custom-element:** support same direct setup function signature in defineCustomElement ([7c8b126](https://github.com/vuejs/core/commit/7c8b12620aad4969b8dc4944d4fc486d16c3033c)), closes [#11116](https://github.com/vuejs/core/issues/11116)\n* **reactivity:** avoid infinite loop when render access a side effect computed ([#11135](https://github.com/vuejs/core/issues/11135)) ([8296e19](https://github.com/vuejs/core/commit/8296e19855e369a7826f5ea26540a6da01dc7093)), closes [#11121](https://github.com/vuejs/core/issues/11121)\n\n\n\n## [3.4.28](https://github.com/vuejs/core/compare/v3.4.27...v3.4.28) (2024-06-14)\n\n\n### Bug Fixes\n\n* **compat:** correctly transform non-identifier expressions in legacy filter syntax ([#10896](https://github.com/vuejs/core/issues/10896)) ([07b3c4b](https://github.com/vuejs/core/commit/07b3c4b7860009e19446f3d78571556c5737d82a)), closes [#10852](https://github.com/vuejs/core/issues/10852)\n* **compat:** ensure proper handling of render function from SFC using Vue.extend ([#7781](https://github.com/vuejs/core/issues/7781)) ([c73847f](https://github.com/vuejs/core/commit/c73847f2becc20f03cb9c68748eea92455e688ee)), closes [#7766](https://github.com/vuejs/core/issues/7766)\n* **compat:** only warn ATTR_FALSE_VALUE when enabled ([04729ba](https://github.com/vuejs/core/commit/04729ba2163d840f0ca7866bc964696eb5557804)), closes [#11126](https://github.com/vuejs/core/issues/11126)\n* **compile-sfc:** register props destructure rest id as setup bindings ([#10888](https://github.com/vuejs/core/issues/10888)) ([b2b5f57](https://github.com/vuejs/core/commit/b2b5f57c2c945edd0eebc1b545ec1b7568e51484)), closes [#10885](https://github.com/vuejs/core/issues/10885)\n* **compile-sfc:** Support project reference with folder,  ([#10908](https://github.com/vuejs/core/issues/10908)) ([bdeac37](https://github.com/vuejs/core/commit/bdeac377c7b85888193b49ac187e927636cc40bc)), closes [#10907](https://github.com/vuejs/core/issues/10907)\n* **compiler-core:** allow unicode to appear in simple identifiers ([#6765](https://github.com/vuejs/core/issues/6765)) ([3ea9644](https://github.com/vuejs/core/commit/3ea964473d3ac0ba3e7b0b2c22d71f23d0f69123)), closes [#6367](https://github.com/vuejs/core/issues/6367)\n* **compiler-core:** change v-for key type to match Object.keys ([#10963](https://github.com/vuejs/core/issues/10963)) ([9fead52](https://github.com/vuejs/core/commit/9fead5234320848f8be82275c6b5dd0a290f2cca)), closes [#8819](https://github.com/vuejs/core/issues/8819)\n* **compiler-core:** emit TS-compatible function declaration when requested ([#9363](https://github.com/vuejs/core/issues/9363)) ([5d25850](https://github.com/vuejs/core/commit/5d258502a0faffc8a451b8701f13a31b2566d068))\n* **compiler-core:** fix :key shorthand on v-for ([#10942](https://github.com/vuejs/core/issues/10942)) ([29425df](https://github.com/vuejs/core/commit/29425df1acb9e520c6ae894d06bcff73fde90edd)), closes [#10882](https://github.com/vuejs/core/issues/10882) [#10939](https://github.com/vuejs/core/issues/10939)\n* **compiler-core:** make `ForIteratorExpression`'s `returns` property optional ([#11011](https://github.com/vuejs/core/issues/11011)) ([5b8c1af](https://github.com/vuejs/core/commit/5b8c1afb74e39045fcb53a011420d26e3f67eab4))\n* **compiler-core:** should set `<math>` tag as block to retain MathML namespace after patching ([#10891](https://github.com/vuejs/core/issues/10891)) ([87c5443](https://github.com/vuejs/core/commit/87c54430448005294c41803f07f517fef848f917))\n* **compiler-core:** v-for expression missing source with spaces should emit error ([#5821](https://github.com/vuejs/core/issues/5821)) ([b9ca202](https://github.com/vuejs/core/commit/b9ca202f477be595477e182972ee9bae3f2b9f74)), closes [#5819](https://github.com/vuejs/core/issues/5819)\n* **compiler-sfc:** improve type resolving for the keyof operator ([#10921](https://github.com/vuejs/core/issues/10921)) ([293cf4e](https://github.com/vuejs/core/commit/293cf4e131b6d4606e1de2cd7ea87814e2544952)), closes [#10920](https://github.com/vuejs/core/issues/10920) [#11002](https://github.com/vuejs/core/issues/11002)\n* **compiler-sfc:** support as keyword with template literal types ([#11100](https://github.com/vuejs/core/issues/11100)) ([2594b1d](https://github.com/vuejs/core/commit/2594b1df57f672ac6621ac2880645e975fea581c)), closes [#10962](https://github.com/vuejs/core/issues/10962)\n* **compiler-sfc:** support type resolve for keyof for intersection & union types ([#11132](https://github.com/vuejs/core/issues/11132)) ([495263a](https://github.com/vuejs/core/commit/495263a9cb356861e58a4364f2570608265486b5)), closes [#11129](https://github.com/vuejs/core/issues/11129)\n* **compiler-sfc:** throw error when import macro as alias ([#11041](https://github.com/vuejs/core/issues/11041)) ([34a97ed](https://github.com/vuejs/core/commit/34a97edd2c8273c213599c44770accdb0846da8e))\n* correct the type of `<details>`'s `onToggle` event handler ([#10938](https://github.com/vuejs/core/issues/10938)) ([fd18ce7](https://github.com/vuejs/core/commit/fd18ce70b1a260a2485c9cd7faa30193da4b79f5)), closes [#10928](https://github.com/vuejs/core/issues/10928)\n* **custom-element:** disconnect MutationObserver in nextTick in case that custom elements are moved ([#10613](https://github.com/vuejs/core/issues/10613)) ([bbb5be2](https://github.com/vuejs/core/commit/bbb5be299b500a00e60c757118c846c3b5ddd8e0)), closes [#10610](https://github.com/vuejs/core/issues/10610)\n* **custom-elements:** compatibility of createElement in older versions of Chrome ([#9615](https://github.com/vuejs/core/issues/9615)) ([a88295d](https://github.com/vuejs/core/commit/a88295dc076ee867939d8b0ee2225e63c5ffb0ca)), closes [#9614](https://github.com/vuejs/core/issues/9614)\n* **hmr:** avoid infinite recursion when reloading hmr components ([#6936](https://github.com/vuejs/core/issues/6936)) ([36bd9b0](https://github.com/vuejs/core/commit/36bd9b0a1fb83e61731fb80d66e265dccbedcfa8)), closes [#6930](https://github.com/vuejs/core/issues/6930)\n* **hydration:** log hydration error even when using async components ([#9403](https://github.com/vuejs/core/issues/9403)) ([5afc76c](https://github.com/vuejs/core/commit/5afc76c229f9ad30eef07f34c7b65e8fe427e637)), closes [#9369](https://github.com/vuejs/core/issues/9369)\n* **KeepAlive:** properly cache nested Suspense subtree ([#10912](https://github.com/vuejs/core/issues/10912)) ([07764fe](https://github.com/vuejs/core/commit/07764fe330692fadf0fc9fb9e92cb5b111df33be))\n* **npm:** explicitly add `@vue/reactivity` as dependency of `@vue/runtime-dom` ([#10468](https://github.com/vuejs/core/issues/10468)) ([ec424f6](https://github.com/vuejs/core/commit/ec424f6cd96b7e6ba74fc244c484c00fa5590aac))\n* **reactivity:** pass oldValue in debug info when triggering refs ([#8210](https://github.com/vuejs/core/issues/8210)) ([3b0a56a](https://github.com/vuejs/core/commit/3b0a56a9c4d162ec3bd725a4f2dfd776b045e727)), closes [vuejs/pinia#2061](https://github.com/vuejs/pinia/issues/2061)\n* **runtime-core:** avoid traversing static children for vnodes w/ PatchFlags.BAIL ([#11115](https://github.com/vuejs/core/issues/11115)) ([b557d3f](https://github.com/vuejs/core/commit/b557d3fb8ae1e4e926c4ad0fbb2fa7abe50fd661)), closes [#10547](https://github.com/vuejs/core/issues/10547)\n* **runtime-core:** do not fire mount/activated hooks if unmounted before mounted ([#9370](https://github.com/vuejs/core/issues/9370)) ([aa156ed](https://github.com/vuejs/core/commit/aa156ed5c4dc0d33ff37e201a7e89d5e0e29160e)), closes [#8898](https://github.com/vuejs/core/issues/8898) [#9264](https://github.com/vuejs/core/issues/9264) [#9617](https://github.com/vuejs/core/issues/9617)\n* **runtime-core:** ensure suspense creates dep component's render effect with correct optimized flag ([#7689](https://github.com/vuejs/core/issues/7689)) ([c521f95](https://github.com/vuejs/core/commit/c521f956e1697cda36a7f1b913599e5e2004f7ba)), closes [#7688](https://github.com/vuejs/core/issues/7688)\n* **runtime-core:** fix missed updates when passing text vnode to `<component :is>` ([#8304](https://github.com/vuejs/core/issues/8304)) ([b310ec3](https://github.com/vuejs/core/commit/b310ec389d9738247e5b0f01711186216eb49955)), closes [#8298](https://github.com/vuejs/core/issues/8298)\n* **runtime-core:** fix stale v-memo after v-if toggle ([#6606](https://github.com/vuejs/core/issues/6606)) ([edf2638](https://github.com/vuejs/core/commit/edf263847eddc910f4d2de68287d84b8c66c3860)), closes [#6593](https://github.com/vuejs/core/issues/6593)\n* **runtime-core:** fix Transition for components with root-level v-if  ([#7678](https://github.com/vuejs/core/issues/7678)) ([ef2e737](https://github.com/vuejs/core/commit/ef2e737577de42ea38771403f8a4dee8c892daa5)), closes [#7649](https://github.com/vuejs/core/issues/7649)\n* **runtime-dom:** also set attribute for form element state ([537a571](https://github.com/vuejs/core/commit/537a571f8cf09dfe0a020e9e8891ecdd351fc3e4)), closes [#6007](https://github.com/vuejs/core/issues/6007) [#6012](https://github.com/vuejs/core/issues/6012)\n* **runtime-dom:** support Symbol for input value bindings  ([#10608](https://github.com/vuejs/core/issues/10608)) ([188f3ae](https://github.com/vuejs/core/commit/188f3ae533fd340603068a516a8fecc5d57426c5)), closes [#10597](https://github.com/vuejs/core/issues/10597)\n* **shared:** ensure invokeArrayFns handles undefined arguments ([#10869](https://github.com/vuejs/core/issues/10869)) ([9b40d0f](https://github.com/vuejs/core/commit/9b40d0f25da868a83b0d6bf99dbbdb3ca68bb700)), closes [#10863](https://github.com/vuejs/core/issues/10863)\n* **ssr:** directive binding.instance should respect exposed during ssr ([df686ab](https://github.com/vuejs/core/commit/df686abb4f0ac9d898e4fd93751e860f8cbbdbea)), closes [#7499](https://github.com/vuejs/core/issues/7499) [#7502](https://github.com/vuejs/core/issues/7502)\n* **ssr:** fix hydration for node with empty text node ([#7216](https://github.com/vuejs/core/issues/7216)) ([d1011c0](https://github.com/vuejs/core/commit/d1011c07a957d858cb37725b13bc8e4d7a395490))\n* **ssr:** fix the bug that multi slot scope id does not work on component ([#6100](https://github.com/vuejs/core/issues/6100)) ([4c74302](https://github.com/vuejs/core/commit/4c74302aae64c118752db7fc2a2c229a11ebaead)), closes [#6093](https://github.com/vuejs/core/issues/6093)\n* **teleport:** do not throw target warning when teleport is disabled ([#9818](https://github.com/vuejs/core/issues/9818)) ([15ee43f](https://github.com/vuejs/core/commit/15ee43f66ad2485ac212b02b444345d867b3c060))\n* **transition:** ensure Transition enterHooks are updated after clone ([#11066](https://github.com/vuejs/core/issues/11066)) ([671cf29](https://github.com/vuejs/core/commit/671cf297a550d15b19fa3fecce1b30e26cad8154)), closes [#11061](https://github.com/vuejs/core/issues/11061)\n* **types/apiWatch:** correct type inference for reactive array ([#11036](https://github.com/vuejs/core/issues/11036)) ([aae2d78](https://github.com/vuejs/core/commit/aae2d78875daa476280a45e71c2f38292964efae)), closes [#9416](https://github.com/vuejs/core/issues/9416)\n* **types:** improve `app.provide` type checking ([#10603](https://github.com/vuejs/core/issues/10603)) ([612bbf0](https://github.com/vuejs/core/commit/612bbf0507cbe39d701acc5dff11824802078063)), closes [#10602](https://github.com/vuejs/core/issues/10602)\n* **types:** support generic argument in setup context expose method ([#8507](https://github.com/vuejs/core/issues/8507)) ([635a59b](https://github.com/vuejs/core/commit/635a59b96fe6be445525c6595ca27da7ef7c1feb))\n* **v-model:** fix the lazy modifier is not reset by other modifications ([#8547](https://github.com/vuejs/core/issues/8547)) ([a52a02f](https://github.com/vuejs/core/commit/a52a02f43fdf73d8aaad99c9cafed07f12ee422a)), closes [#8546](https://github.com/vuejs/core/issues/8546) [#6564](https://github.com/vuejs/core/issues/6564) [#6773](https://github.com/vuejs/core/issues/6773)\n* **watch:** support traversing symbol properties in deep watcher ([#10969](https://github.com/vuejs/core/issues/10969)) ([a3e8aaf](https://github.com/vuejs/core/commit/a3e8aafbcc82003a66caded61143eb64c4ef02cd)), closes [#402](https://github.com/vuejs/core/issues/402)\n\n\n\n## [3.4.27](https://github.com/vuejs/core/compare/v3.4.26...v3.4.27) (2024-05-06)\n\n\n### Bug Fixes\n\n* **compat:** include legacy scoped slots ([#10868](https://github.com/vuejs/core/issues/10868)) ([8366126](https://github.com/vuejs/core/commit/83661264a4ced3cb2ff6800904a86dd9e82bbfe2)), closes [#8869](https://github.com/vuejs/core/issues/8869)\n* **compiler-core:** add support for arrow async function with unbracketed ([#5789](https://github.com/vuejs/core/issues/5789)) ([ca7d421](https://github.com/vuejs/core/commit/ca7d421e8775f6813f8943d32ab485e0c542f98b)), closes [#5788](https://github.com/vuejs/core/issues/5788)\n* **compiler-dom:** restrict createStaticVNode usage with option elements ([#10846](https://github.com/vuejs/core/issues/10846)) ([0e3d617](https://github.com/vuejs/core/commit/0e3d6178b02d0386d779720ae2cc4eac1d1ec990)), closes [#6568](https://github.com/vuejs/core/issues/6568) [#7434](https://github.com/vuejs/core/issues/7434)\n* **compiler-sfc:** handle keyof operator ([#10874](https://github.com/vuejs/core/issues/10874)) ([10d34a5](https://github.com/vuejs/core/commit/10d34a5624775f20437ccad074a97270ef74c3fb)), closes [#10871](https://github.com/vuejs/core/issues/10871)\n* **hydration:** handle edge case of style mismatch without style attribute ([f2c1412](https://github.com/vuejs/core/commit/f2c1412e46a8fad3e13403bfa78335c4f704f21c)), closes [#10786](https://github.com/vuejs/core/issues/10786)\n\n\n\n## [3.4.26](https://github.com/vuejs/core/compare/v3.4.25...v3.4.26) (2024-04-29)\n\n\n### Bug Fixes\n\n* **compiler-core:** fix bail constant for globals ([fefce06](https://github.com/vuejs/core/commit/fefce06b41e3b75de3d748dc6399628ec5056e78))\n* **compiler-core:** remove unnecessary constant bail check ([09b4df8](https://github.com/vuejs/core/commit/09b4df809e59ef5f4bc91acfc56dc8f82a8e243a)), closes [#10807](https://github.com/vuejs/core/issues/10807)\n* **runtime-core:** attrs should be readonly in functional components ([#10767](https://github.com/vuejs/core/issues/10767)) ([e8fd644](https://github.com/vuejs/core/commit/e8fd6446d14a6899e5e8ab1ee394d90088e01844))\n* **runtime-core:** ensure slot compiler marker writable ([#10825](https://github.com/vuejs/core/issues/10825)) ([9c2de62](https://github.com/vuejs/core/commit/9c2de6244cd44bc5fbfd82b5850c710ce725044f)), closes [#10818](https://github.com/vuejs/core/issues/10818)\n* **runtime-core:** properly handle inherit transition during clone VNode ([#10809](https://github.com/vuejs/core/issues/10809)) ([638a79f](https://github.com/vuejs/core/commit/638a79f64a7e184f2a2c65e21d764703f4bda561)), closes [#3716](https://github.com/vuejs/core/issues/3716) [#10497](https://github.com/vuejs/core/issues/10497) [#4091](https://github.com/vuejs/core/issues/4091)\n* **Transition:** re-fix [#10620](https://github.com/vuejs/core/issues/10620) ([#10832](https://github.com/vuejs/core/issues/10832)) ([accf839](https://github.com/vuejs/core/commit/accf8396ae1c9dd49759ba0546483f1d2c70c9bc)), closes [#10632](https://github.com/vuejs/core/issues/10632) [#10827](https://github.com/vuejs/core/issues/10827)\n\n\n\n## [3.4.25](https://github.com/vuejs/core/compare/v3.4.24...v3.4.25) (2024-04-24)\n\n\n### Bug Fixes\n\n* **defineModel:** align prod mode runtime type generation with defineProps ([4253a57](https://github.com/vuejs/core/commit/4253a57f1703a7f1ac701d77e0a235689203461d)), closes [#10769](https://github.com/vuejs/core/issues/10769)\n* **runtime-core:** properly get keepAlive child ([#10772](https://github.com/vuejs/core/issues/10772)) ([3724693](https://github.com/vuejs/core/commit/3724693a25c3f2dd13d70a8a1af760b03a4fb783)), closes [#10771](https://github.com/vuejs/core/issues/10771)\n* **runtime-core:** use normal object as internal prototype for attrs and slots ([064e82f](https://github.com/vuejs/core/commit/064e82f5855f30fe0b77fe9b5e4dd22700fd634d)), closes [/github.com/vuejs/core/commit/6df53d85a207986128159d88565e6e7045db2add#r141304923](https://github.com//github.com/vuejs/core/commit/6df53d85a207986128159d88565e6e7045db2add/issues/r141304923)\n\n\n\n## [3.4.24](https://github.com/vuejs/core/compare/v3.4.23...v3.4.24) (2024-04-22)\n\n\n### Bug Fixes\n\n* **compiler-core:** handle template ref bound via v-bind object on v-for ([#10706](https://github.com/vuejs/core/issues/10706)) ([da7adef](https://github.com/vuejs/core/commit/da7adefa844265eecc9c336abfc727bc05b4f16e)), closes [#10696](https://github.com/vuejs/core/issues/10696)\n* **compiler-core:** properly parse await expressions in edge cases ([b92c25f](https://github.com/vuejs/core/commit/b92c25f53dff0fc1687f57ca4033d0ac25218940)), closes [#10754](https://github.com/vuejs/core/issues/10754)\n* **compiler-sfc:** handle readonly operator and ReadonlyArray/Map/Set types ([5cef52a](https://github.com/vuejs/core/commit/5cef52a5c23ba8ba3239e6def03b8ff008d3cc72)), closes [#10726](https://github.com/vuejs/core/issues/10726)\n* **compiler-ssr:** fix hydration mismatch for conditional slot in transition ([f12c81e](https://github.com/vuejs/core/commit/f12c81efca3fcf9a7ce478af2261ad6ab9b0bfd7)), closes [#10743](https://github.com/vuejs/core/issues/10743)\n* **compiler-ssr:** fix v-html SSR for nullish values ([1ff4076](https://github.com/vuejs/core/commit/1ff407676f9495883b459779a9b0370d7588b51f)), closes [#10725](https://github.com/vuejs/core/issues/10725)\n* **deps:** update compiler ([#10760](https://github.com/vuejs/core/issues/10760)) ([15df5c1](https://github.com/vuejs/core/commit/15df5c1b261b9b471eb811fd47ab7b3cfc41cf83))\n* **runtime-core:** fix edge case of KeepAlive inside Transition with slot children ([#10719](https://github.com/vuejs/core/issues/10719)) ([e51ca61](https://github.com/vuejs/core/commit/e51ca61ca060b2772e967d169548fc2f58fce6d1)), closes [#10708](https://github.com/vuejs/core/issues/10708)\n* **runtime-core:** further fix slots _ctx check ([cde7f05](https://github.com/vuejs/core/commit/cde7f05787d16dbb93d9419ef5331adf992816fd)), closes [#10724](https://github.com/vuejs/core/issues/10724)\n* **runtime-core:** props should be readonly via direct template access ([b93f264](https://github.com/vuejs/core/commit/b93f26464785de227b88c51a88328ae80e80d804)), closes [#8216](https://github.com/vuejs/core/issues/8216) [#10736](https://github.com/vuejs/core/issues/10736)\n* **transition:** transition is breaking/flickering when enter is canceled ([#10688](https://github.com/vuejs/core/issues/10688)) ([65109a7](https://github.com/vuejs/core/commit/65109a70f187473edae8cf4df11af3c33345e6f6))\n\n\n\n## [3.4.23](https://github.com/vuejs/core/compare/v3.4.22...v3.4.23) (2024-04-16)\n\n\n### Bug Fixes\n\n* **runtime-core:** fix regression for $attrs tracking in slots ([6930e60](https://github.com/vuejs/core/commit/6930e60787e4905a50417190263ae7dd46cf5409)), closes [#10710](https://github.com/vuejs/core/issues/10710)\n* **runtime-core:** use same internal object mechanism for slots ([6df53d8](https://github.com/vuejs/core/commit/6df53d85a207986128159d88565e6e7045db2add)), closes [#10709](https://github.com/vuejs/core/issues/10709)\n\n\n\n## [3.4.22](https://github.com/vuejs/core/compare/v3.4.21...v3.4.22) (2024-04-15)\n\n\n### Bug Fixes\n\n* **compat:** fix $options mutation + adjust private API initialization ([d58d133](https://github.com/vuejs/core/commit/d58d133b1cde5085cc5ab0012d544cafd62a6ee6)), closes [#10626](https://github.com/vuejs/core/issues/10626) [#10636](https://github.com/vuejs/core/issues/10636)\n* **compile-sfc:** analyze v-bind shorthand usage in template ([#10518](https://github.com/vuejs/core/issues/10518)) ([e5919d4](https://github.com/vuejs/core/commit/e5919d4658cfe0bb18c76611dd3c3432c57f94ab)), closes [#10515](https://github.com/vuejs/core/issues/10515)\n* **compiler-core:** fix loc.source for end tags with whitespace before > ([16174da](https://github.com/vuejs/core/commit/16174da21d6c8ac0aae027dd964fc35e221ded0a)), closes [#10694](https://github.com/vuejs/core/issues/10694) [#10695](https://github.com/vuejs/core/issues/10695)\n* **compiler-core:** fix v-bind shorthand for component :is ([04af950](https://github.com/vuejs/core/commit/04af9504a720c8e6de26c04b1282cf14fa1bcee3)), closes [#10469](https://github.com/vuejs/core/issues/10469) [#10471](https://github.com/vuejs/core/issues/10471)\n* **compiler-sfc:** :is() and :where() in compound selectors ([#10522](https://github.com/vuejs/core/issues/10522)) ([660cadc](https://github.com/vuejs/core/commit/660cadc7aadb909ef33a6055c4374902a82607a4)), closes [#10511](https://github.com/vuejs/core/issues/10511)\n* **compiler-sfc:** also search for `.tsx` when type import's extension is omitted  ([#10637](https://github.com/vuejs/core/issues/10637)) ([34106bc](https://github.com/vuejs/core/commit/34106bc9c715247211273bb9c64712f04bd4879d)), closes [#10635](https://github.com/vuejs/core/issues/10635)\n* **compiler-sfc:** fix defineModel coercion for boolean + string union types ([#9603](https://github.com/vuejs/core/issues/9603)) ([0cef65c](https://github.com/vuejs/core/commit/0cef65cee411356e721bbc90d731fc52fc8fce94)), closes [#9587](https://github.com/vuejs/core/issues/9587) [#10676](https://github.com/vuejs/core/issues/10676)\n* **compiler-sfc:** fix universal selector scope ([#10551](https://github.com/vuejs/core/issues/10551)) ([54a6afa](https://github.com/vuejs/core/commit/54a6afa75a546078e901ce0882da53b97420fe94)), closes [#10548](https://github.com/vuejs/core/issues/10548)\n* **compiler-sfc:** use options module name if options provide runtimeModuleName options ([#10457](https://github.com/vuejs/core/issues/10457)) ([e76d743](https://github.com/vuejs/core/commit/e76d7430aa7470342f3fe263145a0fa92f5898ca)), closes [#10454](https://github.com/vuejs/core/issues/10454)\n* **custom-element:** avoid setting attr to null if it is removed ([#9012](https://github.com/vuejs/core/issues/9012)) ([b49306a](https://github.com/vuejs/core/commit/b49306adff4572d90a42ccd231387f16eb966bbe)), closes [#9006](https://github.com/vuejs/core/issues/9006) [#10324](https://github.com/vuejs/core/issues/10324)\n* **hydration:** properly handle optimized mode during hydrate node ([#10638](https://github.com/vuejs/core/issues/10638)) ([2ec06fd](https://github.com/vuejs/core/commit/2ec06fd6c8383e11cdf4efcab1707f973bd6a54c)), closes [#10607](https://github.com/vuejs/core/issues/10607)\n* **reactivity:** computed should not be detected as true by isProxy ([#10401](https://github.com/vuejs/core/issues/10401)) ([9da34d7](https://github.com/vuejs/core/commit/9da34d7af81607fddd1f32f21b3b4002402ff1cc))\n* **reactivity:** fix hasOwnProperty key coercion edge cases ([969c5fb](https://github.com/vuejs/core/commit/969c5fb30f4c725757c7385abfc74772514eae4b))\n* **reactivity:** fix tracking when hasOwnProperty is called with non-string value ([c3c5dc9](https://github.com/vuejs/core/commit/c3c5dc93fbccc196771458f0b43cd5b7ad1863f4)), closes [#10455](https://github.com/vuejs/core/issues/10455) [#10464](https://github.com/vuejs/core/issues/10464)\n* **runtime-core:** fix errorHandler causes an infinite loop during execution ([#9575](https://github.com/vuejs/core/issues/9575)) ([ab59bed](https://github.com/vuejs/core/commit/ab59bedae4e5e40b28804d88a51305b236d4a873))\n* **runtime-core:** handle invalid values in callWithAsyncErrorHandling ([53d15d3](https://github.com/vuejs/core/commit/53d15d3f76184eed67a18d35e43d9a2062f8e121))\n* **runtime-core:** show hydration mismatch details for non-rectified mismatches too when __PROD_HYDRATION_MISMATCH_DETAILS__ is set ([#10599](https://github.com/vuejs/core/issues/10599)) ([0dea7f9](https://github.com/vuejs/core/commit/0dea7f9a260d93eb6c39aabac8c94c2c9b2042dd))\n* **runtime-dom:** `v-model` string/number coercion for multiselect options ([#10576](https://github.com/vuejs/core/issues/10576)) ([db374e5](https://github.com/vuejs/core/commit/db374e54c9f5e07324728b85c74eca84e28dd352))\n* **runtime-dom:** fix css v-bind for suspensed components ([#8523](https://github.com/vuejs/core/issues/8523)) ([67722ba](https://github.com/vuejs/core/commit/67722ba23b7c36ab8f3fa2d2b4df08e4ddc322e1)), closes [#8520](https://github.com/vuejs/core/issues/8520)\n* **runtime-dom:** force update v-model number with leading 0 ([#10506](https://github.com/vuejs/core/issues/10506)) ([15ffe8f](https://github.com/vuejs/core/commit/15ffe8f2c954359770c57e4d9e589b0b622e4a60)), closes [#10503](https://github.com/vuejs/core/issues/10503) [#10615](https://github.com/vuejs/core/issues/10615)\n* **runtime-dom:** sanitize wrongly passed string value as event handler ([#8953](https://github.com/vuejs/core/issues/8953)) ([7ccd453](https://github.com/vuejs/core/commit/7ccd453dd004076cad49ec9f56cd5fe97b7b6ed8)), closes [#8818](https://github.com/vuejs/core/issues/8818)\n* **ssr:** don't render v-if comments in TransitionGroup ([#6732](https://github.com/vuejs/core/issues/6732)) ([5a96267](https://github.com/vuejs/core/commit/5a9626708e970c6fc0b6f786e3c80c22273d126f)), closes [#6715](https://github.com/vuejs/core/issues/6715)\n* **Transition:** ensure the KeepAlive children unmount w/ out-in mode ([#10632](https://github.com/vuejs/core/issues/10632)) ([fc99e4d](https://github.com/vuejs/core/commit/fc99e4d3f01b190ef9fd3c218a668ba9124a32bc)), closes [#10620](https://github.com/vuejs/core/issues/10620)\n* **TransitionGroup:** avoid set transition hooks for comment nodes and text nodes ([#9421](https://github.com/vuejs/core/issues/9421)) ([140a768](https://github.com/vuejs/core/commit/140a7681cc3bba22f55d97fd85a5eafe97a1230f)), closes [#4621](https://github.com/vuejs/core/issues/4621) [#4622](https://github.com/vuejs/core/issues/4622) [#5153](https://github.com/vuejs/core/issues/5153) [#5168](https://github.com/vuejs/core/issues/5168) [#7898](https://github.com/vuejs/core/issues/7898) [#9067](https://github.com/vuejs/core/issues/9067)\n* **types:** avoid merging object union types when using withDefaults ([#10596](https://github.com/vuejs/core/issues/10596)) ([37ba93c](https://github.com/vuejs/core/commit/37ba93c213a81f99a68a99ef5d4065d61b150ba3)), closes [#10594](https://github.com/vuejs/core/issues/10594)\n\n\n### Performance Improvements\n\n* add `__NO_SIDE_EFFECTS__` comments ([#9053](https://github.com/vuejs/core/issues/9053)) ([d46df6b](https://github.com/vuejs/core/commit/d46df6bdb14b0509eb2134b3f85297a306821c61))\n* optimize component props/slots internal object checks ([6af733d](https://github.com/vuejs/core/commit/6af733d68eb400a3d2c5ef5f465fff32b72a324e))\n* **ssr:** avoid calling markRaw on component instance proxy ([4bc9f39](https://github.com/vuejs/core/commit/4bc9f39f028af7313e5cf24c16915a1985d27bf8))\n* **ssr:** optimize setup context creation for ssr in v8 ([ca84316](https://github.com/vuejs/core/commit/ca84316bfb3410efe21333670a6ad5cd21857396))\n\n\n\n## [3.4.21](https://github.com/vuejs/core/compare/v3.4.20...v3.4.21) (2024-02-28)\n\n\n### Bug Fixes\n\n* **runtime-dom:** avoid unset option's value ([#10416](https://github.com/vuejs/core/issues/10416)) ([b3f8b5a](https://github.com/vuejs/core/commit/b3f8b5a4e700d4c47a146b6040882287d180f6cb)), closes [#10412](https://github.com/vuejs/core/issues/10412) [#10396](https://github.com/vuejs/core/issues/10396)\n* **suspense:** ensure nested suspense patching if in fallback state ([#10417](https://github.com/vuejs/core/issues/10417)) ([7c97778](https://github.com/vuejs/core/commit/7c97778aec1e3513035e5df265e1b8a7801f6106)), closes [#10415](https://github.com/vuejs/core/issues/10415)\n* **warning:** stringify args in warn handler ([#10414](https://github.com/vuejs/core/issues/10414)) ([bc37258](https://github.com/vuejs/core/commit/bc37258caa2f6f67f4554ab8587aca3798d92124)), closes [#10409](https://github.com/vuejs/core/issues/10409)\n\n\n\n## [3.4.20](https://github.com/vuejs/core/compare/v3.4.19...v3.4.20) (2024-02-26)\n\n\n### Bug Fixes\n\n* **parser:** should not treat uppercase components as special tags ([e0e0253](https://github.com/vuejs/core/commit/e0e02535cdea1aeb1cfaff0d61d4b2555e555c36)), closes [#10395](https://github.com/vuejs/core/issues/10395)\n* **runtime-dom:** avoid always resetting nullish option value ([ff130c4](https://github.com/vuejs/core/commit/ff130c470204086edaa093fb8fdc1247c69cba69)), closes [#10396](https://github.com/vuejs/core/issues/10396)\n* **runtime-dom:** fix nested v-show priority regression ([364f890](https://github.com/vuejs/core/commit/364f8902c8657faec7c3a4d70a5b2c856567e92d)), closes [#10338](https://github.com/vuejs/core/issues/10338)\n* **runtime-dom:** v-bind style should clear previous css string value ([#10373](https://github.com/vuejs/core/issues/10373)) ([e2d3235](https://github.com/vuejs/core/commit/e2d323538e71d404e729148fd19a08bbc2e3da9b)), closes [#10352](https://github.com/vuejs/core/issues/10352)\n* **suspense:** handle suspense switching with nested suspense  ([#10184](https://github.com/vuejs/core/issues/10184)) ([0f3da05](https://github.com/vuejs/core/commit/0f3da05ea201761529bb95594df1e2cee20b7107)), closes [#10098](https://github.com/vuejs/core/issues/10098)\n* **types:** better typing for direct setup signature of defineComponent ([#10357](https://github.com/vuejs/core/issues/10357)) ([eadce5b](https://github.com/vuejs/core/commit/eadce5b75356656fd2209ebdb406d34823c961b7)), closes [#8604](https://github.com/vuejs/core/issues/8604) [#8855](https://github.com/vuejs/core/issues/8855)\n\n\n\n## [3.4.19](https://github.com/vuejs/core/compare/v3.4.18...v3.4.19) (2024-02-13)\n\n\n### Bug Fixes\n\n* **deps:** pin lru-cache to avoid hashing error ([b8be990](https://github.com/vuejs/core/commit/b8be99018ceae92d1732dfb414df12b36b90b31f)), closes [#10300](https://github.com/vuejs/core/issues/10300)\n* **hydration:** fix css vars hydration mismatch false positive on non-root nodes ([995d2fd](https://github.com/vuejs/core/commit/995d2fdcca485c24849c99f498c1edc163722e04)), closes [#10317](https://github.com/vuejs/core/issues/10317) [#10325](https://github.com/vuejs/core/issues/10325)\n* **runtime-dom:** should not trigger transition when v-show value is falsy ([#10311](https://github.com/vuejs/core/issues/10311)) ([e509639](https://github.com/vuejs/core/commit/e50963903d93a7f24003b6e2c03647fdf7454b1e))\n\n\n### Features\n\n> Note: this warning is categorized as a feature but released in a patch because it does not affect public APIs.\n\n* **dx:** warn users when computed is self-triggering ([#10299](https://github.com/vuejs/core/issues/10299)) ([f7ba97f](https://github.com/vuejs/core/commit/f7ba97f9754a9882c1f6b1c07ca1a4040479dd13))\n\n\n### Performance Improvements\n\n* **runtime:** improve `getType()` GC and speed ([#10327](https://github.com/vuejs/core/issues/10327)) ([603a1e1](https://github.com/vuejs/core/commit/603a1e1f5ad587c077f0d974c1bbe856be22ebe9))\n\n\n\n## [3.4.18](https://github.com/vuejs/core/compare/v3.4.17...v3.4.18) (2024-02-09)\n\n\n### Bug Fixes\n\n* **dx:** warn against reserved keys as prop name ([77a804b](https://github.com/vuejs/core/commit/77a804b1d0d6a3f12fb3674cdceb85ebd6481e02)), closes [#10281](https://github.com/vuejs/core/issues/10281)\n* **runtime-dom:**  ensure v-show respects display value set via v-bind ([#10297](https://github.com/vuejs/core/issues/10297)) ([c224897](https://github.com/vuejs/core/commit/c224897dd4e189a10ec601a97fe08cb638ebee19)), closes [#10151](https://github.com/vuejs/core/issues/10151)\n\n\n\n## [3.4.17](https://github.com/vuejs/core/compare/v3.4.16...v3.4.17) (2024-02-09)\n\n\n### Reverts\n\n* fix(runtime-dom): ensure v-show respects display value set via v-bind ([#10161](https://github.com/vuejs/core/issues/10161)) ([2cd5b05](https://github.com/vuejs/core/commit/2cd5b05c3bf171be5c0b473c084c01704a058ffa)), closes [#10294](https://github.com/vuejs/core/issues/10294) [#10151](https://github.com/vuejs/core/issues/10151)\n\n\n\n## [3.4.16](https://github.com/vuejs/core/compare/v3.4.15...v3.4.16) (2024-02-08)\n\n\n### Bug Fixes\n\n* **compiler-core:** handle same-name shorthand edge case for in-DOM templates ([cb87b62](https://github.com/vuejs/core/commit/cb87b6213d7b003fa7280712c285c7c9d9f291ca)), closes [#10280](https://github.com/vuejs/core/issues/10280)\n* **compiler-core:** support v-bind shorthand syntax for dynamic slot name ([#10218](https://github.com/vuejs/core/issues/10218)) ([91f058a](https://github.com/vuejs/core/commit/91f058a90cd603492649633d153b120977c4df6b)), closes [#10213](https://github.com/vuejs/core/issues/10213)\n* **deps:** update compiler ([#10269](https://github.com/vuejs/core/issues/10269)) ([336bb65](https://github.com/vuejs/core/commit/336bb65820243006efdf990e6ea3610696467508))\n* **hydration:** fix SFC style v-bind hydration mismatch warnings ([#10250](https://github.com/vuejs/core/issues/10250)) ([f0b5f7e](https://github.com/vuejs/core/commit/f0b5f7ed8ddf74f9f5ba47cb65e8300370875291)), closes [#10215](https://github.com/vuejs/core/issues/10215)\n* **reactivity:** avoid infinite recursion from side effects in computed getter ([#10232](https://github.com/vuejs/core/issues/10232)) ([0bced13](https://github.com/vuejs/core/commit/0bced13ee5c53a02d5f10e5db76fe38b6e131440)), closes [#10214](https://github.com/vuejs/core/issues/10214)\n* **reactivity:** handle `MaybeDirty` recurse ([#10187](https://github.com/vuejs/core/issues/10187)) ([6c7e0bd](https://github.com/vuejs/core/commit/6c7e0bd88f021b0b6365370e97b0c7e243d7d70b)), closes [#10185](https://github.com/vuejs/core/issues/10185)\n* **reactivity:** skip non-extensible objects when using `markRaw` ([#10289](https://github.com/vuejs/core/issues/10289)) ([2312184](https://github.com/vuejs/core/commit/2312184bc335e0d32aa4c0c0b49190b6334849b4)), closes [#10288](https://github.com/vuejs/core/issues/10288)\n* **runtime-core:** avoid inlining isShallow ([#10238](https://github.com/vuejs/core/issues/10238)) ([53eee72](https://github.com/vuejs/core/commit/53eee72c3a96420db35236b5e8e4d9308a56e1b4))\n* **runtime-core:** support for nested calls to runWithContext ([#10261](https://github.com/vuejs/core/issues/10261)) ([75e02b5](https://github.com/vuejs/core/commit/75e02b5099a08166bdf407127916734c48209ee9)), closes [#10260](https://github.com/vuejs/core/issues/10260)\n* **runtime-dom:** ensure v-show respects display value set via v-bind ([#10161](https://github.com/vuejs/core/issues/10161)) ([9b19f09](https://github.com/vuejs/core/commit/9b19f0912104bfccb10c8cf5beab02b21a648935)), closes [#10151](https://github.com/vuejs/core/issues/10151)\n* **runtime-dom:** fix option selected update failed ([#10200](https://github.com/vuejs/core/issues/10200)) ([f31d782](https://github.com/vuejs/core/commit/f31d782e4668050a188ac0f11ba8d5b861b913ca)), closes [#10194](https://github.com/vuejs/core/issues/10194) [#10267](https://github.com/vuejs/core/issues/10267)\n\n\n### Reverts\n\n* perf(templateRef): avoid double render when using template ref on v-for ([eb1b911](https://github.com/vuejs/core/commit/eb1b9116d7cd4a5747e8dadcdc5ba921df011f64)), closes [#9908](https://github.com/vuejs/core/issues/9908) [#10210](https://github.com/vuejs/core/issues/10210) [#10234](https://github.com/vuejs/core/issues/10234)\n\n\n\n## [3.4.15](https://github.com/vuejs/core/compare/v3.4.14...v3.4.15) (2024-01-18)\n\n\n### Bug Fixes\n\n* **compiler-sfc:** fix type resolution for symlinked node_modules structure w/ pnpm ([75e866b](https://github.com/vuejs/core/commit/75e866bd4ef368b4e037a4933dbaf188920dc683)), closes [#10121](https://github.com/vuejs/core/issues/10121)\n* correct url for production error reference links ([c3087ff](https://github.com/vuejs/core/commit/c3087ff2cce7d96c60a870f8233441311ab4dfb4))\n* **hydration:** fix incorrect mismatch warning for option with non-string value and inner text ([d16a213](https://github.com/vuejs/core/commit/d16a2138a33b106b9e1499bbb9e1c67790370c97))\n* **reactivity:** re-fix [#10114](https://github.com/vuejs/core/issues/10114) ([#10123](https://github.com/vuejs/core/issues/10123)) ([c2b274a](https://github.com/vuejs/core/commit/c2b274a887f61deb7e0185d1bef3b77d31e991cc))\n* **runtime-core:** should not warn out-of-render slot fn usage when mounting another app in setup ([#10125](https://github.com/vuejs/core/issues/10125)) ([6fa33e6](https://github.com/vuejs/core/commit/6fa33e67ec42af140a86fbdb86939032c3a1f345)), closes [#10124](https://github.com/vuejs/core/issues/10124)\n\n\n### Performance Improvements\n\n* **templateRef:** avoid double render when using template ref on v-for ([de4d2e2](https://github.com/vuejs/core/commit/de4d2e2143ea8397cebeb1c7a57a60007b283c9f)), closes [#9908](https://github.com/vuejs/core/issues/9908)\n* **v-model:** optimize v-model multiple select w/ large lists ([2ffb956](https://github.com/vuejs/core/commit/2ffb956efe692da059f4895669084c5278871351)), closes [#10014](https://github.com/vuejs/core/issues/10014)\n\n\n\n## [3.4.14](https://github.com/vuejs/core/compare/v3.4.13...v3.4.14) (2024-01-15)\n\n\n### Bug Fixes\n\n* **compiler-sfc:** enable prefixIdentifiers by default when reparsing on consumed AST ([#10105](https://github.com/vuejs/core/issues/10105)) ([48bf8e4](https://github.com/vuejs/core/commit/48bf8e4c708ec620e4852d71c8713394457108ee))\n* **deps:** update dependency postcss to ^8.4.33 ([#10110](https://github.com/vuejs/core/issues/10110)) ([a557006](https://github.com/vuejs/core/commit/a557006f8e7f110c6f322de38931dceaab8e9cbb))\n* **reactivity:** fix regression for computed with mutation ([#10119](https://github.com/vuejs/core/issues/10119)) ([20f62af](https://github.com/vuejs/core/commit/20f62afaafd422e42b99dde9c16f9a4ebfb9c5f7)), closes [#10114](https://github.com/vuejs/core/issues/10114)\n\n\n\n## [3.4.13](https://github.com/vuejs/core/compare/v3.4.12...v3.4.13) (2024-01-13)\n\n\n### Bug Fixes\n\n* **reactivity:** fix dirtyLevel checks for recursive effects ([#10101](https://github.com/vuejs/core/issues/10101)) ([e45a8d2](https://github.com/vuejs/core/commit/e45a8d24b46c174deb46ed952bdaf54c81ad5a85)), closes [#10082](https://github.com/vuejs/core/issues/10082)\n\n\n\n## [3.4.12](https://github.com/vuejs/core/compare/v3.4.11...v3.4.12) (2024-01-13)\n\n\n### Reverts\n\n* fix(reactivity): correct dirty assign in render function ([#10091](https://github.com/vuejs/core/issues/10091)) ([8b18481](https://github.com/vuejs/core/commit/8b1848173b0bc8fd84ce1da1af8d373c044bf073)), closes [#10098](https://github.com/vuejs/core/issues/10098) [#10100](https://github.com/vuejs/core/issues/10100)\n\n\n\n## [3.4.11](https://github.com/vuejs/core/compare/v3.4.10...v3.4.11) (2024-01-12)\n\n\n### Bug Fixes\n\n* **hydration:** improve mismatch when client value is null or undefined ([#10086](https://github.com/vuejs/core/issues/10086)) ([08b60f5](https://github.com/vuejs/core/commit/08b60f5d0d5b57fcf3347ef66cbeab472c475a88))\n* **reactivity:** correct dirty assign in render function ([#10091](https://github.com/vuejs/core/issues/10091)) ([8d04205](https://github.com/vuejs/core/commit/8d042050411fdf04d9d1d6c153287164b12e0255)), closes [#10082](https://github.com/vuejs/core/issues/10082)\n* **runtime-core:** filter single root for nested DEV_ROOT_FRAGMENT ([#8593](https://github.com/vuejs/core/issues/8593)) ([d35b877](https://github.com/vuejs/core/commit/d35b87725ab3e2bdc86fb5781ab34939f7ec1029)), closes [#5203](https://github.com/vuejs/core/issues/5203) [#8581](https://github.com/vuejs/core/issues/8581) [#10087](https://github.com/vuejs/core/issues/10087)\n\n\n\n## [3.4.10](https://github.com/vuejs/core/compare/v3.4.9...v3.4.10) (2024-01-11)\n\n\n### Bug Fixes\n\n* **hydration:** should not warn on falsy bindings of non-property keys ([3907c87](https://github.com/vuejs/core/commit/3907c87ce23cc6ef4a739b5a66ddb553e8723114))\n\n\n\n## [3.4.9](https://github.com/vuejs/core/compare/v3.4.8...v3.4.9) (2024-01-11)\n\n\n### Bug Fixes\n\n* **build:** avoid accessing __FEATURE_PROD_DEVTOOLS__ flag in root scope ([dfd9654](https://github.com/vuejs/core/commit/dfd9654665890d1bc7129f6e3c2faaa5b1f28f72))\n* **hydration:** do not warn against bindings w/ object values ([dcc68ef](https://github.com/vuejs/core/commit/dcc68ef7d48973abd8dd3178b46e50e3b0785ea4))\n* **runtime-dom:** unify behavior for v-show + style display binding ([#10075](https://github.com/vuejs/core/issues/10075)) ([cd419ae](https://github.com/vuejs/core/commit/cd419aec3cb615eaea8b2324356f38f4c0ff1fcc)), closes [#10074](https://github.com/vuejs/core/issues/10074)\n* **suspense:** avoid double-patching nested suspense when parent suspense is not resolved ([#10055](https://github.com/vuejs/core/issues/10055)) ([bcda96b](https://github.com/vuejs/core/commit/bcda96b525801eb7a1d397300fb3f2f9b827ddfb)), closes [#8678](https://github.com/vuejs/core/issues/8678)\n\n\n\n## [3.4.8](https://github.com/vuejs/core/compare/v3.4.7...v3.4.8) (2024-01-10)\n\n\n### Bug Fixes\n\n* **hydration:** fix class and style hydration mismatch message ([5af3987](https://github.com/vuejs/core/commit/5af398729168481c3bee741b4f36fa4f375e0f4a)), closes [#10067](https://github.com/vuejs/core/issues/10067)\n* **hydration:** improve attr hydration mismatch check for boolean attrs ([972face](https://github.com/vuejs/core/commit/972facee0d892a1b6d9d4ad1da5da9306ed45c3f)), closes [#10057](https://github.com/vuejs/core/issues/10057) [#10060](https://github.com/vuejs/core/issues/10060)\n* **suspense:** fix more suspense patch before resolve edge cases ([70ad4ca](https://github.com/vuejs/core/commit/70ad4caad7d19938f8ccf1ede3228a81254dd4bf)), closes [#10017](https://github.com/vuejs/core/issues/10017)\n\n\n\n## [3.4.7](https://github.com/vuejs/core/compare/v3.4.6...v3.4.7) (2024-01-09)\n\n\n### Bug Fixes\n\n* **parser:** skip compat mode check for SFC root `<template>` tags ([#10034](https://github.com/vuejs/core/issues/10034)) ([923d560](https://github.com/vuejs/core/commit/923d560d0b6713144671809b6dfeb1e2da503b1f))\n* **types:** fix functional component for `h` ([#9991](https://github.com/vuejs/core/issues/9991)) ([438a74a](https://github.com/vuejs/core/commit/438a74aad840183286fbdb488178510f37218a73))\n\n\n### Reverts\n\n* \"dx(computed): warn incorrect use of getCurrentInstance inside computed\" ([2fd3905](https://github.com/vuejs/core/commit/2fd39057386644c8bfee426c60a51f2b07a79b09))\n\n\n\n## [3.4.6](https://github.com/vuejs/core/compare/v3.4.5...v3.4.6) (2024-01-08)\n\n\n### Bug Fixes\n\n* **build:** revert \"build: add production/development export conditions ([#9977](https://github.com/vuejs/core/issues/9977))\" ([7bd4e90](https://github.com/vuejs/core/commit/7bd4e90506547c42234165776b01793abd37b148)), closes [#10012](https://github.com/vuejs/core/issues/10012) [#10020](https://github.com/vuejs/core/issues/10020)\n* fix post watcher fire timing on nested app mounts ([3c3561e](https://github.com/vuejs/core/commit/3c3561e7203091f49d57f1da6d822c91e462bc46)), closes [#10005](https://github.com/vuejs/core/issues/10005)\n* **hydration:** avoid hydration mismatch warning for styles with different order ([#10011](https://github.com/vuejs/core/issues/10011)) ([2701355](https://github.com/vuejs/core/commit/2701355e8eb07ab664e398d9fc05d6c4e2e9b20e)), closes [#10000](https://github.com/vuejs/core/issues/10000) [#10006](https://github.com/vuejs/core/issues/10006)\n* **runtime-core:** handle fragment with null children ([#10010](https://github.com/vuejs/core/issues/10010)) ([3bf34b7](https://github.com/vuejs/core/commit/3bf34b767e4dd3cf6a974301ecf0363ae4dda4ec)), closes [#10007](https://github.com/vuejs/core/issues/10007)\n* **scheduler:** sort nested postFlushCbs ([d9162df](https://github.com/vuejs/core/commit/d9162dfc2ee0c3a369fb9bf32ff413e74761bee6)), closes [#10003](https://github.com/vuejs/core/issues/10003)\n* **suspense:** fix anchor for suspense with transition out-in ([#9999](https://github.com/vuejs/core/issues/9999)) ([a3fbf21](https://github.com/vuejs/core/commit/a3fbf2132b0cd3655e969e290548c8fabc08fd33)), closes [#9996](https://github.com/vuejs/core/issues/9996)\n* **types:** allow `null` type for textarea value ([#9997](https://github.com/vuejs/core/issues/9997)) ([c379bc2](https://github.com/vuejs/core/commit/c379bc29efc70d6ac5840de10c357ee3dad998c0)), closes [#9904](https://github.com/vuejs/core/issues/9904)\n\n\n\n## [3.4.5](https://github.com/vuejs/core/compare/v3.4.4...v3.4.5) (2024-01-04)\n\n\n### Bug Fixes\n\n* **compiler-sfc:** fix co-usage of defineModel transform options and props destructure ([b20350d](https://github.com/vuejs/core/commit/b20350ded562d27e5901f308d0bc13344f840c4a)), closes [#9972](https://github.com/vuejs/core/issues/9972)\n* **compiler-sfc:** fix sfc template unref rewrite for class instantiation ([ae60a91](https://github.com/vuejs/core/commit/ae60a91cc23424493071ad9088782763eb1e8ff7)), closes [#6483](https://github.com/vuejs/core/issues/6483) [#6491](https://github.com/vuejs/core/issues/6491)\n* **compiler-ssr:** fix node clone edge case caused by AST reuse ([#9983](https://github.com/vuejs/core/issues/9983)) ([7dbdb3e](https://github.com/vuejs/core/commit/7dbdb3edf0ab648965331ca42f069387c97a1c8a)), closes [#9981](https://github.com/vuejs/core/issues/9981)\n* **watch:** cleanup watcher effect from scope when manually stopped ([#9978](https://github.com/vuejs/core/issues/9978)) ([d2d8955](https://github.com/vuejs/core/commit/d2d89551bb06dc05cb7ae0496b8f345ae0de78ed))\n\n\n\n## [3.4.4](https://github.com/vuejs/core/compare/v3.4.3...v3.4.4) (2024-01-03)\n\n\n### Bug Fixes\n\n* **compiler-sfc:** fix scss source map regression ([71d3121](https://github.com/vuejs/core/commit/71d3121b72c449351e718ee1539bdfa35b68bb32)), closes [#9970](https://github.com/vuejs/core/issues/9970) [#9969](https://github.com/vuejs/core/issues/9969)\n* **compiler-sfc:** use compilerOptions when re-parsing consumed AST ([d94d8d4](https://github.com/vuejs/core/commit/d94d8d4bffd1daf171a655b292745ffc3e63052d))\n* **defineModel:** support kebab-case/camelCase mismatches ([#9950](https://github.com/vuejs/core/issues/9950)) ([10ccb9b](https://github.com/vuejs/core/commit/10ccb9bfa0f5f3016207fc32b9611bab98e6f090))\n* **runtime-core:** correctly assign suspenseId to avoid conflicts with the default id ([#9966](https://github.com/vuejs/core/issues/9966)) ([0648804](https://github.com/vuejs/core/commit/06488047c184dae3070d0008379716690edceb46)), closes [#9944](https://github.com/vuejs/core/issues/9944)\n* **ssr:** avoid rendering transition-group slot content as a fragment ([#9961](https://github.com/vuejs/core/issues/9961)) ([0160264](https://github.com/vuejs/core/commit/0160264d677478ee928e8e851f39a9e94f97e337)), closes [#9933](https://github.com/vuejs/core/issues/9933)\n* **watch:** remove instance unmounted short circuit in getter of `watchEffect` ([#9948](https://github.com/vuejs/core/issues/9948)) ([f300a40](https://github.com/vuejs/core/commit/f300a4001ec40cadef2520267eb5841ab48cf005))\n* **watch:** revert watch behavior when watching shallow reactive objects ([a9f781a](https://github.com/vuejs/core/commit/a9f781a92cbc7de7b25c9e3d5b1295ca99eb6d86)), closes [#9965](https://github.com/vuejs/core/issues/9965)\n\n\n### Performance Improvements\n\n* **watch:** avoid double traverse for reactive source ([24d77c2](https://github.com/vuejs/core/commit/24d77c25ce5d5356adb5367beef1d23e6e340b35))\n\n\n\n## [3.4.3](https://github.com/vuejs/core/compare/v3.4.2...v3.4.3) (2023-12-30)\n\n\n### Bug Fixes\n\n* **compiler-sfc:** respect sfc parse options in cache key ([b8d58ec](https://github.com/vuejs/core/commit/b8d58ec4f42cbeb9443bf06138add46158db9af0))\n\n\n\n## [3.4.2](https://github.com/vuejs/core/compare/v3.4.1...v3.4.2) (2023-12-30)\n\n\n### Bug Fixes\n\n* **compiler-sfc:** fix dev regression for dot / namespace component usage ([dce99c1](https://github.com/vuejs/core/commit/dce99c12df981ca45a4d848c37ba8b16496025f0)), closes [#9947](https://github.com/vuejs/core/issues/9947)\n* **runtime-core:** support deep: false when watch reactive ([#9928](https://github.com/vuejs/core/issues/9928)) ([4f703d1](https://github.com/vuejs/core/commit/4f703d120d76d711084346f73ea295c73e6ef6b6)), closes [#9916](https://github.com/vuejs/core/issues/9916)\n* **ssr:** fix hydration error for slot outlet inside transition-group ([#9937](https://github.com/vuejs/core/issues/9937)) ([6cb00ed](https://github.com/vuejs/core/commit/6cb00ed0f9b64428ec18fada0f68467d6a813fde)), closes [#9933](https://github.com/vuejs/core/issues/9933)\n\n\n\n## [3.4.1](https://github.com/vuejs/core/compare/v3.4.0...v3.4.1) (2023-12-30)\n\n\n### Bug Fixes\n\n* **compat:** correct enum value for COMPILER_FILTERS feature ([#9875](https://github.com/vuejs/core/issues/9875)) ([77d33e2](https://github.com/vuejs/core/commit/77d33e263cf19983caf4e5c53a0eb0bee374843c))\n* **defineModel:** always default modifiers to empty object ([9bc3c7e](https://github.com/vuejs/core/commit/9bc3c7e29cf15f5ca96703542d10cfd786a3fc55)), closes [#9945](https://github.com/vuejs/core/issues/9945)\n* **defineModel:** support local mutation when only prop but no listener is passed ([97ce041](https://github.com/vuejs/core/commit/97ce041910b6ca4bef10f939493d6b5a06ea5b07))\n* **types:** fix defineModel watch type error ([#9942](https://github.com/vuejs/core/issues/9942)) ([4af8583](https://github.com/vuejs/core/commit/4af85835f7e593a7dffa7dc7e99f14877eb70fd1)), closes [#9939](https://github.com/vuejs/core/issues/9939)\n\n\n### Features\n\n* **compiler-sfc:** support passing template parsing options when parsing sfc ([6fab855](https://github.com/vuejs/core/commit/6fab8551e4aeef4610987640de8b435b1ae321bb)) (necessary to fix https://github.com/vitejs/vite-plugin-vue/issues/322)\n\n\n\n# [3.4.0 Slam Dunk](https://github.com/vuejs/core/compare/v3.4.0-rc.3...v3.4.0) (2023-12-29)\n\n> Read [this blog post](https://blog.vuejs.org/posts/vue-3-4) for an overview of the release highlights.\n\n### Potential Actions Needed\n\n1. To fully leverage new features in 3.4, it is recommended to also update the following dependencies when upgrading to 3.4:\n\n   - Volar / vue-tsc@^1.8.27 (**required**)\n   - @vitejs/plugin-vue@^5.0.0 (if using Vite)\n   - nuxt@^3.9.0 (if using Nuxt)\n   - vue-loader@^17.4.0 (if using webpack or vue-cli)\n\n2. If using TSX with Vue, check actions needed in [Removed: Global JSX Namespace](https://blog.vuejs.org/posts/vue-3-4#global-jsx-namespace).\n\n3. Make sure you are no longer using any deprecated features (if you are, you should have warnings in the console telling you so). They may have been [removed in 3.4](https://blog.vuejs.org/posts/vue-3-4#other-removed-features).\n\n### Features\n\n* **general:** MathML support ([#7836](https://github.com/vuejs/core/issues/7836)) ([d42b6ba](https://github.com/vuejs/core/commit/d42b6ba3f530746eb1221eb7a4be0f44eb56f7d3)), closes [#7820](https://github.com/vuejs/core/issues/7820)\n* **reactivity:** more efficient reactivity system ([#5912](https://github.com/vuejs/core/issues/5912)) ([16e06ca](https://github.com/vuejs/core/commit/16e06ca08f5a1e2af3fc7fb35de153dbe0c3087d)), closes [#311](https://github.com/vuejs/core/issues/311) [#1811](https://github.com/vuejs/core/issues/1811) [#6018](https://github.com/vuejs/core/issues/6018) [#7160](https://github.com/vuejs/core/issues/7160) [#8714](https://github.com/vuejs/core/issues/8714) [#9149](https://github.com/vuejs/core/issues/9149) [#9419](https://github.com/vuejs/core/issues/9419) [#9464](https://github.com/vuejs/core/issues/9464)\n* **reactivity:** expose last result for computed getter ([#9497](https://github.com/vuejs/core/issues/9497)) ([48b47a1](https://github.com/vuejs/core/commit/48b47a1ab63577e2dbd91947eea544e3ef185b85))\n* **runtime-core / dx:** link errors to docs in prod build ([#9165](https://github.com/vuejs/core/issues/9165)) ([9f8ba98](https://github.com/vuejs/core/commit/9f8ba9821fe166f77e63fa940e9e7e13ec3344fa))\n* **runtime-core:** add `once` option to watch ([#9034](https://github.com/vuejs/core/issues/9034)) ([a645e7a](https://github.com/vuejs/core/commit/a645e7aa51006516ba668b3a4365d296eb92ee7d))\n* **runtime-core:** provide full props to props validator functions ([#3258](https://github.com/vuejs/core/issues/3258)) ([8e27692](https://github.com/vuejs/core/commit/8e27692029a4645cd54287f776c0420f2b82740b))\n* **compiler-core:** export error message ([#8729](https://github.com/vuejs/core/issues/8729)) ([f7e80ee](https://github.com/vuejs/core/commit/f7e80ee4a065a9eaba98720abf415d9e87756cbd))\n* **compiler-core:** support specifying root namespace when parsing ([40f72d5](https://github.com/vuejs/core/commit/40f72d5e50b389cb11b7ca13461aa2a75ddacdb4))\n* **compiler-core:** support v-bind shorthand for key and value with the same name ([#9451](https://github.com/vuejs/core/issues/9451)) ([26399aa](https://github.com/vuejs/core/commit/26399aa6fac1596b294ffeba06bb498d86f5508c))\n* **compiler-core:** improve parsing tolerance for language-tools ([41ff68e](https://github.com/vuejs/core/commit/41ff68ea579d933333392146625560359acb728a))\n* **compiler-core:** support accessing Error as global in template expressions ([#7018](https://github.com/vuejs/core/issues/7018)) ([bcca475](https://github.com/vuejs/core/commit/bcca475dbc58d76434cd8120b94929758cee2825))\n* **compiler-core:** lift vnode hooks deprecation warning to error ([8abc754](https://github.com/vuejs/core/commit/8abc754d5d86d9dfd5a7927b846f1a743f352364))\n* **compiler-core:** export runtime error strings ([#9301](https://github.com/vuejs/core/issues/9301)) ([feb2f2e](https://github.com/vuejs/core/commit/feb2f2edce2d91218a5e9a52c81e322e4033296b))\n* **compiler-core:** add current filename to TransformContext ([#8950](https://github.com/vuejs/core/issues/8950)) ([638f1ab](https://github.com/vuejs/core/commit/638f1abbb632000553e2b7d75e87c95d8ca192d6))\n* **compiler-sfc:** analyze import usage in template via AST ([#9729](https://github.com/vuejs/core/issues/9729)) ([e8bbc94](https://github.com/vuejs/core/commit/e8bbc946cba6bf74c9da56f938b67d2a04c340ba)), closes [#8897](https://github.com/vuejs/core/issues/8897) [nuxt/nuxt#22416](https://github.com/nuxt/nuxt/issues/22416)\n* **compiler-sfc:** expose resolve type-based props and emits ([#8874](https://github.com/vuejs/core/issues/8874)) ([9e77580](https://github.com/vuejs/core/commit/9e77580c0c2f0d977bd0031a1d43cc334769d433))\n* **compiler-sfc:** bump postcss-modules to v6 ([2a507e3](https://github.com/vuejs/core/commit/2a507e32f0e2ef73813705a568b8633f68bda7a9))\n* **compiler-sfc:** promote defineModel stable ([#9598](https://github.com/vuejs/core/issues/9598)) ([ef688ba](https://github.com/vuejs/core/commit/ef688ba92bfccbc8b7ea3997eb297665d13e5249))\n* **compiler-sfc:** support import attributes and `using` syntax ([#8786](https://github.com/vuejs/core/issues/8786)) ([5b2bd1d](https://github.com/vuejs/core/commit/5b2bd1df78e8ff524c3a184adaa284681aba6574))\n* **compiler-sfc:** `defineModel` support local mutation by default, remove local option ([f74785b](https://github.com/vuejs/core/commit/f74785bc4ad351102dde17fdfd2c7276b823111f)), closes [/github.com/vuejs/rfcs/discussions/503#discussioncomment-7566278](https://github.com//github.com/vuejs/rfcs/discussions/503/issues/discussioncomment-7566278)\n* **ssr:** add `__VUE_PROD_HYDRATION_MISMATCH_DETAILS__` feature flag ([#9550](https://github.com/vuejs/core/issues/9550)) ([bc7698d](https://github.com/vuejs/core/commit/bc7698dbfed9b5327a93565f9df336ae5a94d605))\n* **ssr:** improve ssr hydration mismatch checks ([#5953](https://github.com/vuejs/core/issues/5953)) ([2ffc1e8](https://github.com/vuejs/core/commit/2ffc1e8cfdc6ec9c45c4a4dd8e3081b2aa138f1e)), closes [#5063](https://github.com/vuejs/core/issues/5063)\n* **types:** use enum to replace const enum ([#9261](https://github.com/vuejs/core/issues/9261)) ([fff7b86](https://github.com/vuejs/core/commit/fff7b864f4292d0430ba2bda7098ad43876b0210)), closes [#1228](https://github.com/vuejs/core/issues/1228)\n* **types:** add emits and slots type to `FunctionalComponent` ([#8644](https://github.com/vuejs/core/issues/8644)) ([927ab17](https://github.com/vuejs/core/commit/927ab17cfc645e82d061fdf227c34689491268e1))\n* **types:** export `AriaAttributes` type ([#8909](https://github.com/vuejs/core/issues/8909)) ([fd0b6ba](https://github.com/vuejs/core/commit/fd0b6ba01660499fa07b0cf360eefaac8cca8287))\n* **types:** export `ObjectPlugin` and `FunctionPlugin` types ([#8946](https://github.com/vuejs/core/issues/8946)) ([fa4969e](https://github.com/vuejs/core/commit/fa4969e7a3aefa6863203f9294fc5e769ddf6d8f)), closes [#8577](https://github.com/vuejs/core/issues/8577)\n* **types:** expose `DefineProps` type ([096ba81](https://github.com/vuejs/core/commit/096ba81817b7da15f61bc55fc1a93f72ac9586e0))\n* **types:** expose `PublicProps` type ([#2403](https://github.com/vuejs/core/issues/2403)) ([44135dc](https://github.com/vuejs/core/commit/44135dc95fb8fea26b84d1433839d28b8c21f708))\n* **types:** improve event type inference when using `h` with native elements  ([#9756](https://github.com/vuejs/core/issues/9756)) ([a625376](https://github.com/vuejs/core/commit/a625376ac8901eea81bf3c66cb531f2157f073ef))\n* **types:** provide `ComponentInstance` type ([#5408](https://github.com/vuejs/core/issues/5408)) ([bfb8565](https://github.com/vuejs/core/commit/bfb856565d3105db4b18991ae9e404e7cc989b25))\n* **types:** support passing generics when registering global directives ([#9660](https://github.com/vuejs/core/issues/9660)) ([a41409e](https://github.com/vuejs/core/commit/a41409ed02a8c7220e637f56caf6813edeb077f8))\n\n\n### Performance Improvements\n\n* **compiler-sfc:** avoid sfc source map unnecessary serialization and parsing ([f15d2f6](https://github.com/vuejs/core/commit/f15d2f6cf69c0c39f8dfb5c33122790c68bf92e2))\n* **compiler-sfc:** remove magic-string trim on script ([e8e3ec6](https://github.com/vuejs/core/commit/e8e3ec6ca7392e43975c75b56eaaa711d5ea9410))\n* **compiler-sfc:** use faster source map addMapping ([50cde7c](https://github.com/vuejs/core/commit/50cde7cfbcc49022ba88f5f69fa9b930b483c282))\n* **compiler-core:** optimize away isBuiltInType ([66c0ed0](https://github.com/vuejs/core/commit/66c0ed0a3c1c6f37dafc6b1c52b75c6bf60e3136))\n* **compiler-core:** optimize position cloning ([2073236](https://github.com/vuejs/core/commit/20732366b9b3530d33b842cf1fc985919afb9317))\n* **codegen:** optimize line / column calculation during codegen ([3be53d9](https://github.com/vuejs/core/commit/3be53d9b974dae1a10eb795cade71ae765e17574))\n* **codegen:** optimize source map generation ([c11002f](https://github.com/vuejs/core/commit/c11002f16afd243a2b15b546816e73882eea9e4d))\n* **shared:** optimize makeMap ([ae6fba9](https://github.com/vuejs/core/commit/ae6fba94954bac6430902f77b0d1113a98a75b18))\n\n\n### BREAKING CHANGES\n\n#### Global JSX Registration Removed\n\nStarting in 3.4, Vue no longer registers the global `JSX` namespace by default. This is necessary to avoid global namespace collision with React so that TSX of both libs can co-exist in the same project. This should not affect SFC-only users with latest version of Volar.\n\nIf you are using TSX, there are two options:\n\n1. Explicitly set [jsxImportSource](https://www.typescriptlang.org/tsconfig#jsxImportSource) to `'vue'` in `tsconfig.json` before upgrading to 3.4. You can also opt-in per file by adding a `/* @jsxImportSource vue */` comment at the top of the file.\n\n2. If you have code that depends on the presence of the global `JSX` namespace, e.g. usage of types like `JSX.Element` etc., you can retain the exact pre-3.4 global behavior by explicitly referencing `vue/jsx`, which registers the global `JSX` namespace.\n\nNote that this is a type-only breaking change in a minor release, which adheres to our [release policy](https://vuejs.org/about/releases.html#semantic-versioning-edge-cases).\n\n#### Deprecated Features Removed\n\n- [Reactivity Transform](https://vuejs.org/guide/extras/reactivity-transform.html) was marked deprecated in 3.3 and is now removed in 3.4. This change does not require a major due to the feature being experimental. Users who wish to continue using the feature can do so via the [Vue Macros plugin](https://vue-macros.dev/features/reactivity-transform.html).\n- `app.config.unwrapInjectedRef` has been removed. It was deprecated and enabled by default in 3.3. In 3.4 it is no longer possible to disable this behavior.\n- `@vnodeXXX` event listeners in templates are now a compiler error instead of a deprecation warning. Use `@vue:XXX` listeners instead.\n- `v-is` directive has been removed. It was deprecated in 3.3. Use the [`is` attribute with `vue:` prefix](https://vuejs.org/api/built-in-special-attributes.html#is) instead.\n\n# [3.4.0-rc.3](https://github.com/vuejs/core/compare/v3.4.0-rc.2...v3.4.0-rc.3) (2023-12-27)\n\n\n### Bug Fixes\n\n* also export runtime error strings in all cjs builds ([38706e4](https://github.com/vuejs/core/commit/38706e4a1e5e5380e7df910b2a784d0a9bc9db29))\n\n\n### Features\n\n* **defineModel:** support modifiers and transformers ([a772031](https://github.com/vuejs/core/commit/a772031ea8431bd732ffeaeaac09bd76a0daec9b))\n\n\n\n# [3.4.0-rc.2](https://github.com/vuejs/core/compare/v3.4.0-rc.1...v3.4.0-rc.2) (2023-12-26)\n\n\n### Bug Fixes\n\n* **deps:** update dependency @vue/repl to ^3.1.0 ([#9911](https://github.com/vuejs/core/issues/9911)) ([f96c413](https://github.com/vuejs/core/commit/f96c413e8ef2f24cacda5bb499492922f62c6e8b))\n* **types:** fix distribution of union types when unwrapping setup bindings ([#9909](https://github.com/vuejs/core/issues/9909)) ([0695c69](https://github.com/vuejs/core/commit/0695c69e0dfaf99882a623fe75b433c9618ea648)), closes [#9903](https://github.com/vuejs/core/issues/9903)\n* **warning:** ensure prod hydration warnings actually work ([b4ebe7a](https://github.com/vuejs/core/commit/b4ebe7ae8b904f28cdda33caf87bc05718d3a08a))\n\n\n### Features\n\n* **compiler-sfc:** export aggregated error messages for compiler-core and compiler-dom ([25c726e](https://github.com/vuejs/core/commit/25c726eca81fc384b41fafbeba5e8dfcda1f030f))\n\n\n\n# [3.4.0-rc.1](https://github.com/vuejs/core/compare/v3.4.0-beta.4...v3.4.0-rc.1) (2023-12-25)\n\n\n### Bug Fixes\n\n* **compiler-core:** fix parsing `<script setup>` generics with > ([7aa3f25](https://github.com/vuejs/core/commit/7aa3f250f26d58ee2db82af907de8b9105e6e418)), closes [#9890](https://github.com/vuejs/core/issues/9890)\n* **compiler-sfc:** fix type resolution for shared type w/ different generic parameters ([a8d0b1b](https://github.com/vuejs/core/commit/a8d0b1b38b092ec2d10b32bedcee2eea33b77657)), closes [#9871](https://github.com/vuejs/core/issues/9871)\n* **ssr:** avoid hydration mismatch warning for classes with different order ([e585b0d](https://github.com/vuejs/core/commit/e585b0db43150c8b8b3d78f71e12efccc018a38d))\n\n\n\n# [3.4.0-beta.4](https://github.com/vuejs/core/compare/v3.3.13...v3.4.0-beta.4) (2023-12-19)\n\n\n### Bug Fixes\n\n* **compile-sfc:** fix identifier prefixing edge case caused by reused AST ([#9867](https://github.com/vuejs/core/issues/9867)) ([eb51b23](https://github.com/vuejs/core/commit/eb51b23d8512f15665d6f8bcdfd51582e0cd8ce8)), closes [#9853](https://github.com/vuejs/core/issues/9853) [#9863](https://github.com/vuejs/core/issues/9863)\n* **ssr:** fix hydration prop mismatch check for class on SVG elements ([e8448b0](https://github.com/vuejs/core/commit/e8448b018d9f837c08eace90cab404a27f68e31a))\n\n\n### Features\n\n* **runtime-core:** throw real error when scheduler detects infinite loop during dev ([#7447](https://github.com/vuejs/core/issues/7447)) ([1d79b64](https://github.com/vuejs/core/commit/1d79b64ebce884d97136d71aa722347470b13e35)), closes [#7437](https://github.com/vuejs/core/issues/7437)\n\n\n\n# [3.4.0-beta.3](https://github.com/vuejs/core/compare/v3.3.12...v3.4.0-beta.3) (2023-12-16)\n\n\n### Bug Fixes\n\n* **compiler-core:** vnode hooks error message ([#9842](https://github.com/vuejs/core/issues/9842)) ([7bc3c9e](https://github.com/vuejs/core/commit/7bc3c9e205c5158230772d9fcd25bf300809342e))\n* **defineModel:** ensure trigger effect when prop changed ([#9841](https://github.com/vuejs/core/issues/9841)) ([eb12f21](https://github.com/vuejs/core/commit/eb12f211b8e312fd64d91ef1a58b2c2db618bdee)), closes [#9838](https://github.com/vuejs/core/issues/9838)\n* **mathml:** update known mathML tags ([#9829](https://github.com/vuejs/core/issues/9829)) ([ebd78d2](https://github.com/vuejs/core/commit/ebd78d2c99d9587307e444e6b7baa7bc920d42e7))\n* **Suspense:** fix edge case of Suspense being patched during async HOC child remount ([f0f6f7c](https://github.com/vuejs/core/commit/f0f6f7cea6e16650181e71dcfccbee405a1db503))\n\n\n\n# [3.4.0-beta.2](https://github.com/vuejs/core/compare/v3.4.0-beta.1...v3.4.0-beta.2) (2023-12-14)\n\n\n### Features\n\n* **types:** remove default jsx global registration ([92b8d9c](https://github.com/vuejs/core/commit/92b8d9cef69146540db2bf7f2a5632ab5d38f672))\n\n\n### BREAKING CHANGES\n\n* **types:** Vue no longer registers the global `JSX` namespace by\ndefault.\n\n\n\n# [3.4.0-beta.1](https://github.com/vuejs/core/compare/v3.3.11...v3.4.0-beta.1) (2023-12-13)\n\n\n### Bug Fixes\n\n* **compiler-core:** use the same resolved options for all compile stages ([#9760](https://github.com/vuejs/core/issues/9760)) ([0dc875d](https://github.com/vuejs/core/commit/0dc875d53e5d869b44d0c1a70736ec859337b58f))\n* **hydration:** should not warn mismatch for nullish prop ([33159a5](https://github.com/vuejs/core/commit/33159a5916bf7686fe53517befa59b450b34e974))\n* **hydration:** swap client/server labels for hydration mismatch warnings ([f41fd86](https://github.com/vuejs/core/commit/f41fd86d5f26bd0009b4ca285ddc3cefaafa9f7c)), closes [#9098](https://github.com/vuejs/core/issues/9098) [#5953](https://github.com/vuejs/core/issues/5953)\n* **runtime-core:** fix suspense crash when patching non-resolved async setup component ([#7290](https://github.com/vuejs/core/issues/7290)) ([bb0c889](https://github.com/vuejs/core/commit/bb0c8899cadd03af22e23c0383aaab363635c5b4)), closes [#5993](https://github.com/vuejs/core/issues/5993) [#6463](https://github.com/vuejs/core/issues/6463) [#6949](https://github.com/vuejs/core/issues/6949) [#6095](https://github.com/vuejs/core/issues/6095) [#8121](https://github.com/vuejs/core/issues/8121)\n* **runtime-core:** properly pop warning context when mounting components with async setup ([69a2acc](https://github.com/vuejs/core/commit/69a2acc6ea159da8300a68ecc8953f19932c251b))\n* **ssr:** fix suspense hydration of fallback content ([#7188](https://github.com/vuejs/core/issues/7188)) ([60415b5](https://github.com/vuejs/core/commit/60415b5d67df55f1fd6b176615299c08640fa142))\n* **ssr:** make isInSSRComponentSetup state sharable across copies of Vue ([e04d821](https://github.com/vuejs/core/commit/e04d821422102446704e223c03e50d26cbb1fe69))\n* **Suspense:** handle switching away from kept-alive component before resolve ([aa0c13f](https://github.com/vuejs/core/commit/aa0c13f637df7eb27faa2545ee731f543c0813ec)), closes [#6416](https://github.com/vuejs/core/issues/6416) [#6467](https://github.com/vuejs/core/issues/6467)\n* **Suspense:** properly fix [#6416](https://github.com/vuejs/core/issues/6416) ([0db336f](https://github.com/vuejs/core/commit/0db336ff6c640fb9d3e48943c69f4c1737412be4))\n* **types:** add `xmlns:xlink` to `SVGAttributes` ([#9300](https://github.com/vuejs/core/issues/9300)) ([0d61b42](https://github.com/vuejs/core/commit/0d61b429ecf63591d31e09702058fa4c7132e1a7)), closes [#9299](https://github.com/vuejs/core/issues/9299)\n* **types:** support for generic keyof slots ([#8374](https://github.com/vuejs/core/issues/8374)) ([213eba4](https://github.com/vuejs/core/commit/213eba479ce080efc1053fe636f6be4a4c889b44))\n\n\n### Features\n\n* **compiler-core:** add current filename to TransformContext ([#8950](https://github.com/vuejs/core/issues/8950)) ([638f1ab](https://github.com/vuejs/core/commit/638f1abbb632000553e2b7d75e87c95d8ca192d6))\n* **compiler-sfc:** promote defineModel stable ([#9598](https://github.com/vuejs/core/issues/9598)) ([ef688ba](https://github.com/vuejs/core/commit/ef688ba92bfccbc8b7ea3997eb297665d13e5249))\n* **compiler-sfc:** support import attributes and `using` syntax ([#8786](https://github.com/vuejs/core/issues/8786)) ([5b2bd1d](https://github.com/vuejs/core/commit/5b2bd1df78e8ff524c3a184adaa284681aba6574))\n* **defineModel:** support local mutation by default, remove local option ([f74785b](https://github.com/vuejs/core/commit/f74785bc4ad351102dde17fdfd2c7276b823111f)), closes [/github.com/vuejs/rfcs/discussions/503#discussioncomment-7566278](https://github.com//github.com/vuejs/rfcs/discussions/503/issues/discussioncomment-7566278)\n* MathML support ([#7836](https://github.com/vuejs/core/issues/7836)) ([d42b6ba](https://github.com/vuejs/core/commit/d42b6ba3f530746eb1221eb7a4be0f44eb56f7d3)), closes [#7820](https://github.com/vuejs/core/issues/7820)\n* **runtime-core:** provide full props to props validator functions ([#3258](https://github.com/vuejs/core/issues/3258)) ([8e27692](https://github.com/vuejs/core/commit/8e27692029a4645cd54287f776c0420f2b82740b))\n* **ssr:** add `__VUE_PROD_HYDRATION_MISMATCH_DETAILS__` feature flag ([#9550](https://github.com/vuejs/core/issues/9550)) ([bc7698d](https://github.com/vuejs/core/commit/bc7698dbfed9b5327a93565f9df336ae5a94d605))\n* **ssr:** improve ssr hydration mismatch checks ([#5953](https://github.com/vuejs/core/issues/5953)) ([2ffc1e8](https://github.com/vuejs/core/commit/2ffc1e8cfdc6ec9c45c4a4dd8e3081b2aa138f1e)), closes [#5063](https://github.com/vuejs/core/issues/5063)\n* **types:** add emits and slots type to `FunctionalComponent` ([#8644](https://github.com/vuejs/core/issues/8644)) ([927ab17](https://github.com/vuejs/core/commit/927ab17cfc645e82d061fdf227c34689491268e1))\n* **types:** export AriaAttributes type ([#8909](https://github.com/vuejs/core/issues/8909)) ([fd0b6ba](https://github.com/vuejs/core/commit/fd0b6ba01660499fa07b0cf360eefaac8cca8287))\n* **types:** export ObjectPlugin and FunctionPlugin types ([#8946](https://github.com/vuejs/core/issues/8946)) ([fa4969e](https://github.com/vuejs/core/commit/fa4969e7a3aefa6863203f9294fc5e769ddf6d8f)), closes [#8577](https://github.com/vuejs/core/issues/8577)\n* **types:** expose `DefineProps` type ([096ba81](https://github.com/vuejs/core/commit/096ba81817b7da15f61bc55fc1a93f72ac9586e0))\n* **types:** expose `PublicProps` type ([#2403](https://github.com/vuejs/core/issues/2403)) ([44135dc](https://github.com/vuejs/core/commit/44135dc95fb8fea26b84d1433839d28b8c21f708))\n* **types:** improve event type inference when using `h` with native elements  ([#9756](https://github.com/vuejs/core/issues/9756)) ([a625376](https://github.com/vuejs/core/commit/a625376ac8901eea81bf3c66cb531f2157f073ef))\n* **types:** provide ComponentInstance type ([#5408](https://github.com/vuejs/core/issues/5408)) ([bfb8565](https://github.com/vuejs/core/commit/bfb856565d3105db4b18991ae9e404e7cc989b25))\n* **types:** support passing generics when registering global directives ([#9660](https://github.com/vuejs/core/issues/9660)) ([a41409e](https://github.com/vuejs/core/commit/a41409ed02a8c7220e637f56caf6813edeb077f8))\n\n\n### Performance Improvements\n\n* use sync watcher for defineModel local mode ([7e60d10](https://github.com/vuejs/core/commit/7e60d1058ff06e3d37c8608f3449453321220edc)), closes [/github.com/vuejs/rfcs/discussions/503#discussioncomment-7566278](https://github.com//github.com/vuejs/rfcs/discussions/503/issues/discussioncomment-7566278)\n\n\n\n# [3.4.0-alpha.4](https://github.com/vuejs/core/compare/v3.3.10...v3.4.0-alpha.4) (2023-12-04)\n\n\n### Bug Fixes\n\n* **compiler-core:** fix referencing typo ([#9708](https://github.com/vuejs/core/issues/9708)) ([3071de4](https://github.com/vuejs/core/commit/3071de44bc4bf669ab6b48fd8db8d728c30fdb0c))\n* **parser:** fix interpolation parsing in v-pre ([53aaa1e](https://github.com/vuejs/core/commit/53aaa1eb2876baf9de16b2f2c77b2c5fd5173900))\n* **parser:** properly set initial inXML state based on root ns ([47ea285](https://github.com/vuejs/core/commit/47ea285be3dcb66a83a593346995b5900d6c5478))\n* **parser:** should reset inRCDATA state ([ef97e8b](https://github.com/vuejs/core/commit/ef97e8b07d8350106c940f23679444b698832067))\n\n\n### Features\n\n* **compiler-core:** support accessing Error as global in template expressions ([#7018](https://github.com/vuejs/core/issues/7018)) ([bcca475](https://github.com/vuejs/core/commit/bcca475dbc58d76434cd8120b94929758cee2825))\n* **compiler-sfc:** analyze import usage in template via AST ([#9729](https://github.com/vuejs/core/issues/9729)) ([e8bbc94](https://github.com/vuejs/core/commit/e8bbc946cba6bf74c9da56f938b67d2a04c340ba)), closes [#8897](https://github.com/vuejs/core/issues/8897) [nuxt/nuxt#22416](https://github.com/nuxt/nuxt/issues/22416)\n* **compiler-sfc:** bump postcss-modules to v6 ([2a507e3](https://github.com/vuejs/core/commit/2a507e32f0e2ef73813705a568b8633f68bda7a9))\n* **compiler:** lift vnode hooks deprecation warning to error ([8abc754](https://github.com/vuejs/core/commit/8abc754d5d86d9dfd5a7927b846f1a743f352364))\n* use enum to replace const enum ([#9261](https://github.com/vuejs/core/issues/9261)) ([fff7b86](https://github.com/vuejs/core/commit/fff7b864f4292d0430ba2bda7098ad43876b0210)), closes [#1228](https://github.com/vuejs/core/issues/1228)\n\n\n\n# [3.4.0-alpha.3](https://github.com/vuejs/core/compare/v3.4.0-alpha.2...v3.4.0-alpha.3) (2023-11-28)\n\n\n### Bug Fixes\n\n* **deps:** update compiler to ^7.23.4 ([#9681](https://github.com/vuejs/core/issues/9681)) ([31f6ebc](https://github.com/vuejs/core/commit/31f6ebc4df84490ed29fb75e7bf4259200eb51f0))\n* **parser:** directive arg should be undefined on shorthands with no arg ([e49dffc](https://github.com/vuejs/core/commit/e49dffc9ece86bddf094b9ad4ad15eb4856d6277))\n\n\n### Features\n\n* **dx:** link errors to docs in prod build ([#9165](https://github.com/vuejs/core/issues/9165)) ([9f8ba98](https://github.com/vuejs/core/commit/9f8ba9821fe166f77e63fa940e9e7e13ec3344fa))\n\n\n\n# [3.4.0-alpha.2](https://github.com/vuejs/core/compare/v3.3.9...v3.4.0-alpha.2) (2023-11-27)\n\n\n### Bug Fixes\n\n* avoid confusing breakage in @vitejs/plugin-vue ([ceec69c](https://github.com/vuejs/core/commit/ceec69c8ccb96c433a4a506ad2e85e276998bade))\n* **compiler-core:** fix line/column tracking when fast forwarding ([2e65ea4](https://github.com/vuejs/core/commit/2e65ea481f74db8649df8110a031cbdc98f98c84))\n* **compiler-sfc:** fix ast reuse for ssr ([fb619cf](https://github.com/vuejs/core/commit/fb619cf9a440239f0ba88e327d10001a6a3c8171))\n* **compiler-sfc:** support `:is` and `:where` selector in scoped css rewrite ([#8929](https://github.com/vuejs/core/issues/8929)) ([c6083dc](https://github.com/vuejs/core/commit/c6083dcad31f3e9292c687fada9e32f287e2317f))\n* **compiler-sfc:** use correct compiler when re-parsing in ssr mode ([678378a](https://github.com/vuejs/core/commit/678378afd559481badb486b243722b6287862e09))\n\n\n* feat!: remove reactivity transform (#9321) ([79b8a09](https://github.com/vuejs/core/commit/79b8a0905bf363bf82edd2096fef10c3db6d9c3c)), closes [#9321](https://github.com/vuejs/core/issues/9321)\n\n\n### Features\n\n* **compiler-core:** support specifying root namespace when parsing ([40f72d5](https://github.com/vuejs/core/commit/40f72d5e50b389cb11b7ca13461aa2a75ddacdb4))\n* **compiler-core:** support v-bind shorthand for key and value with the same name ([#9451](https://github.com/vuejs/core/issues/9451)) ([26399aa](https://github.com/vuejs/core/commit/26399aa6fac1596b294ffeba06bb498d86f5508c))\n* **compiler:** improve parsing tolerance for language-tools ([41ff68e](https://github.com/vuejs/core/commit/41ff68ea579d933333392146625560359acb728a))\n* **reactivity:** expose last result for computed getter ([#9497](https://github.com/vuejs/core/issues/9497)) ([48b47a1](https://github.com/vuejs/core/commit/48b47a1ab63577e2dbd91947eea544e3ef185b85))\n\n\n### Performance Improvements\n\n* avoid sfc source map unnecessary serialization and parsing ([f15d2f6](https://github.com/vuejs/core/commit/f15d2f6cf69c0c39f8dfb5c33122790c68bf92e2))\n* **codegen:** optimize line / column calculation during codegen ([3be53d9](https://github.com/vuejs/core/commit/3be53d9b974dae1a10eb795cade71ae765e17574))\n* **codegen:** optimize source map generation ([c11002f](https://github.com/vuejs/core/commit/c11002f16afd243a2b15b546816e73882eea9e4d))\n* **compiler-sfc:** remove magic-string trim on script ([e8e3ec6](https://github.com/vuejs/core/commit/e8e3ec6ca7392e43975c75b56eaaa711d5ea9410))\n* **compiler-sfc:** use faster source map addMapping ([50cde7c](https://github.com/vuejs/core/commit/50cde7cfbcc49022ba88f5f69fa9b930b483c282))\n* optimize away isBuiltInType ([66c0ed0](https://github.com/vuejs/core/commit/66c0ed0a3c1c6f37dafc6b1c52b75c6bf60e3136))\n* optimize makeMap ([ae6fba9](https://github.com/vuejs/core/commit/ae6fba94954bac6430902f77b0d1113a98a75b18))\n* optimize position cloning ([2073236](https://github.com/vuejs/core/commit/20732366b9b3530d33b842cf1fc985919afb9317))\n\n\n### BREAKING CHANGES\n\n* Reactivity Transform was marked deprecated in 3.3 and is now removed in 3.4. This change does not require a major due to the feature being experimental. Users who wish to continue using the feature can do so via the external plugin at https://vue-macros.dev/features/reactivity-transform.html\n\n\n\n# [3.4.0-alpha.1](https://github.com/vuejs/core/compare/v3.3.7...v3.4.0-alpha.1) (2023-10-28)\n\n\n### Features\n\n* **compiler-core:** export error message ([#8729](https://github.com/vuejs/core/issues/8729)) ([f7e80ee](https://github.com/vuejs/core/commit/f7e80ee4a065a9eaba98720abf415d9e87756cbd))\n* **compiler-sfc:** expose resolve type-based props and emits ([#8874](https://github.com/vuejs/core/issues/8874)) ([9e77580](https://github.com/vuejs/core/commit/9e77580c0c2f0d977bd0031a1d43cc334769d433))\n* export runtime error strings ([#9301](https://github.com/vuejs/core/issues/9301)) ([feb2f2e](https://github.com/vuejs/core/commit/feb2f2edce2d91218a5e9a52c81e322e4033296b))\n* **reactivity:** more efficient reactivity system ([#5912](https://github.com/vuejs/core/issues/5912)) ([16e06ca](https://github.com/vuejs/core/commit/16e06ca08f5a1e2af3fc7fb35de153dbe0c3087d)), closes [#311](https://github.com/vuejs/core/issues/311) [#1811](https://github.com/vuejs/core/issues/1811) [#6018](https://github.com/vuejs/core/issues/6018) [#7160](https://github.com/vuejs/core/issues/7160) [#8714](https://github.com/vuejs/core/issues/8714) [#9149](https://github.com/vuejs/core/issues/9149) [#9419](https://github.com/vuejs/core/issues/9419) [#9464](https://github.com/vuejs/core/issues/9464)\n* **runtime-core:** add `once` option to watch ([#9034](https://github.com/vuejs/core/issues/9034)) ([a645e7a](https://github.com/vuejs/core/commit/a645e7aa51006516ba668b3a4365d296eb92ee7d))\n"
  },
  {
    "path": "eslint.config.js",
    "content": "import importX from 'eslint-plugin-import-x'\nimport tseslint from 'typescript-eslint'\nimport { defineConfig } from 'eslint/config'\nimport vitest from '@vitest/eslint-plugin'\nimport { builtinModules } from 'node:module'\n\nconst DOMGlobals = ['window', 'document']\nconst NodeGlobals = ['module', 'require']\n\nconst banConstEnum = {\n  selector: 'TSEnumDeclaration[const=true]',\n  message:\n    'Please use non-const enums. This project automatically inlines enums.',\n}\n\nexport default defineConfig(\n  {\n    files: ['**/*.js', '**/*.ts', '**/*.tsx'],\n    extends: [tseslint.configs.base],\n    plugins: {\n      'import-x': importX,\n    },\n    rules: {\n      'no-debugger': 'error',\n      'no-console': ['error', { allow: ['warn', 'error', 'info'] }],\n      // most of the codebase are expected to be env agnostic\n      'no-restricted-globals': ['error', ...DOMGlobals, ...NodeGlobals],\n\n      'no-restricted-syntax': [\n        'error',\n        banConstEnum,\n        {\n          selector: 'ObjectPattern > RestElement',\n          message:\n            'Our output target is ES2016, and object rest spread results in ' +\n            'verbose helpers and should be avoided.',\n        },\n        {\n          selector: 'ObjectExpression > SpreadElement',\n          message:\n            'esbuild transpiles object spread into very verbose inline helpers.\\n' +\n            'Please use the `extend` helper from @vue/shared instead.',\n        },\n        {\n          selector: 'AwaitExpression',\n          message:\n            'Our output target is ES2016, so async/await syntax should be avoided.',\n        },\n        {\n          selector: 'ChainExpression',\n          message:\n            'Our output target is ES2016, and optional chaining results in ' +\n            'verbose helpers and should be avoided.',\n        },\n      ],\n      'sort-imports': ['error', { ignoreDeclarationSort: true }],\n\n      'import-x/no-nodejs-modules': [\n        'error',\n        { allow: builtinModules.map(mod => `node:${mod}`) },\n      ],\n      // This rule enforces the preference for using '@ts-expect-error' comments in TypeScript\n      // code to indicate intentional type errors, improving code clarity and maintainability.\n      '@typescript-eslint/ban-ts-comment': [\n        'error',\n        { minimumDescriptionLength: 0 },\n      ],\n      // Enforce the use of 'import type' for importing types\n      '@typescript-eslint/consistent-type-imports': [\n        'error',\n        {\n          fixStyle: 'inline-type-imports',\n          disallowTypeAnnotations: false,\n        },\n      ],\n      // Enforce the use of top-level import type qualifier when an import only has specifiers with inline type qualifiers\n      '@typescript-eslint/no-import-type-side-effects': 'error',\n    },\n  },\n\n  // tests, no restrictions (runs in Node / Vitest with jsdom)\n  {\n    files: [\n      '**/__tests__/**',\n      'packages-private/dts-test/**',\n      'packages-private/dts-build-test/**',\n    ],\n    plugins: { vitest },\n    languageOptions: {\n      globals: {\n        ...vitest.environments.env.globals,\n      },\n    },\n    rules: {\n      'no-console': 'off',\n      'no-restricted-globals': 'off',\n      'no-restricted-syntax': 'off',\n      'vitest/no-disabled-tests': 'error',\n      'vitest/no-focused-tests': 'error',\n    },\n  },\n\n  // shared, may be used in any env\n  {\n    files: ['packages/shared/**', 'eslint.config.js'],\n    rules: {\n      'no-restricted-globals': 'off',\n    },\n  },\n\n  // Packages targeting DOM\n  {\n    files: ['packages/{vue,vue-compat,runtime-dom}/**'],\n    rules: {\n      'no-restricted-globals': ['error', ...NodeGlobals],\n    },\n  },\n\n  // Packages targeting Node\n  {\n    files: ['packages/{compiler-sfc,compiler-ssr,server-renderer}/**'],\n    rules: {\n      'no-restricted-globals': ['error', ...DOMGlobals],\n      'no-restricted-syntax': ['error', banConstEnum],\n    },\n  },\n\n  // Private package, browser only + no syntax restrictions\n  {\n    files: [\n      'packages-private/template-explorer/**',\n      'packages-private/sfc-playground/**',\n    ],\n    rules: {\n      'no-restricted-globals': ['error', ...NodeGlobals],\n      'no-restricted-syntax': ['error', banConstEnum],\n      'no-console': 'off',\n    },\n  },\n\n  // JavaScript files\n  {\n    files: ['*.js'],\n    rules: {\n      // We only do `no-unused-vars` checks for js files, TS files are checked by TypeScript itself.\n      'no-unused-vars': ['error', { vars: 'all', args: 'none' }],\n    },\n  },\n\n  // Node scripts\n  {\n    files: [\n      'eslint.config.js',\n      'rollup*.config.js',\n      'scripts/**',\n      './*.{js,ts}',\n      'packages/*/*.js',\n      'packages/vue/*/*.js',\n    ],\n    rules: {\n      'no-restricted-globals': 'off',\n      'no-restricted-syntax': ['error', banConstEnum],\n      'no-console': 'off',\n    },\n  },\n\n  // Import nodejs modules in compiler-sfc\n  {\n    files: ['packages/compiler-sfc/src/**'],\n    rules: {\n      'import-x/no-nodejs-modules': ['error', { allow: builtinModules }],\n    },\n  },\n\n  {\n    ignores: [\n      '**/dist/',\n      '**/temp/',\n      '**/coverage/',\n      '.idea/',\n      'explorations/',\n      'dts-build/packages',\n    ],\n  },\n)\n"
  },
  {
    "path": "netlify.toml",
    "content": "[build.environment]\n  NODE_VERSION = \"24\"\n  NPM_FLAGS = \"--version\" # prevent Netlify npm install\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"private\": true,\n  \"version\": \"3.5.30\",\n  \"packageManager\": \"pnpm@10.31.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"node scripts/dev.js\",\n    \"build\": \"node scripts/build.js\",\n    \"build-dts\": \"tsc -p tsconfig.build.json --noCheck && rollup -c rollup.dts.config.js\",\n    \"clean\": \"rimraf --glob packages/*/dist temp .eslintcache\",\n    \"size\": \"run-s \\\"size-*\\\" && node scripts/usage-size.js\",\n    \"size-global\": \"node scripts/build.js vue runtime-dom -f global -p --size\",\n    \"size-esm-runtime\": \"node scripts/build.js vue -f esm-bundler-runtime\",\n    \"size-esm\": \"node scripts/build.js runtime-dom runtime-core reactivity shared -f esm-bundler\",\n    \"check\": \"tsc --incremental --noEmit\",\n    \"lint\": \"eslint --cache .\",\n    \"format\": \"prettier --write --cache .\",\n    \"format-check\": \"prettier --check --cache .\",\n    \"test\": \"vitest\",\n    \"test-unit\": \"vitest --project unit*\",\n    \"test-e2e\": \"node scripts/build.js vue -f global -d && vitest --project e2e\",\n    \"test-dts\": \"run-s build-dts test-dts-only\",\n    \"test-dts-only\": \"tsc -p packages-private/dts-built-test/tsconfig.json && tsc -p ./packages-private/dts-test/tsconfig.test.json\",\n    \"test-coverage\": \"vitest run --project unit* --coverage\",\n    \"prebench\": \"node scripts/build.js -pf esm-browser reactivity\",\n    \"prebench-compare\": \"node scripts/build.js -pf esm-browser reactivity\",\n    \"bench\": \"vitest bench --project=unit --outputJson=temp/bench.json\",\n    \"bench-compare\": \"vitest bench --project=unit --compare=temp/bench.json\",\n    \"release\": \"node scripts/release.js\",\n    \"changelog\": \"conventional-changelog -p angular -i CHANGELOG.md -s\",\n    \"dev-esm\": \"node scripts/dev.js -if esm-bundler-runtime\",\n    \"dev-compiler\": \"run-p \\\"dev template-explorer\\\" serve\",\n    \"dev-sfc\": \"run-s dev-sfc-prepare dev-sfc-run\",\n    \"dev-sfc-prepare\": \"node scripts/pre-dev-sfc.js || npm run build-all-cjs\",\n    \"dev-sfc-serve\": \"vite packages-private/sfc-playground --host\",\n    \"dev-sfc-run\": \"run-p \\\"dev compiler-sfc -f esm-browser\\\" \\\"dev vue -if esm-bundler-runtime\\\" \\\"dev vue -ipf esm-browser-runtime\\\" \\\"dev server-renderer -if esm-bundler\\\" dev-sfc-serve\",\n    \"serve\": \"serve\",\n    \"open\": \"open http://localhost:3000/packages-private/template-explorer/local.html\",\n    \"build-sfc-playground\": \"run-s build-all-cjs build-runtime-esm build-browser-esm build-ssr-esm build-sfc-playground-self\",\n    \"build-all-cjs\": \"node scripts/build.js vue runtime compiler reactivity shared -af cjs\",\n    \"build-runtime-esm\": \"node scripts/build.js runtime reactivity shared -af esm-bundler && node scripts/build.js vue -f esm-bundler-runtime && node scripts/build.js vue -f esm-browser-runtime\",\n    \"build-browser-esm\": \"node scripts/build.js runtime reactivity shared -af esm-bundler && node scripts/build.js vue -f esm-bundler && node scripts/build.js vue -f esm-browser\",\n    \"build-ssr-esm\": \"node scripts/build.js compiler-sfc server-renderer -f esm-browser\",\n    \"build-sfc-playground-self\": \"cd packages-private/sfc-playground && npm run build\",\n    \"preinstall\": \"npx only-allow pnpm\",\n    \"postinstall\": \"simple-git-hooks\"\n  },\n  \"simple-git-hooks\": {\n    \"pre-commit\": \"pnpm lint-staged && pnpm check\",\n    \"commit-msg\": \"node scripts/verify-commit.js\"\n  },\n  \"lint-staged\": {\n    \"*.{js,json}\": [\n      \"prettier --write\"\n    ],\n    \"*.ts?(x)\": [\n      \"eslint --fix\",\n      \"prettier --parser=typescript --write\"\n    ]\n  },\n  \"engines\": {\n    \"node\": \">=20.0.0\"\n  },\n  \"devDependencies\": {\n    \"@babel/parser\": \"catalog:\",\n    \"@babel/types\": \"catalog:\",\n    \"@rollup/plugin-alias\": \"^6.0.0\",\n    \"@rollup/plugin-commonjs\": \"^29.0.2\",\n    \"@rollup/plugin-json\": \"^6.1.0\",\n    \"@rollup/plugin-node-resolve\": \"^16.0.3\",\n    \"@rollup/plugin-replace\": \"5.0.4\",\n    \"@swc/core\": \"^1.15.18\",\n    \"@types/hash-sum\": \"^1.0.2\",\n    \"@types/node\": \"^24.12.0\",\n    \"@types/semver\": \"^7.7.1\",\n    \"@types/serve-handler\": \"^6.1.4\",\n    \"@vitest/coverage-v8\": \"^4.0.18\",\n    \"@vitest/eslint-plugin\": \"^1.6.9\",\n    \"@vue/consolidate\": \"1.0.0\",\n    \"conventional-changelog-cli\": \"^5.0.0\",\n    \"enquirer\": \"^2.4.1\",\n    \"esbuild\": \"^0.27.3\",\n    \"esbuild-plugin-polyfill-node\": \"^0.3.0\",\n    \"eslint\": \"^10.0.3\",\n    \"eslint-plugin-import-x\": \"^4.16.1\",\n    \"estree-walker\": \"catalog:\",\n    \"jsdom\": \"^28.1.0\",\n    \"lint-staged\": \"^16.3.2\",\n    \"lodash\": \"^4.17.23\",\n    \"magic-string\": \"^0.30.21\",\n    \"markdown-table\": \"^3.0.4\",\n    \"marked\": \"13.0.3\",\n    \"npm-run-all2\": \"^8.0.4\",\n    \"picocolors\": \"^1.1.1\",\n    \"prettier\": \"^3.8.1\",\n    \"pretty-bytes\": \"^7.1.0\",\n    \"pug\": \"^3.0.3\",\n    \"puppeteer\": \"~24.38.0\",\n    \"rimraf\": \"^6.1.3\",\n    \"rollup\": \"^4.59.0\",\n    \"rollup-plugin-dts\": \"^6.3.0\",\n    \"rollup-plugin-esbuild\": \"^6.2.1\",\n    \"rollup-plugin-polyfill-node\": \"^0.13.0\",\n    \"semver\": \"^7.7.4\",\n    \"serve\": \"^14.2.6\",\n    \"serve-handler\": \"^6.1.7\",\n    \"simple-git-hooks\": \"^2.13.1\",\n    \"todomvc-app-css\": \"^2.4.3\",\n    \"tslib\": \"^2.8.1\",\n    \"typescript\": \"~5.6.2\",\n    \"typescript-eslint\": \"^8.56.1\",\n    \"vite\": \"catalog:\",\n    \"vitest\": \"^4.0.18\"\n  }\n}\n"
  },
  {
    "path": "packages/compiler-core/LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2018-present, Yuxi (Evan) You\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "packages/compiler-core/README.md",
    "content": "# @vue/compiler-core\n"
  },
  {
    "path": "packages/compiler-core/__tests__/__snapshots__/codegen.spec.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`compiler: codegen > ArrayExpression 1`] = `\n\"\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    return [\n      foo,\n      bar(baz)\n    ]\n  }\n}\"\n`;\n\nexports[`compiler: codegen > CacheExpression 1`] = `\n\"\nexport function render(_ctx, _cache) {\n  return _cache[1] || (_cache[1] = foo)\n}\"\n`;\n\nexports[`compiler: codegen > CacheExpression w/ isVOnce: true 1`] = `\n\"\nexport function render(_ctx, _cache) {\n  return _cache[1] || (\n    _setBlockTracking(-1),\n    (_cache[1] = foo).cacheIndex = 1,\n    _setBlockTracking(1),\n    _cache[1]\n  )\n}\"\n`;\n\nexports[`compiler: codegen > ConditionalExpression 1`] = `\n\"\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    return ok\n      ? foo()\n      : orNot\n        ? bar()\n        : baz()\n  }\n}\"\n`;\n\nexports[`compiler: codegen > Element (callExpression + objectExpression + TemplateChildNode[]) 1`] = `\n\"\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    return _createElementVNode(\"div\", {\n      id: \"foo\",\n      [prop]: bar,\n      [foo + bar]: bar\n    }, [\n      _createElementVNode(\"p\", { \"some-key\": \"foo\" })\n    ], 16 /* FULL_PROPS */)\n  }\n}\"\n`;\n\nexports[`compiler: codegen > assets + temps 1`] = `\n\"\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const _component_Foo = _resolveComponent(\"Foo\")\n    const _component_bar_baz = _resolveComponent(\"bar-baz\")\n    const _component_barbaz = _resolveComponent(\"barbaz\")\n    const _component_Qux = _resolveComponent(\"Qux\", true)\n    const _directive_my_dir_0 = _resolveDirective(\"my_dir_0\")\n    const _directive_my_dir_1 = _resolveDirective(\"my_dir_1\")\n    let _temp0, _temp1, _temp2\n\n    return null\n  }\n}\"\n`;\n\nexports[`compiler: codegen > comment 1`] = `\n\"\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    return _createCommentVNode(\"foo\")\n  }\n}\"\n`;\n\nexports[`compiler: codegen > compound expression 1`] = `\n\"\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    return _ctx.foo + _toDisplayString(bar) + nested\n  }\n}\"\n`;\n\nexports[`compiler: codegen > forNode 1`] = `\n\"\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    return (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(), 1 /* TEXT */))\n  }\n}\"\n`;\n\nexports[`compiler: codegen > forNode with constant expression 1`] = `\n\"\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    return (_openBlock(), _createElementBlock(_Fragment, null, _renderList(), 64 /* STABLE_FRAGMENT */))\n  }\n}\"\n`;\n\nexports[`compiler: codegen > function mode preamble 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { createVNode: _createVNode, resolveDirective: _resolveDirective } = _Vue\n\n    return null\n  }\n}\"\n`;\n\nexports[`compiler: codegen > function mode preamble w/ prefixIdentifiers: true 1`] = `\n\"const { createVNode: _createVNode, resolveDirective: _resolveDirective } = Vue\n\nreturn function render(_ctx, _cache) {\n  return null\n}\"\n`;\n\nexports[`compiler: codegen > hoists 1`] = `\n\"\nconst _hoisted_1 = hello\nconst _hoisted_2 = { id: \"foo\" }\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    return null\n  }\n}\"\n`;\n\nexports[`compiler: codegen > ifNode 1`] = `\n\"\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    return foo\n      ? bar\n      : baz\n  }\n}\"\n`;\n\nexports[`compiler: codegen > interpolation 1`] = `\n\"\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    return _toDisplayString(hello)\n  }\n}\"\n`;\n\nexports[`compiler: codegen > module mode preamble 1`] = `\n\"import { createVNode as _createVNode, resolveDirective as _resolveDirective } from \"vue\"\n\nexport function render(_ctx, _cache) {\n  return null\n}\"\n`;\n\nexports[`compiler: codegen > module mode preamble w/ optimizeImports: true 1`] = `\n\"import { createVNode, resolveDirective } from \"vue\"\n\n// Binding optimization for webpack code-split\nconst _createVNode = createVNode, _resolveDirective = resolveDirective\n\nexport function render(_ctx, _cache) {\n  return null\n}\"\n`;\n\nexports[`compiler: codegen > static text 1`] = `\n\"\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    return \"hello\"\n  }\n}\"\n`;\n\nexports[`compiler: codegen > temps 1`] = `\n\"\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    let _temp0, _temp1, _temp2\n\n    return null\n  }\n}\"\n`;\n"
  },
  {
    "path": "packages/compiler-core/__tests__/__snapshots__/compile.spec.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`compiler: integration tests > function mode 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { toDisplayString: _toDisplayString, openBlock: _openBlock, createElementBlock: _createElementBlock, createCommentVNode: _createCommentVNode, createTextVNode: _createTextVNode, Fragment: _Fragment, renderList: _renderList, createElementVNode: _createElementVNode, normalizeClass: _normalizeClass } = _Vue\n\n    return (_openBlock(), _createElementBlock(\"div\", {\n      id: \"foo\",\n      class: _normalizeClass(bar.baz)\n    }, [\n      _createTextVNode(_toDisplayString(world.burn()) + \" \", 1 /* TEXT */),\n      ok\n        ? (_openBlock(), _createElementBlock(\"div\", { key: 0 }, \"yes\"))\n        : (_openBlock(), _createElementBlock(_Fragment, { key: 1 }, [\n            _createTextVNode(\"no\")\n          ], 64 /* STABLE_FRAGMENT */)),\n      (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(list, (value, index) => {\n        return (_openBlock(), _createElementBlock(\"div\", null, [\n          _createElementVNode(\"span\", null, _toDisplayString(value + index), 1 /* TEXT */)\n        ]))\n      }), 256 /* UNKEYED_FRAGMENT */))\n    ], 2 /* CLASS */))\n  }\n}\"\n`;\n\nexports[`compiler: integration tests > function mode w/ prefixIdentifiers: true 1`] = `\n\"const { toDisplayString: _toDisplayString, openBlock: _openBlock, createElementBlock: _createElementBlock, createCommentVNode: _createCommentVNode, createTextVNode: _createTextVNode, Fragment: _Fragment, renderList: _renderList, createElementVNode: _createElementVNode, normalizeClass: _normalizeClass } = Vue\n\nreturn function render(_ctx, _cache) {\n  return (_openBlock(), _createElementBlock(\"div\", {\n    id: \"foo\",\n    class: _normalizeClass(_ctx.bar.baz)\n  }, [\n    _createTextVNode(_toDisplayString(_ctx.world.burn()) + \" \", 1 /* TEXT */),\n    (_ctx.ok)\n      ? (_openBlock(), _createElementBlock(\"div\", { key: 0 }, \"yes\"))\n      : (_openBlock(), _createElementBlock(_Fragment, { key: 1 }, [\n          _createTextVNode(\"no\")\n        ], 64 /* STABLE_FRAGMENT */)),\n    (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(_ctx.list, (value, index) => {\n      return (_openBlock(), _createElementBlock(\"div\", null, [\n        _createElementVNode(\"span\", null, _toDisplayString(value + index), 1 /* TEXT */)\n      ]))\n    }), 256 /* UNKEYED_FRAGMENT */))\n  ], 2 /* CLASS */))\n}\"\n`;\n\nexports[`compiler: integration tests > module mode 1`] = `\n\"import { toDisplayString as _toDisplayString, openBlock as _openBlock, createElementBlock as _createElementBlock, createCommentVNode as _createCommentVNode, createTextVNode as _createTextVNode, Fragment as _Fragment, renderList as _renderList, createElementVNode as _createElementVNode, normalizeClass as _normalizeClass } from \"vue\"\n\nexport function render(_ctx, _cache) {\n  return (_openBlock(), _createElementBlock(\"div\", {\n    id: \"foo\",\n    class: _normalizeClass(_ctx.bar.baz)\n  }, [\n    _createTextVNode(_toDisplayString(_ctx.world.burn()) + \" \", 1 /* TEXT */),\n    (_ctx.ok)\n      ? (_openBlock(), _createElementBlock(\"div\", { key: 0 }, \"yes\"))\n      : (_openBlock(), _createElementBlock(_Fragment, { key: 1 }, [\n          _createTextVNode(\"no\")\n        ], 64 /* STABLE_FRAGMENT */)),\n    (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(_ctx.list, (value, index) => {\n      return (_openBlock(), _createElementBlock(\"div\", null, [\n        _createElementVNode(\"span\", null, _toDisplayString(value + index), 1 /* TEXT */)\n      ]))\n    }), 256 /* UNKEYED_FRAGMENT */))\n  ], 2 /* CLASS */))\n}\"\n`;\n"
  },
  {
    "path": "packages/compiler-core/__tests__/__snapshots__/parse.spec.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`compiler: parse > Edge Cases > invalid html 1`] = `\n{\n  \"cached\": [],\n  \"children\": [\n    {\n      \"children\": [\n        {\n          \"children\": [],\n          \"codegenNode\": undefined,\n          \"loc\": {\n            \"end\": {\n              \"column\": 1,\n              \"line\": 3,\n              \"offset\": 13,\n            },\n            \"source\": \"<span>\n\",\n            \"start\": {\n              \"column\": 1,\n              \"line\": 2,\n              \"offset\": 6,\n            },\n          },\n          \"ns\": 0,\n          \"props\": [],\n          \"tag\": \"span\",\n          \"tagType\": 0,\n          \"type\": 1,\n        },\n      ],\n      \"codegenNode\": undefined,\n      \"loc\": {\n        \"end\": {\n          \"column\": 7,\n          \"line\": 3,\n          \"offset\": 19,\n        },\n        \"source\": \"<div>\n<span>\n</div>\",\n        \"start\": {\n          \"column\": 1,\n          \"line\": 1,\n          \"offset\": 0,\n        },\n      },\n      \"ns\": 0,\n      \"props\": [],\n      \"tag\": \"div\",\n      \"tagType\": 0,\n      \"type\": 1,\n    },\n  ],\n  \"codegenNode\": undefined,\n  \"components\": [],\n  \"directives\": [],\n  \"helpers\": Set {},\n  \"hoists\": [],\n  \"imports\": [],\n  \"loc\": {\n    \"end\": {\n      \"column\": 8,\n      \"line\": 4,\n      \"offset\": 27,\n    },\n    \"source\": \"<div>\n<span>\n</div>\n</span>\",\n    \"start\": {\n      \"column\": 1,\n      \"line\": 1,\n      \"offset\": 0,\n    },\n  },\n  \"source\": \"<div>\n<span>\n</div>\n</span>\",\n  \"temps\": 0,\n  \"type\": 0,\n}\n`;\n\nexports[`compiler: parse > Edge Cases > self closing multiple tag 1`] = `\n{\n  \"cached\": [],\n  \"children\": [\n    {\n      \"children\": [],\n      \"codegenNode\": undefined,\n      \"isSelfClosing\": true,\n      \"loc\": {\n        \"end\": {\n          \"column\": 37,\n          \"line\": 1,\n          \"offset\": 36,\n        },\n        \"source\": \"<div :class=\"{ some: condition }\" />\",\n        \"start\": {\n          \"column\": 1,\n          \"line\": 1,\n          \"offset\": 0,\n        },\n      },\n      \"ns\": 0,\n      \"props\": [\n        {\n          \"arg\": {\n            \"constType\": 3,\n            \"content\": \"class\",\n            \"isStatic\": true,\n            \"loc\": {\n              \"end\": {\n                \"column\": 12,\n                \"line\": 1,\n                \"offset\": 11,\n              },\n              \"source\": \"class\",\n              \"start\": {\n                \"column\": 7,\n                \"line\": 1,\n                \"offset\": 6,\n              },\n            },\n            \"type\": 4,\n          },\n          \"exp\": {\n            \"constType\": 0,\n            \"content\": \"{ some: condition }\",\n            \"isStatic\": false,\n            \"loc\": {\n              \"end\": {\n                \"column\": 33,\n                \"line\": 1,\n                \"offset\": 32,\n              },\n              \"source\": \"{ some: condition }\",\n              \"start\": {\n                \"column\": 14,\n                \"line\": 1,\n                \"offset\": 13,\n              },\n            },\n            \"type\": 4,\n          },\n          \"loc\": {\n            \"end\": {\n              \"column\": 34,\n              \"line\": 1,\n              \"offset\": 33,\n            },\n            \"source\": \":class=\"{ some: condition }\"\",\n            \"start\": {\n              \"column\": 6,\n              \"line\": 1,\n              \"offset\": 5,\n            },\n          },\n          \"modifiers\": [],\n          \"name\": \"bind\",\n          \"rawName\": \":class\",\n          \"type\": 7,\n        },\n      ],\n      \"tag\": \"div\",\n      \"tagType\": 0,\n      \"type\": 1,\n    },\n    {\n      \"children\": [],\n      \"codegenNode\": undefined,\n      \"isSelfClosing\": true,\n      \"loc\": {\n        \"end\": {\n          \"column\": 37,\n          \"line\": 2,\n          \"offset\": 73,\n        },\n        \"source\": \"<p v-bind:style=\"{ color: 'red' }\"/>\",\n        \"start\": {\n          \"column\": 1,\n          \"line\": 2,\n          \"offset\": 37,\n        },\n      },\n      \"ns\": 0,\n      \"props\": [\n        {\n          \"arg\": {\n            \"constType\": 3,\n            \"content\": \"style\",\n            \"isStatic\": true,\n            \"loc\": {\n              \"end\": {\n                \"column\": 16,\n                \"line\": 2,\n                \"offset\": 52,\n              },\n              \"source\": \"style\",\n              \"start\": {\n                \"column\": 11,\n                \"line\": 2,\n                \"offset\": 47,\n              },\n            },\n            \"type\": 4,\n          },\n          \"exp\": {\n            \"constType\": 0,\n            \"content\": \"{ color: 'red' }\",\n            \"isStatic\": false,\n            \"loc\": {\n              \"end\": {\n                \"column\": 34,\n                \"line\": 2,\n                \"offset\": 70,\n              },\n              \"source\": \"{ color: 'red' }\",\n              \"start\": {\n                \"column\": 18,\n                \"line\": 2,\n                \"offset\": 54,\n              },\n            },\n            \"type\": 4,\n          },\n          \"loc\": {\n            \"end\": {\n              \"column\": 35,\n              \"line\": 2,\n              \"offset\": 71,\n            },\n            \"source\": \"v-bind:style=\"{ color: 'red' }\"\",\n            \"start\": {\n              \"column\": 4,\n              \"line\": 2,\n              \"offset\": 40,\n            },\n          },\n          \"modifiers\": [],\n          \"name\": \"bind\",\n          \"rawName\": \"v-bind:style\",\n          \"type\": 7,\n        },\n      ],\n      \"tag\": \"p\",\n      \"tagType\": 0,\n      \"type\": 1,\n    },\n  ],\n  \"codegenNode\": undefined,\n  \"components\": [],\n  \"directives\": [],\n  \"helpers\": Set {},\n  \"hoists\": [],\n  \"imports\": [],\n  \"loc\": {\n    \"end\": {\n      \"column\": 37,\n      \"line\": 2,\n      \"offset\": 73,\n    },\n    \"source\": \"<div :class=\"{ some: condition }\" />\n<p v-bind:style=\"{ color: 'red' }\"/>\",\n    \"start\": {\n      \"column\": 1,\n      \"line\": 1,\n      \"offset\": 0,\n    },\n  },\n  \"source\": \"<div :class=\"{ some: condition }\" />\n<p v-bind:style=\"{ color: 'red' }\"/>\",\n  \"temps\": 0,\n  \"type\": 0,\n}\n`;\n\nexports[`compiler: parse > Edge Cases > valid html 1`] = `\n{\n  \"cached\": [],\n  \"children\": [\n    {\n      \"children\": [\n        {\n          \"children\": [],\n          \"codegenNode\": undefined,\n          \"isSelfClosing\": true,\n          \"loc\": {\n            \"end\": {\n              \"column\": 39,\n              \"line\": 2,\n              \"offset\": 73,\n            },\n            \"source\": \"<p v-bind:style=\"{ color: 'red' }\"/>\",\n            \"start\": {\n              \"column\": 3,\n              \"line\": 2,\n              \"offset\": 37,\n            },\n          },\n          \"ns\": 0,\n          \"props\": [\n            {\n              \"arg\": {\n                \"constType\": 3,\n                \"content\": \"style\",\n                \"isStatic\": true,\n                \"loc\": {\n                  \"end\": {\n                    \"column\": 18,\n                    \"line\": 2,\n                    \"offset\": 52,\n                  },\n                  \"source\": \"style\",\n                  \"start\": {\n                    \"column\": 13,\n                    \"line\": 2,\n                    \"offset\": 47,\n                  },\n                },\n                \"type\": 4,\n              },\n              \"exp\": {\n                \"constType\": 0,\n                \"content\": \"{ color: 'red' }\",\n                \"isStatic\": false,\n                \"loc\": {\n                  \"end\": {\n                    \"column\": 36,\n                    \"line\": 2,\n                    \"offset\": 70,\n                  },\n                  \"source\": \"{ color: 'red' }\",\n                  \"start\": {\n                    \"column\": 20,\n                    \"line\": 2,\n                    \"offset\": 54,\n                  },\n                },\n                \"type\": 4,\n              },\n              \"loc\": {\n                \"end\": {\n                  \"column\": 37,\n                  \"line\": 2,\n                  \"offset\": 71,\n                },\n                \"source\": \"v-bind:style=\"{ color: 'red' }\"\",\n                \"start\": {\n                  \"column\": 6,\n                  \"line\": 2,\n                  \"offset\": 40,\n                },\n              },\n              \"modifiers\": [],\n              \"name\": \"bind\",\n              \"rawName\": \"v-bind:style\",\n              \"type\": 7,\n            },\n          ],\n          \"tag\": \"p\",\n          \"tagType\": 0,\n          \"type\": 1,\n        },\n        {\n          \"content\": \" a comment with <html> inside it \",\n          \"loc\": {\n            \"end\": {\n              \"column\": 43,\n              \"line\": 3,\n              \"offset\": 116,\n            },\n            \"source\": \"<!-- a comment with <html> inside it -->\",\n            \"start\": {\n              \"column\": 3,\n              \"line\": 3,\n              \"offset\": 76,\n            },\n          },\n          \"type\": 3,\n        },\n      ],\n      \"codegenNode\": undefined,\n      \"loc\": {\n        \"end\": {\n          \"column\": 7,\n          \"line\": 4,\n          \"offset\": 123,\n        },\n        \"source\": \"<div :class=\"{ some: condition }\">\n  <p v-bind:style=\"{ color: 'red' }\"/>\n  <!-- a comment with <html> inside it -->\n</div>\",\n        \"start\": {\n          \"column\": 1,\n          \"line\": 1,\n          \"offset\": 0,\n        },\n      },\n      \"ns\": 0,\n      \"props\": [\n        {\n          \"arg\": {\n            \"constType\": 3,\n            \"content\": \"class\",\n            \"isStatic\": true,\n            \"loc\": {\n              \"end\": {\n                \"column\": 12,\n                \"line\": 1,\n                \"offset\": 11,\n              },\n              \"source\": \"class\",\n              \"start\": {\n                \"column\": 7,\n                \"line\": 1,\n                \"offset\": 6,\n              },\n            },\n            \"type\": 4,\n          },\n          \"exp\": {\n            \"constType\": 0,\n            \"content\": \"{ some: condition }\",\n            \"isStatic\": false,\n            \"loc\": {\n              \"end\": {\n                \"column\": 33,\n                \"line\": 1,\n                \"offset\": 32,\n              },\n              \"source\": \"{ some: condition }\",\n              \"start\": {\n                \"column\": 14,\n                \"line\": 1,\n                \"offset\": 13,\n              },\n            },\n            \"type\": 4,\n          },\n          \"loc\": {\n            \"end\": {\n              \"column\": 34,\n              \"line\": 1,\n              \"offset\": 33,\n            },\n            \"source\": \":class=\"{ some: condition }\"\",\n            \"start\": {\n              \"column\": 6,\n              \"line\": 1,\n              \"offset\": 5,\n            },\n          },\n          \"modifiers\": [],\n          \"name\": \"bind\",\n          \"rawName\": \":class\",\n          \"type\": 7,\n        },\n      ],\n      \"tag\": \"div\",\n      \"tagType\": 0,\n      \"type\": 1,\n    },\n  ],\n  \"codegenNode\": undefined,\n  \"components\": [],\n  \"directives\": [],\n  \"helpers\": Set {},\n  \"hoists\": [],\n  \"imports\": [],\n  \"loc\": {\n    \"end\": {\n      \"column\": 7,\n      \"line\": 4,\n      \"offset\": 123,\n    },\n    \"source\": \"<div :class=\"{ some: condition }\">\n  <p v-bind:style=\"{ color: 'red' }\"/>\n  <!-- a comment with <html> inside it -->\n</div>\",\n    \"start\": {\n      \"column\": 1,\n      \"line\": 1,\n      \"offset\": 0,\n    },\n  },\n  \"source\": \"<div :class=\"{ some: condition }\">\n  <p v-bind:style=\"{ color: 'red' }\"/>\n  <!-- a comment with <html> inside it -->\n</div>\",\n  \"temps\": 0,\n  \"type\": 0,\n}\n`;\n\nexports[`compiler: parse > Errors > CDATA_IN_HTML_CONTENT > <template><![CDATA[cdata]]></template> 1`] = `\n{\n  \"cached\": [],\n  \"children\": [\n    {\n      \"children\": [],\n      \"codegenNode\": undefined,\n      \"loc\": {\n        \"end\": {\n          \"column\": 39,\n          \"line\": 1,\n          \"offset\": 38,\n        },\n        \"source\": \"<template><![CDATA[cdata]]></template>\",\n        \"start\": {\n          \"column\": 1,\n          \"line\": 1,\n          \"offset\": 0,\n        },\n      },\n      \"ns\": 0,\n      \"props\": [],\n      \"tag\": \"template\",\n      \"tagType\": 0,\n      \"type\": 1,\n    },\n  ],\n  \"codegenNode\": undefined,\n  \"components\": [],\n  \"directives\": [],\n  \"helpers\": Set {},\n  \"hoists\": [],\n  \"imports\": [],\n  \"loc\": {\n    \"end\": {\n      \"column\": 39,\n      \"line\": 1,\n      \"offset\": 38,\n    },\n    \"source\": \"<template><![CDATA[cdata]]></template>\",\n    \"start\": {\n      \"column\": 1,\n      \"line\": 1,\n      \"offset\": 0,\n    },\n  },\n  \"source\": \"<template><![CDATA[cdata]]></template>\",\n  \"temps\": 0,\n  \"type\": 0,\n}\n`;\n\nexports[`compiler: parse > Errors > CDATA_IN_HTML_CONTENT > <template><svg><![CDATA[cdata]]></svg></template> 1`] = `\n{\n  \"cached\": [],\n  \"children\": [\n    {\n      \"children\": [\n        {\n          \"children\": [\n            {\n              \"content\": \"cdata\",\n              \"loc\": {\n                \"end\": {\n                  \"column\": 30,\n                  \"line\": 1,\n                  \"offset\": 29,\n                },\n                \"source\": \"cdata\",\n                \"start\": {\n                  \"column\": 25,\n                  \"line\": 1,\n                  \"offset\": 24,\n                },\n              },\n              \"type\": 2,\n            },\n          ],\n          \"codegenNode\": undefined,\n          \"loc\": {\n            \"end\": {\n              \"column\": 39,\n              \"line\": 1,\n              \"offset\": 38,\n            },\n            \"source\": \"<svg><![CDATA[cdata]]></svg>\",\n            \"start\": {\n              \"column\": 11,\n              \"line\": 1,\n              \"offset\": 10,\n            },\n          },\n          \"ns\": 1,\n          \"props\": [],\n          \"tag\": \"svg\",\n          \"tagType\": 0,\n          \"type\": 1,\n        },\n      ],\n      \"codegenNode\": undefined,\n      \"loc\": {\n        \"end\": {\n          \"column\": 50,\n          \"line\": 1,\n          \"offset\": 49,\n        },\n        \"source\": \"<template><svg><![CDATA[cdata]]></svg></template>\",\n        \"start\": {\n          \"column\": 1,\n          \"line\": 1,\n          \"offset\": 0,\n        },\n      },\n      \"ns\": 0,\n      \"props\": [],\n      \"tag\": \"template\",\n      \"tagType\": 0,\n      \"type\": 1,\n    },\n  ],\n  \"codegenNode\": undefined,\n  \"components\": [],\n  \"directives\": [],\n  \"helpers\": Set {},\n  \"hoists\": [],\n  \"imports\": [],\n  \"loc\": {\n    \"end\": {\n      \"column\": 50,\n      \"line\": 1,\n      \"offset\": 49,\n    },\n    \"source\": \"<template><svg><![CDATA[cdata]]></svg></template>\",\n    \"start\": {\n      \"column\": 1,\n      \"line\": 1,\n      \"offset\": 0,\n    },\n  },\n  \"source\": \"<template><svg><![CDATA[cdata]]></svg></template>\",\n  \"temps\": 0,\n  \"type\": 0,\n}\n`;\n\nexports[`compiler: parse > Errors > DUPLICATE_ATTRIBUTE > <template><div id=\"\" id=\"\"></div></template> 1`] = `\n{\n  \"cached\": [],\n  \"children\": [\n    {\n      \"children\": [\n        {\n          \"children\": [],\n          \"codegenNode\": undefined,\n          \"loc\": {\n            \"end\": {\n              \"column\": 34,\n              \"line\": 1,\n              \"offset\": 33,\n            },\n            \"source\": \"<div id=\"\" id=\"\"></div>\",\n            \"start\": {\n              \"column\": 11,\n              \"line\": 1,\n              \"offset\": 10,\n            },\n          },\n          \"ns\": 0,\n          \"props\": [\n            {\n              \"loc\": {\n                \"end\": {\n                  \"column\": 21,\n                  \"line\": 1,\n                  \"offset\": 20,\n                },\n                \"source\": \"id=\"\"\",\n                \"start\": {\n                  \"column\": 16,\n                  \"line\": 1,\n                  \"offset\": 15,\n                },\n              },\n              \"name\": \"id\",\n              \"nameLoc\": {\n                \"end\": {\n                  \"column\": 18,\n                  \"line\": 1,\n                  \"offset\": 17,\n                },\n                \"source\": \"id\",\n                \"start\": {\n                  \"column\": 16,\n                  \"line\": 1,\n                  \"offset\": 15,\n                },\n              },\n              \"type\": 6,\n              \"value\": {\n                \"content\": \"\",\n                \"loc\": {\n                  \"end\": {\n                    \"column\": 21,\n                    \"line\": 1,\n                    \"offset\": 20,\n                  },\n                  \"source\": \"\"\"\",\n                  \"start\": {\n                    \"column\": 19,\n                    \"line\": 1,\n                    \"offset\": 18,\n                  },\n                },\n                \"type\": 2,\n              },\n            },\n            {\n              \"loc\": {\n                \"end\": {\n                  \"column\": 27,\n                  \"line\": 1,\n                  \"offset\": 26,\n                },\n                \"source\": \"id=\"\"\",\n                \"start\": {\n                  \"column\": 22,\n                  \"line\": 1,\n                  \"offset\": 21,\n                },\n              },\n              \"name\": \"id\",\n              \"nameLoc\": {\n                \"end\": {\n                  \"column\": 24,\n                  \"line\": 1,\n                  \"offset\": 23,\n                },\n                \"source\": \"id\",\n                \"start\": {\n                  \"column\": 22,\n                  \"line\": 1,\n                  \"offset\": 21,\n                },\n              },\n              \"type\": 6,\n              \"value\": {\n                \"content\": \"\",\n                \"loc\": {\n                  \"end\": {\n                    \"column\": 27,\n                    \"line\": 1,\n                    \"offset\": 26,\n                  },\n                  \"source\": \"\"\"\",\n                  \"start\": {\n                    \"column\": 25,\n                    \"line\": 1,\n                    \"offset\": 24,\n                  },\n                },\n                \"type\": 2,\n              },\n            },\n          ],\n          \"tag\": \"div\",\n          \"tagType\": 0,\n          \"type\": 1,\n        },\n      ],\n      \"codegenNode\": undefined,\n      \"loc\": {\n        \"end\": {\n          \"column\": 45,\n          \"line\": 1,\n          \"offset\": 44,\n        },\n        \"source\": \"<template><div id=\"\" id=\"\"></div></template>\",\n        \"start\": {\n          \"column\": 1,\n          \"line\": 1,\n          \"offset\": 0,\n        },\n      },\n      \"ns\": 0,\n      \"props\": [],\n      \"tag\": \"template\",\n      \"tagType\": 0,\n      \"type\": 1,\n    },\n  ],\n  \"codegenNode\": undefined,\n  \"components\": [],\n  \"directives\": [],\n  \"helpers\": Set {},\n  \"hoists\": [],\n  \"imports\": [],\n  \"loc\": {\n    \"end\": {\n      \"column\": 45,\n      \"line\": 1,\n      \"offset\": 44,\n    },\n    \"source\": \"<template><div id=\"\" id=\"\"></div></template>\",\n    \"start\": {\n      \"column\": 1,\n      \"line\": 1,\n      \"offset\": 0,\n    },\n  },\n  \"source\": \"<template><div id=\"\" id=\"\"></div></template>\",\n  \"temps\": 0,\n  \"type\": 0,\n}\n`;\n\nexports[`compiler: parse > Errors > EOF_BEFORE_TAG_NAME > <template>< 1`] = `\n{\n  \"cached\": [],\n  \"children\": [\n    {\n      \"children\": [\n        {\n          \"content\": \"<\",\n          \"loc\": {\n            \"end\": {\n              \"column\": 12,\n              \"line\": 1,\n              \"offset\": 11,\n            },\n            \"source\": \"<\",\n            \"start\": {\n              \"column\": 11,\n              \"line\": 1,\n              \"offset\": 10,\n            },\n          },\n          \"type\": 2,\n        },\n      ],\n      \"codegenNode\": undefined,\n      \"loc\": {\n        \"end\": {\n          \"column\": 12,\n          \"line\": 1,\n          \"offset\": 11,\n        },\n        \"source\": \"<template><\",\n        \"start\": {\n          \"column\": 1,\n          \"line\": 1,\n          \"offset\": 0,\n        },\n      },\n      \"ns\": 0,\n      \"props\": [],\n      \"tag\": \"template\",\n      \"tagType\": 0,\n      \"type\": 1,\n    },\n  ],\n  \"codegenNode\": undefined,\n  \"components\": [],\n  \"directives\": [],\n  \"helpers\": Set {},\n  \"hoists\": [],\n  \"imports\": [],\n  \"loc\": {\n    \"end\": {\n      \"column\": 12,\n      \"line\": 1,\n      \"offset\": 11,\n    },\n    \"source\": \"<template><\",\n    \"start\": {\n      \"column\": 1,\n      \"line\": 1,\n      \"offset\": 0,\n    },\n  },\n  \"source\": \"<template><\",\n  \"temps\": 0,\n  \"type\": 0,\n}\n`;\n\nexports[`compiler: parse > Errors > EOF_BEFORE_TAG_NAME > <template></ 1`] = `\n{\n  \"cached\": [],\n  \"children\": [\n    {\n      \"children\": [\n        {\n          \"content\": \"</\",\n          \"loc\": {\n            \"end\": {\n              \"column\": 13,\n              \"line\": 1,\n              \"offset\": 12,\n            },\n            \"source\": \"</\",\n            \"start\": {\n              \"column\": 11,\n              \"line\": 1,\n              \"offset\": 10,\n            },\n          },\n          \"type\": 2,\n        },\n      ],\n      \"codegenNode\": undefined,\n      \"loc\": {\n        \"end\": {\n          \"column\": 13,\n          \"line\": 1,\n          \"offset\": 12,\n        },\n        \"source\": \"<template></\",\n        \"start\": {\n          \"column\": 1,\n          \"line\": 1,\n          \"offset\": 0,\n        },\n      },\n      \"ns\": 0,\n      \"props\": [],\n      \"tag\": \"template\",\n      \"tagType\": 0,\n      \"type\": 1,\n    },\n  ],\n  \"codegenNode\": undefined,\n  \"components\": [],\n  \"directives\": [],\n  \"helpers\": Set {},\n  \"hoists\": [],\n  \"imports\": [],\n  \"loc\": {\n    \"end\": {\n      \"column\": 13,\n      \"line\": 1,\n      \"offset\": 12,\n    },\n    \"source\": \"<template></\",\n    \"start\": {\n      \"column\": 1,\n      \"line\": 1,\n      \"offset\": 0,\n    },\n  },\n  \"source\": \"<template></\",\n  \"temps\": 0,\n  \"type\": 0,\n}\n`;\n\nexports[`compiler: parse > Errors > EOF_IN_CDATA > <template><svg><![CDATA[ 1`] = `\n{\n  \"cached\": [],\n  \"children\": [\n    {\n      \"children\": [\n        {\n          \"children\": [],\n          \"codegenNode\": undefined,\n          \"loc\": {\n            \"end\": {\n              \"column\": 25,\n              \"line\": 1,\n              \"offset\": 24,\n            },\n            \"source\": \"<svg><![CDATA[\",\n            \"start\": {\n              \"column\": 11,\n              \"line\": 1,\n              \"offset\": 10,\n            },\n          },\n          \"ns\": 1,\n          \"props\": [],\n          \"tag\": \"svg\",\n          \"tagType\": 0,\n          \"type\": 1,\n        },\n      ],\n      \"codegenNode\": undefined,\n      \"loc\": {\n        \"end\": {\n          \"column\": 25,\n          \"line\": 1,\n          \"offset\": 24,\n        },\n        \"source\": \"<template><svg><![CDATA[\",\n        \"start\": {\n          \"column\": 1,\n          \"line\": 1,\n          \"offset\": 0,\n        },\n      },\n      \"ns\": 0,\n      \"props\": [],\n      \"tag\": \"template\",\n      \"tagType\": 0,\n      \"type\": 1,\n    },\n  ],\n  \"codegenNode\": undefined,\n  \"components\": [],\n  \"directives\": [],\n  \"helpers\": Set {},\n  \"hoists\": [],\n  \"imports\": [],\n  \"loc\": {\n    \"end\": {\n      \"column\": 25,\n      \"line\": 1,\n      \"offset\": 24,\n    },\n    \"source\": \"<template><svg><![CDATA[\",\n    \"start\": {\n      \"column\": 1,\n      \"line\": 1,\n      \"offset\": 0,\n    },\n  },\n  \"source\": \"<template><svg><![CDATA[\",\n  \"temps\": 0,\n  \"type\": 0,\n}\n`;\n\nexports[`compiler: parse > Errors > EOF_IN_CDATA > <template><svg><![CDATA[cdata 1`] = `\n{\n  \"cached\": [],\n  \"children\": [\n    {\n      \"children\": [\n        {\n          \"children\": [\n            {\n              \"content\": \"cdata\",\n              \"loc\": {\n                \"end\": {\n                  \"column\": 30,\n                  \"line\": 1,\n                  \"offset\": 29,\n                },\n                \"source\": \"cdata\",\n                \"start\": {\n                  \"column\": 25,\n                  \"line\": 1,\n                  \"offset\": 24,\n                },\n              },\n              \"type\": 2,\n            },\n          ],\n          \"codegenNode\": undefined,\n          \"loc\": {\n            \"end\": {\n              \"column\": 30,\n              \"line\": 1,\n              \"offset\": 29,\n            },\n            \"source\": \"<svg><![CDATA[cdata\",\n            \"start\": {\n              \"column\": 11,\n              \"line\": 1,\n              \"offset\": 10,\n            },\n          },\n          \"ns\": 1,\n          \"props\": [],\n          \"tag\": \"svg\",\n          \"tagType\": 0,\n          \"type\": 1,\n        },\n      ],\n      \"codegenNode\": undefined,\n      \"loc\": {\n        \"end\": {\n          \"column\": 30,\n          \"line\": 1,\n          \"offset\": 29,\n        },\n        \"source\": \"<template><svg><![CDATA[cdata\",\n        \"start\": {\n          \"column\": 1,\n          \"line\": 1,\n          \"offset\": 0,\n        },\n      },\n      \"ns\": 0,\n      \"props\": [],\n      \"tag\": \"template\",\n      \"tagType\": 0,\n      \"type\": 1,\n    },\n  ],\n  \"codegenNode\": undefined,\n  \"components\": [],\n  \"directives\": [],\n  \"helpers\": Set {},\n  \"hoists\": [],\n  \"imports\": [],\n  \"loc\": {\n    \"end\": {\n      \"column\": 30,\n      \"line\": 1,\n      \"offset\": 29,\n    },\n    \"source\": \"<template><svg><![CDATA[cdata\",\n    \"start\": {\n      \"column\": 1,\n      \"line\": 1,\n      \"offset\": 0,\n    },\n  },\n  \"source\": \"<template><svg><![CDATA[cdata\",\n  \"temps\": 0,\n  \"type\": 0,\n}\n`;\n\nexports[`compiler: parse > Errors > EOF_IN_COMMENT > <template><!-- 1`] = `\n{\n  \"cached\": [],\n  \"children\": [\n    {\n      \"children\": [],\n      \"codegenNode\": undefined,\n      \"loc\": {\n        \"end\": {\n          \"column\": 15,\n          \"line\": 1,\n          \"offset\": 14,\n        },\n        \"source\": \"<template><!--\",\n        \"start\": {\n          \"column\": 1,\n          \"line\": 1,\n          \"offset\": 0,\n        },\n      },\n      \"ns\": 0,\n      \"props\": [],\n      \"tag\": \"template\",\n      \"tagType\": 0,\n      \"type\": 1,\n    },\n  ],\n  \"codegenNode\": undefined,\n  \"components\": [],\n  \"directives\": [],\n  \"helpers\": Set {},\n  \"hoists\": [],\n  \"imports\": [],\n  \"loc\": {\n    \"end\": {\n      \"column\": 15,\n      \"line\": 1,\n      \"offset\": 14,\n    },\n    \"source\": \"<template><!--\",\n    \"start\": {\n      \"column\": 1,\n      \"line\": 1,\n      \"offset\": 0,\n    },\n  },\n  \"source\": \"<template><!--\",\n  \"temps\": 0,\n  \"type\": 0,\n}\n`;\n\nexports[`compiler: parse > Errors > EOF_IN_COMMENT > <template><!--comment 1`] = `\n{\n  \"cached\": [],\n  \"children\": [\n    {\n      \"children\": [\n        {\n          \"content\": \"comment\",\n          \"loc\": {\n            \"end\": {\n              \"column\": 25,\n              \"line\": 1,\n              \"offset\": 24,\n            },\n            \"source\": \"<!--comment\",\n            \"start\": {\n              \"column\": 11,\n              \"line\": 1,\n              \"offset\": 10,\n            },\n          },\n          \"type\": 3,\n        },\n      ],\n      \"codegenNode\": undefined,\n      \"loc\": {\n        \"end\": {\n          \"column\": 22,\n          \"line\": 1,\n          \"offset\": 21,\n        },\n        \"source\": \"<template><!--comment\",\n        \"start\": {\n          \"column\": 1,\n          \"line\": 1,\n          \"offset\": 0,\n        },\n      },\n      \"ns\": 0,\n      \"props\": [],\n      \"tag\": \"template\",\n      \"tagType\": 0,\n      \"type\": 1,\n    },\n  ],\n  \"codegenNode\": undefined,\n  \"components\": [],\n  \"directives\": [],\n  \"helpers\": Set {},\n  \"hoists\": [],\n  \"imports\": [],\n  \"loc\": {\n    \"end\": {\n      \"column\": 22,\n      \"line\": 1,\n      \"offset\": 21,\n    },\n    \"source\": \"<template><!--comment\",\n    \"start\": {\n      \"column\": 1,\n      \"line\": 1,\n      \"offset\": 0,\n    },\n  },\n  \"source\": \"<template><!--comment\",\n  \"temps\": 0,\n  \"type\": 0,\n}\n`;\n\nexports[`compiler: parse > Errors > EOF_IN_TAG > <div></div 1`] = `\n{\n  \"cached\": [],\n  \"children\": [\n    {\n      \"children\": [],\n      \"codegenNode\": undefined,\n      \"loc\": {\n        \"end\": {\n          \"column\": 11,\n          \"line\": 1,\n          \"offset\": 10,\n        },\n        \"source\": \"<div></div\",\n        \"start\": {\n          \"column\": 1,\n          \"line\": 1,\n          \"offset\": 0,\n        },\n      },\n      \"ns\": 0,\n      \"props\": [],\n      \"tag\": \"div\",\n      \"tagType\": 0,\n      \"type\": 1,\n    },\n  ],\n  \"codegenNode\": undefined,\n  \"components\": [],\n  \"directives\": [],\n  \"helpers\": Set {},\n  \"hoists\": [],\n  \"imports\": [],\n  \"loc\": {\n    \"end\": {\n      \"column\": 11,\n      \"line\": 1,\n      \"offset\": 10,\n    },\n    \"source\": \"<div></div\",\n    \"start\": {\n      \"column\": 1,\n      \"line\": 1,\n      \"offset\": 0,\n    },\n  },\n  \"source\": \"<div></div\",\n  \"temps\": 0,\n  \"type\": 0,\n}\n`;\n\nexports[`compiler: parse > Errors > EOF_IN_TAG > <template><div  1`] = `\n{\n  \"cached\": [],\n  \"children\": [\n    {\n      \"children\": [],\n      \"codegenNode\": undefined,\n      \"loc\": {\n        \"end\": {\n          \"column\": 16,\n          \"line\": 1,\n          \"offset\": 15,\n        },\n        \"source\": \"<template><div \",\n        \"start\": {\n          \"column\": 1,\n          \"line\": 1,\n          \"offset\": 0,\n        },\n      },\n      \"ns\": 0,\n      \"props\": [],\n      \"tag\": \"template\",\n      \"tagType\": 0,\n      \"type\": 1,\n    },\n  ],\n  \"codegenNode\": undefined,\n  \"components\": [],\n  \"directives\": [],\n  \"helpers\": Set {},\n  \"hoists\": [],\n  \"imports\": [],\n  \"loc\": {\n    \"end\": {\n      \"column\": 16,\n      \"line\": 1,\n      \"offset\": 15,\n    },\n    \"source\": \"<template><div \",\n    \"start\": {\n      \"column\": 1,\n      \"line\": 1,\n      \"offset\": 0,\n    },\n  },\n  \"source\": \"<template><div \",\n  \"temps\": 0,\n  \"type\": 0,\n}\n`;\n\nexports[`compiler: parse > Errors > EOF_IN_TAG > <template><div 1`] = `\n{\n  \"cached\": [],\n  \"children\": [\n    {\n      \"children\": [],\n      \"codegenNode\": undefined,\n      \"loc\": {\n        \"end\": {\n          \"column\": 15,\n          \"line\": 1,\n          \"offset\": 14,\n        },\n        \"source\": \"<template><div\",\n        \"start\": {\n          \"column\": 1,\n          \"line\": 1,\n          \"offset\": 0,\n        },\n      },\n      \"ns\": 0,\n      \"props\": [],\n      \"tag\": \"template\",\n      \"tagType\": 0,\n      \"type\": 1,\n    },\n  ],\n  \"codegenNode\": undefined,\n  \"components\": [],\n  \"directives\": [],\n  \"helpers\": Set {},\n  \"hoists\": [],\n  \"imports\": [],\n  \"loc\": {\n    \"end\": {\n      \"column\": 15,\n      \"line\": 1,\n      \"offset\": 14,\n    },\n    \"source\": \"<template><div\",\n    \"start\": {\n      \"column\": 1,\n      \"line\": 1,\n      \"offset\": 0,\n    },\n  },\n  \"source\": \"<template><div\",\n  \"temps\": 0,\n  \"type\": 0,\n}\n`;\n\nexports[`compiler: parse > Errors > EOF_IN_TAG > <template><div id  1`] = `\n{\n  \"cached\": [],\n  \"children\": [\n    {\n      \"children\": [],\n      \"codegenNode\": undefined,\n      \"loc\": {\n        \"end\": {\n          \"column\": 19,\n          \"line\": 1,\n          \"offset\": 18,\n        },\n        \"source\": \"<template><div id \",\n        \"start\": {\n          \"column\": 1,\n          \"line\": 1,\n          \"offset\": 0,\n        },\n      },\n      \"ns\": 0,\n      \"props\": [],\n      \"tag\": \"template\",\n      \"tagType\": 0,\n      \"type\": 1,\n    },\n  ],\n  \"codegenNode\": undefined,\n  \"components\": [],\n  \"directives\": [],\n  \"helpers\": Set {},\n  \"hoists\": [],\n  \"imports\": [],\n  \"loc\": {\n    \"end\": {\n      \"column\": 19,\n      \"line\": 1,\n      \"offset\": 18,\n    },\n    \"source\": \"<template><div id \",\n    \"start\": {\n      \"column\": 1,\n      \"line\": 1,\n      \"offset\": 0,\n    },\n  },\n  \"source\": \"<template><div id \",\n  \"temps\": 0,\n  \"type\": 0,\n}\n`;\n\nexports[`compiler: parse > Errors > EOF_IN_TAG > <template><div id = 1`] = `\n{\n  \"cached\": [],\n  \"children\": [\n    {\n      \"children\": [],\n      \"codegenNode\": undefined,\n      \"loc\": {\n        \"end\": {\n          \"column\": 20,\n          \"line\": 1,\n          \"offset\": 19,\n        },\n        \"source\": \"<template><div id =\",\n        \"start\": {\n          \"column\": 1,\n          \"line\": 1,\n          \"offset\": 0,\n        },\n      },\n      \"ns\": 0,\n      \"props\": [],\n      \"tag\": \"template\",\n      \"tagType\": 0,\n      \"type\": 1,\n    },\n  ],\n  \"codegenNode\": undefined,\n  \"components\": [],\n  \"directives\": [],\n  \"helpers\": Set {},\n  \"hoists\": [],\n  \"imports\": [],\n  \"loc\": {\n    \"end\": {\n      \"column\": 20,\n      \"line\": 1,\n      \"offset\": 19,\n    },\n    \"source\": \"<template><div id =\",\n    \"start\": {\n      \"column\": 1,\n      \"line\": 1,\n      \"offset\": 0,\n    },\n  },\n  \"source\": \"<template><div id =\",\n  \"temps\": 0,\n  \"type\": 0,\n}\n`;\n\nexports[`compiler: parse > Errors > EOF_IN_TAG > <template><div id 1`] = `\n{\n  \"cached\": [],\n  \"children\": [\n    {\n      \"children\": [],\n      \"codegenNode\": undefined,\n      \"loc\": {\n        \"end\": {\n          \"column\": 18,\n          \"line\": 1,\n          \"offset\": 17,\n        },\n        \"source\": \"<template><div id\",\n        \"start\": {\n          \"column\": 1,\n          \"line\": 1,\n          \"offset\": 0,\n        },\n      },\n      \"ns\": 0,\n      \"props\": [],\n      \"tag\": \"template\",\n      \"tagType\": 0,\n      \"type\": 1,\n    },\n  ],\n  \"codegenNode\": undefined,\n  \"components\": [],\n  \"directives\": [],\n  \"helpers\": Set {},\n  \"hoists\": [],\n  \"imports\": [],\n  \"loc\": {\n    \"end\": {\n      \"column\": 18,\n      \"line\": 1,\n      \"offset\": 17,\n    },\n    \"source\": \"<template><div id\",\n    \"start\": {\n      \"column\": 1,\n      \"line\": 1,\n      \"offset\": 0,\n    },\n  },\n  \"source\": \"<template><div id\",\n  \"temps\": 0,\n  \"type\": 0,\n}\n`;\n\nexports[`compiler: parse > Errors > EOF_IN_TAG > <template><div id=\"abc 1`] = `\n{\n  \"cached\": [],\n  \"children\": [\n    {\n      \"children\": [],\n      \"codegenNode\": undefined,\n      \"loc\": {\n        \"end\": {\n          \"column\": 23,\n          \"line\": 1,\n          \"offset\": 22,\n        },\n        \"source\": \"<template><div id=\"abc\",\n        \"start\": {\n          \"column\": 1,\n          \"line\": 1,\n          \"offset\": 0,\n        },\n      },\n      \"ns\": 0,\n      \"props\": [],\n      \"tag\": \"template\",\n      \"tagType\": 0,\n      \"type\": 1,\n    },\n  ],\n  \"codegenNode\": undefined,\n  \"components\": [],\n  \"directives\": [],\n  \"helpers\": Set {},\n  \"hoists\": [],\n  \"imports\": [],\n  \"loc\": {\n    \"end\": {\n      \"column\": 23,\n      \"line\": 1,\n      \"offset\": 22,\n    },\n    \"source\": \"<template><div id=\"abc\",\n    \"start\": {\n      \"column\": 1,\n      \"line\": 1,\n      \"offset\": 0,\n    },\n  },\n  \"source\": \"<template><div id=\"abc\",\n  \"temps\": 0,\n  \"type\": 0,\n}\n`;\n\nexports[`compiler: parse > Errors > EOF_IN_TAG > <template><div id=\"abc\" 1`] = `\n{\n  \"cached\": [],\n  \"children\": [\n    {\n      \"children\": [],\n      \"codegenNode\": undefined,\n      \"loc\": {\n        \"end\": {\n          \"column\": 24,\n          \"line\": 1,\n          \"offset\": 23,\n        },\n        \"source\": \"<template><div id=\"abc\"\",\n        \"start\": {\n          \"column\": 1,\n          \"line\": 1,\n          \"offset\": 0,\n        },\n      },\n      \"ns\": 0,\n      \"props\": [],\n      \"tag\": \"template\",\n      \"tagType\": 0,\n      \"type\": 1,\n    },\n  ],\n  \"codegenNode\": undefined,\n  \"components\": [],\n  \"directives\": [],\n  \"helpers\": Set {},\n  \"hoists\": [],\n  \"imports\": [],\n  \"loc\": {\n    \"end\": {\n      \"column\": 24,\n      \"line\": 1,\n      \"offset\": 23,\n    },\n    \"source\": \"<template><div id=\"abc\"\",\n    \"start\": {\n      \"column\": 1,\n      \"line\": 1,\n      \"offset\": 0,\n    },\n  },\n  \"source\": \"<template><div id=\"abc\"\",\n  \"temps\": 0,\n  \"type\": 0,\n}\n`;\n\nexports[`compiler: parse > Errors > EOF_IN_TAG > <template><div id=\"abc\"/ 1`] = `\n{\n  \"cached\": [],\n  \"children\": [\n    {\n      \"children\": [\n        {\n          \"content\": \"/\",\n          \"loc\": {\n            \"end\": {\n              \"column\": 25,\n              \"line\": 1,\n              \"offset\": 24,\n            },\n            \"source\": \"/\",\n            \"start\": {\n              \"column\": 0,\n              \"line\": 1,\n              \"offset\": -1,\n            },\n          },\n          \"type\": 2,\n        },\n      ],\n      \"codegenNode\": undefined,\n      \"loc\": {\n        \"end\": {\n          \"column\": 25,\n          \"line\": 1,\n          \"offset\": 24,\n        },\n        \"source\": \"<template><div id=\"abc\"/\",\n        \"start\": {\n          \"column\": 1,\n          \"line\": 1,\n          \"offset\": 0,\n        },\n      },\n      \"ns\": 0,\n      \"props\": [],\n      \"tag\": \"template\",\n      \"tagType\": 0,\n      \"type\": 1,\n    },\n  ],\n  \"codegenNode\": undefined,\n  \"components\": [],\n  \"directives\": [],\n  \"helpers\": Set {},\n  \"hoists\": [],\n  \"imports\": [],\n  \"loc\": {\n    \"end\": {\n      \"column\": 25,\n      \"line\": 1,\n      \"offset\": 24,\n    },\n    \"source\": \"<template><div id=\"abc\"/\",\n    \"start\": {\n      \"column\": 1,\n      \"line\": 1,\n      \"offset\": 0,\n    },\n  },\n  \"source\": \"<template><div id=\"abc\"/\",\n  \"temps\": 0,\n  \"type\": 0,\n}\n`;\n\nexports[`compiler: parse > Errors > EOF_IN_TAG > <template><div id='abc 1`] = `\n{\n  \"cached\": [],\n  \"children\": [\n    {\n      \"children\": [],\n      \"codegenNode\": undefined,\n      \"loc\": {\n        \"end\": {\n          \"column\": 23,\n          \"line\": 1,\n          \"offset\": 22,\n        },\n        \"source\": \"<template><div id='abc\",\n        \"start\": {\n          \"column\": 1,\n          \"line\": 1,\n          \"offset\": 0,\n        },\n      },\n      \"ns\": 0,\n      \"props\": [],\n      \"tag\": \"template\",\n      \"tagType\": 0,\n      \"type\": 1,\n    },\n  ],\n  \"codegenNode\": undefined,\n  \"components\": [],\n  \"directives\": [],\n  \"helpers\": Set {},\n  \"hoists\": [],\n  \"imports\": [],\n  \"loc\": {\n    \"end\": {\n      \"column\": 23,\n      \"line\": 1,\n      \"offset\": 22,\n    },\n    \"source\": \"<template><div id='abc\",\n    \"start\": {\n      \"column\": 1,\n      \"line\": 1,\n      \"offset\": 0,\n    },\n  },\n  \"source\": \"<template><div id='abc\",\n  \"temps\": 0,\n  \"type\": 0,\n}\n`;\n\nexports[`compiler: parse > Errors > EOF_IN_TAG > <template><div id='abc' 1`] = `\n{\n  \"cached\": [],\n  \"children\": [\n    {\n      \"children\": [],\n      \"codegenNode\": undefined,\n      \"loc\": {\n        \"end\": {\n          \"column\": 24,\n          \"line\": 1,\n          \"offset\": 23,\n        },\n        \"source\": \"<template><div id='abc'\",\n        \"start\": {\n          \"column\": 1,\n          \"line\": 1,\n          \"offset\": 0,\n        },\n      },\n      \"ns\": 0,\n      \"props\": [],\n      \"tag\": \"template\",\n      \"tagType\": 0,\n      \"type\": 1,\n    },\n  ],\n  \"codegenNode\": undefined,\n  \"components\": [],\n  \"directives\": [],\n  \"helpers\": Set {},\n  \"hoists\": [],\n  \"imports\": [],\n  \"loc\": {\n    \"end\": {\n      \"column\": 24,\n      \"line\": 1,\n      \"offset\": 23,\n    },\n    \"source\": \"<template><div id='abc'\",\n    \"start\": {\n      \"column\": 1,\n      \"line\": 1,\n      \"offset\": 0,\n    },\n  },\n  \"source\": \"<template><div id='abc'\",\n  \"temps\": 0,\n  \"type\": 0,\n}\n`;\n\nexports[`compiler: parse > Errors > EOF_IN_TAG > <template><div id='abc'/ 1`] = `\n{\n  \"cached\": [],\n  \"children\": [\n    {\n      \"children\": [\n        {\n          \"content\": \"/\",\n          \"loc\": {\n            \"end\": {\n              \"column\": 25,\n              \"line\": 1,\n              \"offset\": 24,\n            },\n            \"source\": \"/\",\n            \"start\": {\n              \"column\": 0,\n              \"line\": 1,\n              \"offset\": -1,\n            },\n          },\n          \"type\": 2,\n        },\n      ],\n      \"codegenNode\": undefined,\n      \"loc\": {\n        \"end\": {\n          \"column\": 25,\n          \"line\": 1,\n          \"offset\": 24,\n        },\n        \"source\": \"<template><div id='abc'/\",\n        \"start\": {\n          \"column\": 1,\n          \"line\": 1,\n          \"offset\": 0,\n        },\n      },\n      \"ns\": 0,\n      \"props\": [],\n      \"tag\": \"template\",\n      \"tagType\": 0,\n      \"type\": 1,\n    },\n  ],\n  \"codegenNode\": undefined,\n  \"components\": [],\n  \"directives\": [],\n  \"helpers\": Set {},\n  \"hoists\": [],\n  \"imports\": [],\n  \"loc\": {\n    \"end\": {\n      \"column\": 25,\n      \"line\": 1,\n      \"offset\": 24,\n    },\n    \"source\": \"<template><div id='abc'/\",\n    \"start\": {\n      \"column\": 1,\n      \"line\": 1,\n      \"offset\": 0,\n    },\n  },\n  \"source\": \"<template><div id='abc'/\",\n  \"temps\": 0,\n  \"type\": 0,\n}\n`;\n\nexports[`compiler: parse > Errors > EOF_IN_TAG > <template><div id=abc / 1`] = `\n{\n  \"cached\": [],\n  \"children\": [\n    {\n      \"children\": [\n        {\n          \"content\": \"/\",\n          \"loc\": {\n            \"end\": {\n              \"column\": 24,\n              \"line\": 1,\n              \"offset\": 23,\n            },\n            \"source\": \"/\",\n            \"start\": {\n              \"column\": 0,\n              \"line\": 1,\n              \"offset\": -1,\n            },\n          },\n          \"type\": 2,\n        },\n      ],\n      \"codegenNode\": undefined,\n      \"loc\": {\n        \"end\": {\n          \"column\": 24,\n          \"line\": 1,\n          \"offset\": 23,\n        },\n        \"source\": \"<template><div id=abc /\",\n        \"start\": {\n          \"column\": 1,\n          \"line\": 1,\n          \"offset\": 0,\n        },\n      },\n      \"ns\": 0,\n      \"props\": [],\n      \"tag\": \"template\",\n      \"tagType\": 0,\n      \"type\": 1,\n    },\n  ],\n  \"codegenNode\": undefined,\n  \"components\": [],\n  \"directives\": [],\n  \"helpers\": Set {},\n  \"hoists\": [],\n  \"imports\": [],\n  \"loc\": {\n    \"end\": {\n      \"column\": 24,\n      \"line\": 1,\n      \"offset\": 23,\n    },\n    \"source\": \"<template><div id=abc /\",\n    \"start\": {\n      \"column\": 1,\n      \"line\": 1,\n      \"offset\": 0,\n    },\n  },\n  \"source\": \"<template><div id=abc /\",\n  \"temps\": 0,\n  \"type\": 0,\n}\n`;\n\nexports[`compiler: parse > Errors > EOF_IN_TAG > <template><div id=abc 1`] = `\n{\n  \"cached\": [],\n  \"children\": [\n    {\n      \"children\": [],\n      \"codegenNode\": undefined,\n      \"loc\": {\n        \"end\": {\n          \"column\": 22,\n          \"line\": 1,\n          \"offset\": 21,\n        },\n        \"source\": \"<template><div id=abc\",\n        \"start\": {\n          \"column\": 1,\n          \"line\": 1,\n          \"offset\": 0,\n        },\n      },\n      \"ns\": 0,\n      \"props\": [],\n      \"tag\": \"template\",\n      \"tagType\": 0,\n      \"type\": 1,\n    },\n  ],\n  \"codegenNode\": undefined,\n  \"components\": [],\n  \"directives\": [],\n  \"helpers\": Set {},\n  \"hoists\": [],\n  \"imports\": [],\n  \"loc\": {\n    \"end\": {\n      \"column\": 22,\n      \"line\": 1,\n      \"offset\": 21,\n    },\n    \"source\": \"<template><div id=abc\",\n    \"start\": {\n      \"column\": 1,\n      \"line\": 1,\n      \"offset\": 0,\n    },\n  },\n  \"source\": \"<template><div id=abc\",\n  \"temps\": 0,\n  \"type\": 0,\n}\n`;\n\nexports[`compiler: parse > Errors > MISSING_ATTRIBUTE_VALUE > <template><div id= /></div></template> 1`] = `\n{\n  \"cached\": [],\n  \"children\": [\n    {\n      \"children\": [\n        {\n          \"children\": [],\n          \"codegenNode\": undefined,\n          \"loc\": {\n            \"end\": {\n              \"column\": 28,\n              \"line\": 1,\n              \"offset\": 27,\n            },\n            \"source\": \"<div id= /></div>\",\n            \"start\": {\n              \"column\": 11,\n              \"line\": 1,\n              \"offset\": 10,\n            },\n          },\n          \"ns\": 0,\n          \"props\": [\n            {\n              \"loc\": {\n                \"end\": {\n                  \"column\": 21,\n                  \"line\": 1,\n                  \"offset\": 20,\n                },\n                \"source\": \"id= /\",\n                \"start\": {\n                  \"column\": 16,\n                  \"line\": 1,\n                  \"offset\": 15,\n                },\n              },\n              \"name\": \"id\",\n              \"nameLoc\": {\n                \"end\": {\n                  \"column\": 18,\n                  \"line\": 1,\n                  \"offset\": 17,\n                },\n                \"source\": \"id\",\n                \"start\": {\n                  \"column\": 16,\n                  \"line\": 1,\n                  \"offset\": 15,\n                },\n              },\n              \"type\": 6,\n              \"value\": {\n                \"content\": \"/\",\n                \"loc\": {\n                  \"end\": {\n                    \"column\": 21,\n                    \"line\": 1,\n                    \"offset\": 20,\n                  },\n                  \"source\": \"/\",\n                  \"start\": {\n                    \"column\": 20,\n                    \"line\": 1,\n                    \"offset\": 19,\n                  },\n                },\n                \"type\": 2,\n              },\n            },\n          ],\n          \"tag\": \"div\",\n          \"tagType\": 0,\n          \"type\": 1,\n        },\n      ],\n      \"codegenNode\": undefined,\n      \"loc\": {\n        \"end\": {\n          \"column\": 39,\n          \"line\": 1,\n          \"offset\": 38,\n        },\n        \"source\": \"<template><div id= /></div></template>\",\n        \"start\": {\n          \"column\": 1,\n          \"line\": 1,\n          \"offset\": 0,\n        },\n      },\n      \"ns\": 0,\n      \"props\": [],\n      \"tag\": \"template\",\n      \"tagType\": 0,\n      \"type\": 1,\n    },\n  ],\n  \"codegenNode\": undefined,\n  \"components\": [],\n  \"directives\": [],\n  \"helpers\": Set {},\n  \"hoists\": [],\n  \"imports\": [],\n  \"loc\": {\n    \"end\": {\n      \"column\": 39,\n      \"line\": 1,\n      \"offset\": 38,\n    },\n    \"source\": \"<template><div id= /></div></template>\",\n    \"start\": {\n      \"column\": 1,\n      \"line\": 1,\n      \"offset\": 0,\n    },\n  },\n  \"source\": \"<template><div id= /></div></template>\",\n  \"temps\": 0,\n  \"type\": 0,\n}\n`;\n\nexports[`compiler: parse > Errors > MISSING_ATTRIBUTE_VALUE > <template><div id= ></div></template> 1`] = `\n{\n  \"cached\": [],\n  \"children\": [\n    {\n      \"children\": [\n        {\n          \"children\": [],\n          \"codegenNode\": undefined,\n          \"loc\": {\n            \"end\": {\n              \"column\": 27,\n              \"line\": 1,\n              \"offset\": 26,\n            },\n            \"source\": \"<div id= ></div>\",\n            \"start\": {\n              \"column\": 11,\n              \"line\": 1,\n              \"offset\": 10,\n            },\n          },\n          \"ns\": 0,\n          \"props\": [\n            {\n              \"loc\": {\n                \"end\": {\n                  \"column\": 20,\n                  \"line\": 1,\n                  \"offset\": 19,\n                },\n                \"source\": \"id= \",\n                \"start\": {\n                  \"column\": 16,\n                  \"line\": 1,\n                  \"offset\": 15,\n                },\n              },\n              \"name\": \"id\",\n              \"nameLoc\": {\n                \"end\": {\n                  \"column\": 18,\n                  \"line\": 1,\n                  \"offset\": 17,\n                },\n                \"source\": \"id\",\n                \"start\": {\n                  \"column\": 16,\n                  \"line\": 1,\n                  \"offset\": 15,\n                },\n              },\n              \"type\": 6,\n              \"value\": {\n                \"content\": \"\",\n                \"loc\": {\n                  \"end\": {\n                    \"column\": 20,\n                    \"line\": 1,\n                    \"offset\": 19,\n                  },\n                  \"source\": \"\",\n                  \"start\": {\n                    \"column\": 20,\n                    \"line\": 1,\n                    \"offset\": 19,\n                  },\n                },\n                \"type\": 2,\n              },\n            },\n          ],\n          \"tag\": \"div\",\n          \"tagType\": 0,\n          \"type\": 1,\n        },\n      ],\n      \"codegenNode\": undefined,\n      \"loc\": {\n        \"end\": {\n          \"column\": 38,\n          \"line\": 1,\n          \"offset\": 37,\n        },\n        \"source\": \"<template><div id= ></div></template>\",\n        \"start\": {\n          \"column\": 1,\n          \"line\": 1,\n          \"offset\": 0,\n        },\n      },\n      \"ns\": 0,\n      \"props\": [],\n      \"tag\": \"template\",\n      \"tagType\": 0,\n      \"type\": 1,\n    },\n  ],\n  \"codegenNode\": undefined,\n  \"components\": [],\n  \"directives\": [],\n  \"helpers\": Set {},\n  \"hoists\": [],\n  \"imports\": [],\n  \"loc\": {\n    \"end\": {\n      \"column\": 38,\n      \"line\": 1,\n      \"offset\": 37,\n    },\n    \"source\": \"<template><div id= ></div></template>\",\n    \"start\": {\n      \"column\": 1,\n      \"line\": 1,\n      \"offset\": 0,\n    },\n  },\n  \"source\": \"<template><div id= ></div></template>\",\n  \"temps\": 0,\n  \"type\": 0,\n}\n`;\n\nexports[`compiler: parse > Errors > MISSING_ATTRIBUTE_VALUE > <template><div id=></div></template> 1`] = `\n{\n  \"cached\": [],\n  \"children\": [\n    {\n      \"children\": [\n        {\n          \"children\": [],\n          \"codegenNode\": undefined,\n          \"loc\": {\n            \"end\": {\n              \"column\": 26,\n              \"line\": 1,\n              \"offset\": 25,\n            },\n            \"source\": \"<div id=></div>\",\n            \"start\": {\n              \"column\": 11,\n              \"line\": 1,\n              \"offset\": 10,\n            },\n          },\n          \"ns\": 0,\n          \"props\": [\n            {\n              \"loc\": {\n                \"end\": {\n                  \"column\": 19,\n                  \"line\": 1,\n                  \"offset\": 18,\n                },\n                \"source\": \"id=\",\n                \"start\": {\n                  \"column\": 16,\n                  \"line\": 1,\n                  \"offset\": 15,\n                },\n              },\n              \"name\": \"id\",\n              \"nameLoc\": {\n                \"end\": {\n                  \"column\": 18,\n                  \"line\": 1,\n                  \"offset\": 17,\n                },\n                \"source\": \"id\",\n                \"start\": {\n                  \"column\": 16,\n                  \"line\": 1,\n                  \"offset\": 15,\n                },\n              },\n              \"type\": 6,\n              \"value\": {\n                \"content\": \"\",\n                \"loc\": {\n                  \"end\": {\n                    \"column\": 19,\n                    \"line\": 1,\n                    \"offset\": 18,\n                  },\n                  \"source\": \"\",\n                  \"start\": {\n                    \"column\": 19,\n                    \"line\": 1,\n                    \"offset\": 18,\n                  },\n                },\n                \"type\": 2,\n              },\n            },\n          ],\n          \"tag\": \"div\",\n          \"tagType\": 0,\n          \"type\": 1,\n        },\n      ],\n      \"codegenNode\": undefined,\n      \"loc\": {\n        \"end\": {\n          \"column\": 37,\n          \"line\": 1,\n          \"offset\": 36,\n        },\n        \"source\": \"<template><div id=></div></template>\",\n        \"start\": {\n          \"column\": 1,\n          \"line\": 1,\n          \"offset\": 0,\n        },\n      },\n      \"ns\": 0,\n      \"props\": [],\n      \"tag\": \"template\",\n      \"tagType\": 0,\n      \"type\": 1,\n    },\n  ],\n  \"codegenNode\": undefined,\n  \"components\": [],\n  \"directives\": [],\n  \"helpers\": Set {},\n  \"hoists\": [],\n  \"imports\": [],\n  \"loc\": {\n    \"end\": {\n      \"column\": 37,\n      \"line\": 1,\n      \"offset\": 36,\n    },\n    \"source\": \"<template><div id=></div></template>\",\n    \"start\": {\n      \"column\": 1,\n      \"line\": 1,\n      \"offset\": 0,\n    },\n  },\n  \"source\": \"<template><div id=></div></template>\",\n  \"temps\": 0,\n  \"type\": 0,\n}\n`;\n\nexports[`compiler: parse > Errors > MISSING_END_TAG_NAME > <template></></template> 1`] = `\n{\n  \"cached\": [],\n  \"children\": [\n    {\n      \"children\": [],\n      \"codegenNode\": undefined,\n      \"loc\": {\n        \"end\": {\n          \"column\": 25,\n          \"line\": 1,\n          \"offset\": 24,\n        },\n        \"source\": \"<template></></template>\",\n        \"start\": {\n          \"column\": 1,\n          \"line\": 1,\n          \"offset\": 0,\n        },\n      },\n      \"ns\": 0,\n      \"props\": [],\n      \"tag\": \"template\",\n      \"tagType\": 0,\n      \"type\": 1,\n    },\n  ],\n  \"codegenNode\": undefined,\n  \"components\": [],\n  \"directives\": [],\n  \"helpers\": Set {},\n  \"hoists\": [],\n  \"imports\": [],\n  \"loc\": {\n    \"end\": {\n      \"column\": 25,\n      \"line\": 1,\n      \"offset\": 24,\n    },\n    \"source\": \"<template></></template>\",\n    \"start\": {\n      \"column\": 1,\n      \"line\": 1,\n      \"offset\": 0,\n    },\n  },\n  \"source\": \"<template></></template>\",\n  \"temps\": 0,\n  \"type\": 0,\n}\n`;\n\nexports[`compiler: parse > Errors > UNEXPECTED_CHARACTER_IN_ATTRIBUTE_NAME > <template><div a\"bc=''></div></template> 1`] = `\n{\n  \"cached\": [],\n  \"children\": [\n    {\n      \"children\": [\n        {\n          \"children\": [],\n          \"codegenNode\": undefined,\n          \"loc\": {\n            \"end\": {\n              \"column\": 30,\n              \"line\": 1,\n              \"offset\": 29,\n            },\n            \"source\": \"<div a\"bc=''></div>\",\n            \"start\": {\n              \"column\": 11,\n              \"line\": 1,\n              \"offset\": 10,\n            },\n          },\n          \"ns\": 0,\n          \"props\": [\n            {\n              \"loc\": {\n                \"end\": {\n                  \"column\": 23,\n                  \"line\": 1,\n                  \"offset\": 22,\n                },\n                \"source\": \"a\"bc=''\",\n                \"start\": {\n                  \"column\": 16,\n                  \"line\": 1,\n                  \"offset\": 15,\n                },\n              },\n              \"name\": \"a\"bc\",\n              \"nameLoc\": {\n                \"end\": {\n                  \"column\": 20,\n                  \"line\": 1,\n                  \"offset\": 19,\n                },\n                \"source\": \"a\"bc\",\n                \"start\": {\n                  \"column\": 16,\n                  \"line\": 1,\n                  \"offset\": 15,\n                },\n              },\n              \"type\": 6,\n              \"value\": {\n                \"content\": \"\",\n                \"loc\": {\n                  \"end\": {\n                    \"column\": 23,\n                    \"line\": 1,\n                    \"offset\": 22,\n                  },\n                  \"source\": \"''\",\n                  \"start\": {\n                    \"column\": 21,\n                    \"line\": 1,\n                    \"offset\": 20,\n                  },\n                },\n                \"type\": 2,\n              },\n            },\n          ],\n          \"tag\": \"div\",\n          \"tagType\": 0,\n          \"type\": 1,\n        },\n      ],\n      \"codegenNode\": undefined,\n      \"loc\": {\n        \"end\": {\n          \"column\": 41,\n          \"line\": 1,\n          \"offset\": 40,\n        },\n        \"source\": \"<template><div a\"bc=''></div></template>\",\n        \"start\": {\n          \"column\": 1,\n          \"line\": 1,\n          \"offset\": 0,\n        },\n      },\n      \"ns\": 0,\n      \"props\": [],\n      \"tag\": \"template\",\n      \"tagType\": 0,\n      \"type\": 1,\n    },\n  ],\n  \"codegenNode\": undefined,\n  \"components\": [],\n  \"directives\": [],\n  \"helpers\": Set {},\n  \"hoists\": [],\n  \"imports\": [],\n  \"loc\": {\n    \"end\": {\n      \"column\": 41,\n      \"line\": 1,\n      \"offset\": 40,\n    },\n    \"source\": \"<template><div a\"bc=''></div></template>\",\n    \"start\": {\n      \"column\": 1,\n      \"line\": 1,\n      \"offset\": 0,\n    },\n  },\n  \"source\": \"<template><div a\"bc=''></div></template>\",\n  \"temps\": 0,\n  \"type\": 0,\n}\n`;\n\nexports[`compiler: parse > Errors > UNEXPECTED_CHARACTER_IN_ATTRIBUTE_NAME > <template><div a'bc=''></div></template> 1`] = `\n{\n  \"cached\": [],\n  \"children\": [\n    {\n      \"children\": [\n        {\n          \"children\": [],\n          \"codegenNode\": undefined,\n          \"loc\": {\n            \"end\": {\n              \"column\": 30,\n              \"line\": 1,\n              \"offset\": 29,\n            },\n            \"source\": \"<div a'bc=''></div>\",\n            \"start\": {\n              \"column\": 11,\n              \"line\": 1,\n              \"offset\": 10,\n            },\n          },\n          \"ns\": 0,\n          \"props\": [\n            {\n              \"loc\": {\n                \"end\": {\n                  \"column\": 23,\n                  \"line\": 1,\n                  \"offset\": 22,\n                },\n                \"source\": \"a'bc=''\",\n                \"start\": {\n                  \"column\": 16,\n                  \"line\": 1,\n                  \"offset\": 15,\n                },\n              },\n              \"name\": \"a'bc\",\n              \"nameLoc\": {\n                \"end\": {\n                  \"column\": 20,\n                  \"line\": 1,\n                  \"offset\": 19,\n                },\n                \"source\": \"a'bc\",\n                \"start\": {\n                  \"column\": 16,\n                  \"line\": 1,\n                  \"offset\": 15,\n                },\n              },\n              \"type\": 6,\n              \"value\": {\n                \"content\": \"\",\n                \"loc\": {\n                  \"end\": {\n                    \"column\": 23,\n                    \"line\": 1,\n                    \"offset\": 22,\n                  },\n                  \"source\": \"''\",\n                  \"start\": {\n                    \"column\": 21,\n                    \"line\": 1,\n                    \"offset\": 20,\n                  },\n                },\n                \"type\": 2,\n              },\n            },\n          ],\n          \"tag\": \"div\",\n          \"tagType\": 0,\n          \"type\": 1,\n        },\n      ],\n      \"codegenNode\": undefined,\n      \"loc\": {\n        \"end\": {\n          \"column\": 41,\n          \"line\": 1,\n          \"offset\": 40,\n        },\n        \"source\": \"<template><div a'bc=''></div></template>\",\n        \"start\": {\n          \"column\": 1,\n          \"line\": 1,\n          \"offset\": 0,\n        },\n      },\n      \"ns\": 0,\n      \"props\": [],\n      \"tag\": \"template\",\n      \"tagType\": 0,\n      \"type\": 1,\n    },\n  ],\n  \"codegenNode\": undefined,\n  \"components\": [],\n  \"directives\": [],\n  \"helpers\": Set {},\n  \"hoists\": [],\n  \"imports\": [],\n  \"loc\": {\n    \"end\": {\n      \"column\": 41,\n      \"line\": 1,\n      \"offset\": 40,\n    },\n    \"source\": \"<template><div a'bc=''></div></template>\",\n    \"start\": {\n      \"column\": 1,\n      \"line\": 1,\n      \"offset\": 0,\n    },\n  },\n  \"source\": \"<template><div a'bc=''></div></template>\",\n  \"temps\": 0,\n  \"type\": 0,\n}\n`;\n\nexports[`compiler: parse > Errors > UNEXPECTED_CHARACTER_IN_ATTRIBUTE_NAME > <template><div a<bc=''></div></template> 1`] = `\n{\n  \"cached\": [],\n  \"children\": [\n    {\n      \"children\": [\n        {\n          \"children\": [],\n          \"codegenNode\": undefined,\n          \"loc\": {\n            \"end\": {\n              \"column\": 30,\n              \"line\": 1,\n              \"offset\": 29,\n            },\n            \"source\": \"<div a<bc=''></div>\",\n            \"start\": {\n              \"column\": 11,\n              \"line\": 1,\n              \"offset\": 10,\n            },\n          },\n          \"ns\": 0,\n          \"props\": [\n            {\n              \"loc\": {\n                \"end\": {\n                  \"column\": 23,\n                  \"line\": 1,\n                  \"offset\": 22,\n                },\n                \"source\": \"a<bc=''\",\n                \"start\": {\n                  \"column\": 16,\n                  \"line\": 1,\n                  \"offset\": 15,\n                },\n              },\n              \"name\": \"a<bc\",\n              \"nameLoc\": {\n                \"end\": {\n                  \"column\": 20,\n                  \"line\": 1,\n                  \"offset\": 19,\n                },\n                \"source\": \"a<bc\",\n                \"start\": {\n                  \"column\": 16,\n                  \"line\": 1,\n                  \"offset\": 15,\n                },\n              },\n              \"type\": 6,\n              \"value\": {\n                \"content\": \"\",\n                \"loc\": {\n                  \"end\": {\n                    \"column\": 23,\n                    \"line\": 1,\n                    \"offset\": 22,\n                  },\n                  \"source\": \"''\",\n                  \"start\": {\n                    \"column\": 21,\n                    \"line\": 1,\n                    \"offset\": 20,\n                  },\n                },\n                \"type\": 2,\n              },\n            },\n          ],\n          \"tag\": \"div\",\n          \"tagType\": 0,\n          \"type\": 1,\n        },\n      ],\n      \"codegenNode\": undefined,\n      \"loc\": {\n        \"end\": {\n          \"column\": 41,\n          \"line\": 1,\n          \"offset\": 40,\n        },\n        \"source\": \"<template><div a<bc=''></div></template>\",\n        \"start\": {\n          \"column\": 1,\n          \"line\": 1,\n          \"offset\": 0,\n        },\n      },\n      \"ns\": 0,\n      \"props\": [],\n      \"tag\": \"template\",\n      \"tagType\": 0,\n      \"type\": 1,\n    },\n  ],\n  \"codegenNode\": undefined,\n  \"components\": [],\n  \"directives\": [],\n  \"helpers\": Set {},\n  \"hoists\": [],\n  \"imports\": [],\n  \"loc\": {\n    \"end\": {\n      \"column\": 41,\n      \"line\": 1,\n      \"offset\": 40,\n    },\n    \"source\": \"<template><div a<bc=''></div></template>\",\n    \"start\": {\n      \"column\": 1,\n      \"line\": 1,\n      \"offset\": 0,\n    },\n  },\n  \"source\": \"<template><div a<bc=''></div></template>\",\n  \"temps\": 0,\n  \"type\": 0,\n}\n`;\n\nexports[`compiler: parse > Errors > UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_VALUE > <template><div foo=bar\"></div></template> 1`] = `\n{\n  \"cached\": [],\n  \"children\": [\n    {\n      \"children\": [\n        {\n          \"children\": [],\n          \"codegenNode\": undefined,\n          \"loc\": {\n            \"end\": {\n              \"column\": 31,\n              \"line\": 1,\n              \"offset\": 30,\n            },\n            \"source\": \"<div foo=bar\"></div>\",\n            \"start\": {\n              \"column\": 11,\n              \"line\": 1,\n              \"offset\": 10,\n            },\n          },\n          \"ns\": 0,\n          \"props\": [\n            {\n              \"loc\": {\n                \"end\": {\n                  \"column\": 24,\n                  \"line\": 1,\n                  \"offset\": 23,\n                },\n                \"source\": \"foo=bar\"\",\n                \"start\": {\n                  \"column\": 16,\n                  \"line\": 1,\n                  \"offset\": 15,\n                },\n              },\n              \"name\": \"foo\",\n              \"nameLoc\": {\n                \"end\": {\n                  \"column\": 19,\n                  \"line\": 1,\n                  \"offset\": 18,\n                },\n                \"source\": \"foo\",\n                \"start\": {\n                  \"column\": 16,\n                  \"line\": 1,\n                  \"offset\": 15,\n                },\n              },\n              \"type\": 6,\n              \"value\": {\n                \"content\": \"bar\"\",\n                \"loc\": {\n                  \"end\": {\n                    \"column\": 24,\n                    \"line\": 1,\n                    \"offset\": 23,\n                  },\n                  \"source\": \"bar\"\",\n                  \"start\": {\n                    \"column\": 20,\n                    \"line\": 1,\n                    \"offset\": 19,\n                  },\n                },\n                \"type\": 2,\n              },\n            },\n          ],\n          \"tag\": \"div\",\n          \"tagType\": 0,\n          \"type\": 1,\n        },\n      ],\n      \"codegenNode\": undefined,\n      \"loc\": {\n        \"end\": {\n          \"column\": 42,\n          \"line\": 1,\n          \"offset\": 41,\n        },\n        \"source\": \"<template><div foo=bar\"></div></template>\",\n        \"start\": {\n          \"column\": 1,\n          \"line\": 1,\n          \"offset\": 0,\n        },\n      },\n      \"ns\": 0,\n      \"props\": [],\n      \"tag\": \"template\",\n      \"tagType\": 0,\n      \"type\": 1,\n    },\n  ],\n  \"codegenNode\": undefined,\n  \"components\": [],\n  \"directives\": [],\n  \"helpers\": Set {},\n  \"hoists\": [],\n  \"imports\": [],\n  \"loc\": {\n    \"end\": {\n      \"column\": 42,\n      \"line\": 1,\n      \"offset\": 41,\n    },\n    \"source\": \"<template><div foo=bar\"></div></template>\",\n    \"start\": {\n      \"column\": 1,\n      \"line\": 1,\n      \"offset\": 0,\n    },\n  },\n  \"source\": \"<template><div foo=bar\"></div></template>\",\n  \"temps\": 0,\n  \"type\": 0,\n}\n`;\n\nexports[`compiler: parse > Errors > UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_VALUE > <template><div foo=bar'></div></template> 1`] = `\n{\n  \"cached\": [],\n  \"children\": [\n    {\n      \"children\": [\n        {\n          \"children\": [],\n          \"codegenNode\": undefined,\n          \"loc\": {\n            \"end\": {\n              \"column\": 31,\n              \"line\": 1,\n              \"offset\": 30,\n            },\n            \"source\": \"<div foo=bar'></div>\",\n            \"start\": {\n              \"column\": 11,\n              \"line\": 1,\n              \"offset\": 10,\n            },\n          },\n          \"ns\": 0,\n          \"props\": [\n            {\n              \"loc\": {\n                \"end\": {\n                  \"column\": 24,\n                  \"line\": 1,\n                  \"offset\": 23,\n                },\n                \"source\": \"foo=bar'\",\n                \"start\": {\n                  \"column\": 16,\n                  \"line\": 1,\n                  \"offset\": 15,\n                },\n              },\n              \"name\": \"foo\",\n              \"nameLoc\": {\n                \"end\": {\n                  \"column\": 19,\n                  \"line\": 1,\n                  \"offset\": 18,\n                },\n                \"source\": \"foo\",\n                \"start\": {\n                  \"column\": 16,\n                  \"line\": 1,\n                  \"offset\": 15,\n                },\n              },\n              \"type\": 6,\n              \"value\": {\n                \"content\": \"bar'\",\n                \"loc\": {\n                  \"end\": {\n                    \"column\": 24,\n                    \"line\": 1,\n                    \"offset\": 23,\n                  },\n                  \"source\": \"bar'\",\n                  \"start\": {\n                    \"column\": 20,\n                    \"line\": 1,\n                    \"offset\": 19,\n                  },\n                },\n                \"type\": 2,\n              },\n            },\n          ],\n          \"tag\": \"div\",\n          \"tagType\": 0,\n          \"type\": 1,\n        },\n      ],\n      \"codegenNode\": undefined,\n      \"loc\": {\n        \"end\": {\n          \"column\": 42,\n          \"line\": 1,\n          \"offset\": 41,\n        },\n        \"source\": \"<template><div foo=bar'></div></template>\",\n        \"start\": {\n          \"column\": 1,\n          \"line\": 1,\n          \"offset\": 0,\n        },\n      },\n      \"ns\": 0,\n      \"props\": [],\n      \"tag\": \"template\",\n      \"tagType\": 0,\n      \"type\": 1,\n    },\n  ],\n  \"codegenNode\": undefined,\n  \"components\": [],\n  \"directives\": [],\n  \"helpers\": Set {},\n  \"hoists\": [],\n  \"imports\": [],\n  \"loc\": {\n    \"end\": {\n      \"column\": 42,\n      \"line\": 1,\n      \"offset\": 41,\n    },\n    \"source\": \"<template><div foo=bar'></div></template>\",\n    \"start\": {\n      \"column\": 1,\n      \"line\": 1,\n      \"offset\": 0,\n    },\n  },\n  \"source\": \"<template><div foo=bar'></div></template>\",\n  \"temps\": 0,\n  \"type\": 0,\n}\n`;\n\nexports[`compiler: parse > Errors > UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_VALUE > <template><div foo=bar<div></div></template> 1`] = `\n{\n  \"cached\": [],\n  \"children\": [\n    {\n      \"children\": [\n        {\n          \"children\": [],\n          \"codegenNode\": undefined,\n          \"loc\": {\n            \"end\": {\n              \"column\": 34,\n              \"line\": 1,\n              \"offset\": 33,\n            },\n            \"source\": \"<div foo=bar<div></div>\",\n            \"start\": {\n              \"column\": 11,\n              \"line\": 1,\n              \"offset\": 10,\n            },\n          },\n          \"ns\": 0,\n          \"props\": [\n            {\n              \"loc\": {\n                \"end\": {\n                  \"column\": 27,\n                  \"line\": 1,\n                  \"offset\": 26,\n                },\n                \"source\": \"foo=bar<div\",\n                \"start\": {\n                  \"column\": 16,\n                  \"line\": 1,\n                  \"offset\": 15,\n                },\n              },\n              \"name\": \"foo\",\n              \"nameLoc\": {\n                \"end\": {\n                  \"column\": 19,\n                  \"line\": 1,\n                  \"offset\": 18,\n                },\n                \"source\": \"foo\",\n                \"start\": {\n                  \"column\": 16,\n                  \"line\": 1,\n                  \"offset\": 15,\n                },\n              },\n              \"type\": 6,\n              \"value\": {\n                \"content\": \"bar<div\",\n                \"loc\": {\n                  \"end\": {\n                    \"column\": 27,\n                    \"line\": 1,\n                    \"offset\": 26,\n                  },\n                  \"source\": \"bar<div\",\n                  \"start\": {\n                    \"column\": 20,\n                    \"line\": 1,\n                    \"offset\": 19,\n                  },\n                },\n                \"type\": 2,\n              },\n            },\n          ],\n          \"tag\": \"div\",\n          \"tagType\": 0,\n          \"type\": 1,\n        },\n      ],\n      \"codegenNode\": undefined,\n      \"loc\": {\n        \"end\": {\n          \"column\": 45,\n          \"line\": 1,\n          \"offset\": 44,\n        },\n        \"source\": \"<template><div foo=bar<div></div></template>\",\n        \"start\": {\n          \"column\": 1,\n          \"line\": 1,\n          \"offset\": 0,\n        },\n      },\n      \"ns\": 0,\n      \"props\": [],\n      \"tag\": \"template\",\n      \"tagType\": 0,\n      \"type\": 1,\n    },\n  ],\n  \"codegenNode\": undefined,\n  \"components\": [],\n  \"directives\": [],\n  \"helpers\": Set {},\n  \"hoists\": [],\n  \"imports\": [],\n  \"loc\": {\n    \"end\": {\n      \"column\": 45,\n      \"line\": 1,\n      \"offset\": 44,\n    },\n    \"source\": \"<template><div foo=bar<div></div></template>\",\n    \"start\": {\n      \"column\": 1,\n      \"line\": 1,\n      \"offset\": 0,\n    },\n  },\n  \"source\": \"<template><div foo=bar<div></div></template>\",\n  \"temps\": 0,\n  \"type\": 0,\n}\n`;\n\nexports[`compiler: parse > Errors > UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_VALUE > <template><div foo=bar=baz></div></template> 1`] = `\n{\n  \"cached\": [],\n  \"children\": [\n    {\n      \"children\": [\n        {\n          \"children\": [],\n          \"codegenNode\": undefined,\n          \"loc\": {\n            \"end\": {\n              \"column\": 34,\n              \"line\": 1,\n              \"offset\": 33,\n            },\n            \"source\": \"<div foo=bar=baz></div>\",\n            \"start\": {\n              \"column\": 11,\n              \"line\": 1,\n              \"offset\": 10,\n            },\n          },\n          \"ns\": 0,\n          \"props\": [\n            {\n              \"loc\": {\n                \"end\": {\n                  \"column\": 27,\n                  \"line\": 1,\n                  \"offset\": 26,\n                },\n                \"source\": \"foo=bar=baz\",\n                \"start\": {\n                  \"column\": 16,\n                  \"line\": 1,\n                  \"offset\": 15,\n                },\n              },\n              \"name\": \"foo\",\n              \"nameLoc\": {\n                \"end\": {\n                  \"column\": 19,\n                  \"line\": 1,\n                  \"offset\": 18,\n                },\n                \"source\": \"foo\",\n                \"start\": {\n                  \"column\": 16,\n                  \"line\": 1,\n                  \"offset\": 15,\n                },\n              },\n              \"type\": 6,\n              \"value\": {\n                \"content\": \"bar=baz\",\n                \"loc\": {\n                  \"end\": {\n                    \"column\": 27,\n                    \"line\": 1,\n                    \"offset\": 26,\n                  },\n                  \"source\": \"bar=baz\",\n                  \"start\": {\n                    \"column\": 20,\n                    \"line\": 1,\n                    \"offset\": 19,\n                  },\n                },\n                \"type\": 2,\n              },\n            },\n          ],\n          \"tag\": \"div\",\n          \"tagType\": 0,\n          \"type\": 1,\n        },\n      ],\n      \"codegenNode\": undefined,\n      \"loc\": {\n        \"end\": {\n          \"column\": 45,\n          \"line\": 1,\n          \"offset\": 44,\n        },\n        \"source\": \"<template><div foo=bar=baz></div></template>\",\n        \"start\": {\n          \"column\": 1,\n          \"line\": 1,\n          \"offset\": 0,\n        },\n      },\n      \"ns\": 0,\n      \"props\": [],\n      \"tag\": \"template\",\n      \"tagType\": 0,\n      \"type\": 1,\n    },\n  ],\n  \"codegenNode\": undefined,\n  \"components\": [],\n  \"directives\": [],\n  \"helpers\": Set {},\n  \"hoists\": [],\n  \"imports\": [],\n  \"loc\": {\n    \"end\": {\n      \"column\": 45,\n      \"line\": 1,\n      \"offset\": 44,\n    },\n    \"source\": \"<template><div foo=bar=baz></div></template>\",\n    \"start\": {\n      \"column\": 1,\n      \"line\": 1,\n      \"offset\": 0,\n    },\n  },\n  \"source\": \"<template><div foo=bar=baz></div></template>\",\n  \"temps\": 0,\n  \"type\": 0,\n}\n`;\n\nexports[`compiler: parse > Errors > UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_VALUE > <template><div foo=bar\\`></div></template> 1`] = `\n{\n  \"cached\": [],\n  \"children\": [\n    {\n      \"children\": [\n        {\n          \"children\": [],\n          \"codegenNode\": undefined,\n          \"loc\": {\n            \"end\": {\n              \"column\": 31,\n              \"line\": 1,\n              \"offset\": 30,\n            },\n            \"source\": \"<div foo=bar\\`></div>\",\n            \"start\": {\n              \"column\": 11,\n              \"line\": 1,\n              \"offset\": 10,\n            },\n          },\n          \"ns\": 0,\n          \"props\": [\n            {\n              \"loc\": {\n                \"end\": {\n                  \"column\": 24,\n                  \"line\": 1,\n                  \"offset\": 23,\n                },\n                \"source\": \"foo=bar\\`\",\n                \"start\": {\n                  \"column\": 16,\n                  \"line\": 1,\n                  \"offset\": 15,\n                },\n              },\n              \"name\": \"foo\",\n              \"nameLoc\": {\n                \"end\": {\n                  \"column\": 19,\n                  \"line\": 1,\n                  \"offset\": 18,\n                },\n                \"source\": \"foo\",\n                \"start\": {\n                  \"column\": 16,\n                  \"line\": 1,\n                  \"offset\": 15,\n                },\n              },\n              \"type\": 6,\n              \"value\": {\n                \"content\": \"bar\\`\",\n                \"loc\": {\n                  \"end\": {\n                    \"column\": 24,\n                    \"line\": 1,\n                    \"offset\": 23,\n                  },\n                  \"source\": \"bar\\`\",\n                  \"start\": {\n                    \"column\": 20,\n                    \"line\": 1,\n                    \"offset\": 19,\n                  },\n                },\n                \"type\": 2,\n              },\n            },\n          ],\n          \"tag\": \"div\",\n          \"tagType\": 0,\n          \"type\": 1,\n        },\n      ],\n      \"codegenNode\": undefined,\n      \"loc\": {\n        \"end\": {\n          \"column\": 42,\n          \"line\": 1,\n          \"offset\": 41,\n        },\n        \"source\": \"<template><div foo=bar\\`></div></template>\",\n        \"start\": {\n          \"column\": 1,\n          \"line\": 1,\n          \"offset\": 0,\n        },\n      },\n      \"ns\": 0,\n      \"props\": [],\n      \"tag\": \"template\",\n      \"tagType\": 0,\n      \"type\": 1,\n    },\n  ],\n  \"codegenNode\": undefined,\n  \"components\": [],\n  \"directives\": [],\n  \"helpers\": Set {},\n  \"hoists\": [],\n  \"imports\": [],\n  \"loc\": {\n    \"end\": {\n      \"column\": 42,\n      \"line\": 1,\n      \"offset\": 41,\n    },\n    \"source\": \"<template><div foo=bar\\`></div></template>\",\n    \"start\": {\n      \"column\": 1,\n      \"line\": 1,\n      \"offset\": 0,\n    },\n  },\n  \"source\": \"<template><div foo=bar\\`></div></template>\",\n  \"temps\": 0,\n  \"type\": 0,\n}\n`;\n\nexports[`compiler: parse > Errors > UNEXPECTED_EQUALS_SIGN_BEFORE_ATTRIBUTE_NAME > <template><div =></div></template> 1`] = `\n{\n  \"cached\": [],\n  \"children\": [\n    {\n      \"children\": [\n        {\n          \"children\": [],\n          \"codegenNode\": undefined,\n          \"loc\": {\n            \"end\": {\n              \"column\": 24,\n              \"line\": 1,\n              \"offset\": 23,\n            },\n            \"source\": \"<div =></div>\",\n            \"start\": {\n              \"column\": 11,\n              \"line\": 1,\n              \"offset\": 10,\n            },\n          },\n          \"ns\": 0,\n          \"props\": [\n            {\n              \"loc\": {\n                \"end\": {\n                  \"column\": 17,\n                  \"line\": 1,\n                  \"offset\": 16,\n                },\n                \"source\": \"=\",\n                \"start\": {\n                  \"column\": 16,\n                  \"line\": 1,\n                  \"offset\": 15,\n                },\n              },\n              \"name\": \"=\",\n              \"nameLoc\": {\n                \"end\": {\n                  \"column\": 17,\n                  \"line\": 1,\n                  \"offset\": 16,\n                },\n                \"source\": \"=\",\n                \"start\": {\n                  \"column\": 16,\n                  \"line\": 1,\n                  \"offset\": 15,\n                },\n              },\n              \"type\": 6,\n              \"value\": undefined,\n            },\n          ],\n          \"tag\": \"div\",\n          \"tagType\": 0,\n          \"type\": 1,\n        },\n      ],\n      \"codegenNode\": undefined,\n      \"loc\": {\n        \"end\": {\n          \"column\": 35,\n          \"line\": 1,\n          \"offset\": 34,\n        },\n        \"source\": \"<template><div =></div></template>\",\n        \"start\": {\n          \"column\": 1,\n          \"line\": 1,\n          \"offset\": 0,\n        },\n      },\n      \"ns\": 0,\n      \"props\": [],\n      \"tag\": \"template\",\n      \"tagType\": 0,\n      \"type\": 1,\n    },\n  ],\n  \"codegenNode\": undefined,\n  \"components\": [],\n  \"directives\": [],\n  \"helpers\": Set {},\n  \"hoists\": [],\n  \"imports\": [],\n  \"loc\": {\n    \"end\": {\n      \"column\": 35,\n      \"line\": 1,\n      \"offset\": 34,\n    },\n    \"source\": \"<template><div =></div></template>\",\n    \"start\": {\n      \"column\": 1,\n      \"line\": 1,\n      \"offset\": 0,\n    },\n  },\n  \"source\": \"<template><div =></div></template>\",\n  \"temps\": 0,\n  \"type\": 0,\n}\n`;\n\nexports[`compiler: parse > Errors > UNEXPECTED_EQUALS_SIGN_BEFORE_ATTRIBUTE_NAME > <template><div =foo=bar></div></template> 1`] = `\n{\n  \"cached\": [],\n  \"children\": [\n    {\n      \"children\": [\n        {\n          \"children\": [],\n          \"codegenNode\": undefined,\n          \"loc\": {\n            \"end\": {\n              \"column\": 31,\n              \"line\": 1,\n              \"offset\": 30,\n            },\n            \"source\": \"<div =foo=bar></div>\",\n            \"start\": {\n              \"column\": 11,\n              \"line\": 1,\n              \"offset\": 10,\n            },\n          },\n          \"ns\": 0,\n          \"props\": [\n            {\n              \"loc\": {\n                \"end\": {\n                  \"column\": 24,\n                  \"line\": 1,\n                  \"offset\": 23,\n                },\n                \"source\": \"=foo=bar\",\n                \"start\": {\n                  \"column\": 16,\n                  \"line\": 1,\n                  \"offset\": 15,\n                },\n              },\n              \"name\": \"=foo\",\n              \"nameLoc\": {\n                \"end\": {\n                  \"column\": 20,\n                  \"line\": 1,\n                  \"offset\": 19,\n                },\n                \"source\": \"=foo\",\n                \"start\": {\n                  \"column\": 16,\n                  \"line\": 1,\n                  \"offset\": 15,\n                },\n              },\n              \"type\": 6,\n              \"value\": {\n                \"content\": \"bar\",\n                \"loc\": {\n                  \"end\": {\n                    \"column\": 24,\n                    \"line\": 1,\n                    \"offset\": 23,\n                  },\n                  \"source\": \"bar\",\n                  \"start\": {\n                    \"column\": 21,\n                    \"line\": 1,\n                    \"offset\": 20,\n                  },\n                },\n                \"type\": 2,\n              },\n            },\n          ],\n          \"tag\": \"div\",\n          \"tagType\": 0,\n          \"type\": 1,\n        },\n      ],\n      \"codegenNode\": undefined,\n      \"loc\": {\n        \"end\": {\n          \"column\": 42,\n          \"line\": 1,\n          \"offset\": 41,\n        },\n        \"source\": \"<template><div =foo=bar></div></template>\",\n        \"start\": {\n          \"column\": 1,\n          \"line\": 1,\n          \"offset\": 0,\n        },\n      },\n      \"ns\": 0,\n      \"props\": [],\n      \"tag\": \"template\",\n      \"tagType\": 0,\n      \"type\": 1,\n    },\n  ],\n  \"codegenNode\": undefined,\n  \"components\": [],\n  \"directives\": [],\n  \"helpers\": Set {},\n  \"hoists\": [],\n  \"imports\": [],\n  \"loc\": {\n    \"end\": {\n      \"column\": 42,\n      \"line\": 1,\n      \"offset\": 41,\n    },\n    \"source\": \"<template><div =foo=bar></div></template>\",\n    \"start\": {\n      \"column\": 1,\n      \"line\": 1,\n      \"offset\": 0,\n    },\n  },\n  \"source\": \"<template><div =foo=bar></div></template>\",\n  \"temps\": 0,\n  \"type\": 0,\n}\n`;\n\nexports[`compiler: parse > Errors > UNEXPECTED_QUESTION_MARK_INSTEAD_OF_TAG_NAME > <template><?xml?></template> 1`] = `\n{\n  \"cached\": [],\n  \"children\": [\n    {\n      \"children\": [],\n      \"codegenNode\": undefined,\n      \"loc\": {\n        \"end\": {\n          \"column\": 29,\n          \"line\": 1,\n          \"offset\": 28,\n        },\n        \"source\": \"<template><?xml?></template>\",\n        \"start\": {\n          \"column\": 1,\n          \"line\": 1,\n          \"offset\": 0,\n        },\n      },\n      \"ns\": 0,\n      \"props\": [],\n      \"tag\": \"template\",\n      \"tagType\": 0,\n      \"type\": 1,\n    },\n  ],\n  \"codegenNode\": undefined,\n  \"components\": [],\n  \"directives\": [],\n  \"helpers\": Set {},\n  \"hoists\": [],\n  \"imports\": [],\n  \"loc\": {\n    \"end\": {\n      \"column\": 29,\n      \"line\": 1,\n      \"offset\": 28,\n    },\n    \"source\": \"<template><?xml?></template>\",\n    \"start\": {\n      \"column\": 1,\n      \"line\": 1,\n      \"offset\": 0,\n    },\n  },\n  \"source\": \"<template><?xml?></template>\",\n  \"temps\": 0,\n  \"type\": 0,\n}\n`;\n\nexports[`compiler: parse > Errors > UNEXPECTED_SOLIDUS_IN_TAG > <template><div a/b></div></template> 1`] = `\n{\n  \"cached\": [],\n  \"children\": [\n    {\n      \"children\": [\n        {\n          \"children\": [],\n          \"codegenNode\": undefined,\n          \"loc\": {\n            \"end\": {\n              \"column\": 26,\n              \"line\": 1,\n              \"offset\": 25,\n            },\n            \"source\": \"<div a/b></div>\",\n            \"start\": {\n              \"column\": 11,\n              \"line\": 1,\n              \"offset\": 10,\n            },\n          },\n          \"ns\": 0,\n          \"props\": [\n            {\n              \"loc\": {\n                \"end\": {\n                  \"column\": 17,\n                  \"line\": 1,\n                  \"offset\": 16,\n                },\n                \"source\": \"a\",\n                \"start\": {\n                  \"column\": 16,\n                  \"line\": 1,\n                  \"offset\": 15,\n                },\n              },\n              \"name\": \"a\",\n              \"nameLoc\": {\n                \"end\": {\n                  \"column\": 17,\n                  \"line\": 1,\n                  \"offset\": 16,\n                },\n                \"source\": \"a\",\n                \"start\": {\n                  \"column\": 16,\n                  \"line\": 1,\n                  \"offset\": 15,\n                },\n              },\n              \"type\": 6,\n              \"value\": undefined,\n            },\n            {\n              \"loc\": {\n                \"end\": {\n                  \"column\": 19,\n                  \"line\": 1,\n                  \"offset\": 18,\n                },\n                \"source\": \"b\",\n                \"start\": {\n                  \"column\": 18,\n                  \"line\": 1,\n                  \"offset\": 17,\n                },\n              },\n              \"name\": \"b\",\n              \"nameLoc\": {\n                \"end\": {\n                  \"column\": 19,\n                  \"line\": 1,\n                  \"offset\": 18,\n                },\n                \"source\": \"b\",\n                \"start\": {\n                  \"column\": 18,\n                  \"line\": 1,\n                  \"offset\": 17,\n                },\n              },\n              \"type\": 6,\n              \"value\": undefined,\n            },\n          ],\n          \"tag\": \"div\",\n          \"tagType\": 0,\n          \"type\": 1,\n        },\n      ],\n      \"codegenNode\": undefined,\n      \"loc\": {\n        \"end\": {\n          \"column\": 37,\n          \"line\": 1,\n          \"offset\": 36,\n        },\n        \"source\": \"<template><div a/b></div></template>\",\n        \"start\": {\n          \"column\": 1,\n          \"line\": 1,\n          \"offset\": 0,\n        },\n      },\n      \"ns\": 0,\n      \"props\": [],\n      \"tag\": \"template\",\n      \"tagType\": 0,\n      \"type\": 1,\n    },\n  ],\n  \"codegenNode\": undefined,\n  \"components\": [],\n  \"directives\": [],\n  \"helpers\": Set {},\n  \"hoists\": [],\n  \"imports\": [],\n  \"loc\": {\n    \"end\": {\n      \"column\": 37,\n      \"line\": 1,\n      \"offset\": 36,\n    },\n    \"source\": \"<template><div a/b></div></template>\",\n    \"start\": {\n      \"column\": 1,\n      \"line\": 1,\n      \"offset\": 0,\n    },\n  },\n  \"source\": \"<template><div a/b></div></template>\",\n  \"temps\": 0,\n  \"type\": 0,\n}\n`;\n\nexports[`compiler: parse > Errors > X_INVALID_END_TAG > <svg><![CDATA[</div>]]></svg> 1`] = `\n{\n  \"cached\": [],\n  \"children\": [\n    {\n      \"children\": [\n        {\n          \"content\": \"</div>\",\n          \"loc\": {\n            \"end\": {\n              \"column\": 21,\n              \"line\": 1,\n              \"offset\": 20,\n            },\n            \"source\": \"</div>\",\n            \"start\": {\n              \"column\": 15,\n              \"line\": 1,\n              \"offset\": 14,\n            },\n          },\n          \"type\": 2,\n        },\n      ],\n      \"codegenNode\": undefined,\n      \"loc\": {\n        \"end\": {\n          \"column\": 30,\n          \"line\": 1,\n          \"offset\": 29,\n        },\n        \"source\": \"<svg><![CDATA[</div>]]></svg>\",\n        \"start\": {\n          \"column\": 1,\n          \"line\": 1,\n          \"offset\": 0,\n        },\n      },\n      \"ns\": 1,\n      \"props\": [],\n      \"tag\": \"svg\",\n      \"tagType\": 0,\n      \"type\": 1,\n    },\n  ],\n  \"codegenNode\": undefined,\n  \"components\": [],\n  \"directives\": [],\n  \"helpers\": Set {},\n  \"hoists\": [],\n  \"imports\": [],\n  \"loc\": {\n    \"end\": {\n      \"column\": 30,\n      \"line\": 1,\n      \"offset\": 29,\n    },\n    \"source\": \"<svg><![CDATA[</div>]]></svg>\",\n    \"start\": {\n      \"column\": 1,\n      \"line\": 1,\n      \"offset\": 0,\n    },\n  },\n  \"source\": \"<svg><![CDATA[</div>]]></svg>\",\n  \"temps\": 0,\n  \"type\": 0,\n}\n`;\n\nexports[`compiler: parse > Errors > X_INVALID_END_TAG > <svg><!--</div>--></svg> 1`] = `\n{\n  \"cached\": [],\n  \"children\": [\n    {\n      \"children\": [\n        {\n          \"content\": \"</div>\",\n          \"loc\": {\n            \"end\": {\n              \"column\": 19,\n              \"line\": 1,\n              \"offset\": 18,\n            },\n            \"source\": \"<!--</div>-->\",\n            \"start\": {\n              \"column\": 6,\n              \"line\": 1,\n              \"offset\": 5,\n            },\n          },\n          \"type\": 3,\n        },\n      ],\n      \"codegenNode\": undefined,\n      \"loc\": {\n        \"end\": {\n          \"column\": 25,\n          \"line\": 1,\n          \"offset\": 24,\n        },\n        \"source\": \"<svg><!--</div>--></svg>\",\n        \"start\": {\n          \"column\": 1,\n          \"line\": 1,\n          \"offset\": 0,\n        },\n      },\n      \"ns\": 1,\n      \"props\": [],\n      \"tag\": \"svg\",\n      \"tagType\": 0,\n      \"type\": 1,\n    },\n  ],\n  \"codegenNode\": undefined,\n  \"components\": [],\n  \"directives\": [],\n  \"helpers\": Set {},\n  \"hoists\": [],\n  \"imports\": [],\n  \"loc\": {\n    \"end\": {\n      \"column\": 25,\n      \"line\": 1,\n      \"offset\": 24,\n    },\n    \"source\": \"<svg><!--</div>--></svg>\",\n    \"start\": {\n      \"column\": 1,\n      \"line\": 1,\n      \"offset\": 0,\n    },\n  },\n  \"source\": \"<svg><!--</div>--></svg>\",\n  \"temps\": 0,\n  \"type\": 0,\n}\n`;\n\nexports[`compiler: parse > Errors > X_INVALID_END_TAG > <template></div></div></template> 1`] = `\n{\n  \"cached\": [],\n  \"children\": [\n    {\n      \"children\": [],\n      \"codegenNode\": undefined,\n      \"loc\": {\n        \"end\": {\n          \"column\": 34,\n          \"line\": 1,\n          \"offset\": 33,\n        },\n        \"source\": \"<template></div></div></template>\",\n        \"start\": {\n          \"column\": 1,\n          \"line\": 1,\n          \"offset\": 0,\n        },\n      },\n      \"ns\": 0,\n      \"props\": [],\n      \"tag\": \"template\",\n      \"tagType\": 0,\n      \"type\": 1,\n    },\n  ],\n  \"codegenNode\": undefined,\n  \"components\": [],\n  \"directives\": [],\n  \"helpers\": Set {},\n  \"hoists\": [],\n  \"imports\": [],\n  \"loc\": {\n    \"end\": {\n      \"column\": 34,\n      \"line\": 1,\n      \"offset\": 33,\n    },\n    \"source\": \"<template></div></div></template>\",\n    \"start\": {\n      \"column\": 1,\n      \"line\": 1,\n      \"offset\": 0,\n    },\n  },\n  \"source\": \"<template></div></div></template>\",\n  \"temps\": 0,\n  \"type\": 0,\n}\n`;\n\nexports[`compiler: parse > Errors > X_INVALID_END_TAG > <template></div></template> 1`] = `\n{\n  \"cached\": [],\n  \"children\": [\n    {\n      \"children\": [],\n      \"codegenNode\": undefined,\n      \"loc\": {\n        \"end\": {\n          \"column\": 28,\n          \"line\": 1,\n          \"offset\": 27,\n        },\n        \"source\": \"<template></div></template>\",\n        \"start\": {\n          \"column\": 1,\n          \"line\": 1,\n          \"offset\": 0,\n        },\n      },\n      \"ns\": 0,\n      \"props\": [],\n      \"tag\": \"template\",\n      \"tagType\": 0,\n      \"type\": 1,\n    },\n  ],\n  \"codegenNode\": undefined,\n  \"components\": [],\n  \"directives\": [],\n  \"helpers\": Set {},\n  \"hoists\": [],\n  \"imports\": [],\n  \"loc\": {\n    \"end\": {\n      \"column\": 28,\n      \"line\": 1,\n      \"offset\": 27,\n    },\n    \"source\": \"<template></div></template>\",\n    \"start\": {\n      \"column\": 1,\n      \"line\": 1,\n      \"offset\": 0,\n    },\n  },\n  \"source\": \"<template></div></template>\",\n  \"temps\": 0,\n  \"type\": 0,\n}\n`;\n\nexports[`compiler: parse > Errors > X_INVALID_END_TAG > <template>{{'</div>'}}</template> 1`] = `\n{\n  \"cached\": [],\n  \"children\": [\n    {\n      \"children\": [\n        {\n          \"content\": {\n            \"constType\": 0,\n            \"content\": \"'</div>'\",\n            \"isStatic\": false,\n            \"loc\": {\n              \"end\": {\n                \"column\": 21,\n                \"line\": 1,\n                \"offset\": 20,\n              },\n              \"source\": \"'</div>'\",\n              \"start\": {\n                \"column\": 13,\n                \"line\": 1,\n                \"offset\": 12,\n              },\n            },\n            \"type\": 4,\n          },\n          \"loc\": {\n            \"end\": {\n              \"column\": 23,\n              \"line\": 1,\n              \"offset\": 22,\n            },\n            \"source\": \"{{'</div>'}}\",\n            \"start\": {\n              \"column\": 11,\n              \"line\": 1,\n              \"offset\": 10,\n            },\n          },\n          \"type\": 5,\n        },\n      ],\n      \"codegenNode\": undefined,\n      \"loc\": {\n        \"end\": {\n          \"column\": 34,\n          \"line\": 1,\n          \"offset\": 33,\n        },\n        \"source\": \"<template>{{'</div>'}}</template>\",\n        \"start\": {\n          \"column\": 1,\n          \"line\": 1,\n          \"offset\": 0,\n        },\n      },\n      \"ns\": 0,\n      \"props\": [],\n      \"tag\": \"template\",\n      \"tagType\": 0,\n      \"type\": 1,\n    },\n  ],\n  \"codegenNode\": undefined,\n  \"components\": [],\n  \"directives\": [],\n  \"helpers\": Set {},\n  \"hoists\": [],\n  \"imports\": [],\n  \"loc\": {\n    \"end\": {\n      \"column\": 34,\n      \"line\": 1,\n      \"offset\": 33,\n    },\n    \"source\": \"<template>{{'</div>'}}</template>\",\n    \"start\": {\n      \"column\": 1,\n      \"line\": 1,\n      \"offset\": 0,\n    },\n  },\n  \"source\": \"<template>{{'</div>'}}</template>\",\n  \"temps\": 0,\n  \"type\": 0,\n}\n`;\n\nexports[`compiler: parse > Errors > X_INVALID_END_TAG > <template>a </ b</template> 1`] = `\n{\n  \"cached\": [],\n  \"children\": [\n    {\n      \"children\": [\n        {\n          \"content\": \"a \",\n          \"loc\": {\n            \"end\": {\n              \"column\": 13,\n              \"line\": 1,\n              \"offset\": 12,\n            },\n            \"source\": \"a \",\n            \"start\": {\n              \"column\": 11,\n              \"line\": 1,\n              \"offset\": 10,\n            },\n          },\n          \"type\": 2,\n        },\n      ],\n      \"codegenNode\": undefined,\n      \"loc\": {\n        \"end\": {\n          \"column\": 28,\n          \"line\": 1,\n          \"offset\": 27,\n        },\n        \"source\": \"<template>a </ b</template>\",\n        \"start\": {\n          \"column\": 1,\n          \"line\": 1,\n          \"offset\": 0,\n        },\n      },\n      \"ns\": 0,\n      \"props\": [],\n      \"tag\": \"template\",\n      \"tagType\": 0,\n      \"type\": 1,\n    },\n  ],\n  \"codegenNode\": undefined,\n  \"components\": [],\n  \"directives\": [],\n  \"helpers\": Set {},\n  \"hoists\": [],\n  \"imports\": [],\n  \"loc\": {\n    \"end\": {\n      \"column\": 28,\n      \"line\": 1,\n      \"offset\": 27,\n    },\n    \"source\": \"<template>a </ b</template>\",\n    \"start\": {\n      \"column\": 1,\n      \"line\": 1,\n      \"offset\": 0,\n    },\n  },\n  \"source\": \"<template>a </ b</template>\",\n  \"temps\": 0,\n  \"type\": 0,\n}\n`;\n\nexports[`compiler: parse > Errors > X_INVALID_END_TAG > <textarea></div></textarea> 1`] = `\n{\n  \"cached\": [],\n  \"children\": [\n    {\n      \"children\": [\n        {\n          \"content\": \"</div>\",\n          \"loc\": {\n            \"end\": {\n              \"column\": 17,\n              \"line\": 1,\n              \"offset\": 16,\n            },\n            \"source\": \"</div>\",\n            \"start\": {\n              \"column\": 11,\n              \"line\": 1,\n              \"offset\": 10,\n            },\n          },\n          \"type\": 2,\n        },\n      ],\n      \"codegenNode\": undefined,\n      \"loc\": {\n        \"end\": {\n          \"column\": 28,\n          \"line\": 1,\n          \"offset\": 27,\n        },\n        \"source\": \"<textarea></div></textarea>\",\n        \"start\": {\n          \"column\": 1,\n          \"line\": 1,\n          \"offset\": 0,\n        },\n      },\n      \"ns\": 0,\n      \"props\": [],\n      \"tag\": \"textarea\",\n      \"tagType\": 0,\n      \"type\": 1,\n    },\n  ],\n  \"codegenNode\": undefined,\n  \"components\": [],\n  \"directives\": [],\n  \"helpers\": Set {},\n  \"hoists\": [],\n  \"imports\": [],\n  \"loc\": {\n    \"end\": {\n      \"column\": 28,\n      \"line\": 1,\n      \"offset\": 27,\n    },\n    \"source\": \"<textarea></div></textarea>\",\n    \"start\": {\n      \"column\": 1,\n      \"line\": 1,\n      \"offset\": 0,\n    },\n  },\n  \"source\": \"<textarea></div></textarea>\",\n  \"temps\": 0,\n  \"type\": 0,\n}\n`;\n\nexports[`compiler: parse > Errors > X_MISSING_DYNAMIC_DIRECTIVE_ARGUMENT_END > <div v-foo:[sef fsef] /> 1`] = `\n{\n  \"cached\": [],\n  \"children\": [\n    {\n      \"children\": [],\n      \"codegenNode\": undefined,\n      \"isSelfClosing\": true,\n      \"loc\": {\n        \"end\": {\n          \"column\": 25,\n          \"line\": 1,\n          \"offset\": 24,\n        },\n        \"source\": \"<div v-foo:[sef fsef] />\",\n        \"start\": {\n          \"column\": 1,\n          \"line\": 1,\n          \"offset\": 0,\n        },\n      },\n      \"ns\": 0,\n      \"props\": [\n        {\n          \"arg\": {\n            \"constType\": 0,\n            \"content\": \"sef\",\n            \"isStatic\": false,\n            \"loc\": {\n              \"end\": {\n                \"column\": 17,\n                \"line\": 1,\n                \"offset\": 16,\n              },\n              \"source\": \"[sef \",\n              \"start\": {\n                \"column\": 12,\n                \"line\": 1,\n                \"offset\": 11,\n              },\n            },\n            \"type\": 4,\n          },\n          \"exp\": undefined,\n          \"loc\": {\n            \"end\": {\n              \"column\": 16,\n              \"line\": 1,\n              \"offset\": 15,\n            },\n            \"source\": \"v-foo:[sef\",\n            \"start\": {\n              \"column\": 6,\n              \"line\": 1,\n              \"offset\": 5,\n            },\n          },\n          \"modifiers\": [],\n          \"name\": \"foo\",\n          \"rawName\": \"v-foo:[sef\",\n          \"type\": 7,\n        },\n        {\n          \"loc\": {\n            \"end\": {\n              \"column\": 22,\n              \"line\": 1,\n              \"offset\": 21,\n            },\n            \"source\": \"fsef]\",\n            \"start\": {\n              \"column\": 17,\n              \"line\": 1,\n              \"offset\": 16,\n            },\n          },\n          \"name\": \"fsef]\",\n          \"nameLoc\": {\n            \"end\": {\n              \"column\": 22,\n              \"line\": 1,\n              \"offset\": 21,\n            },\n            \"source\": \"fsef]\",\n            \"start\": {\n              \"column\": 17,\n              \"line\": 1,\n              \"offset\": 16,\n            },\n          },\n          \"type\": 6,\n          \"value\": undefined,\n        },\n      ],\n      \"tag\": \"div\",\n      \"tagType\": 0,\n      \"type\": 1,\n    },\n  ],\n  \"codegenNode\": undefined,\n  \"components\": [],\n  \"directives\": [],\n  \"helpers\": Set {},\n  \"hoists\": [],\n  \"imports\": [],\n  \"loc\": {\n    \"end\": {\n      \"column\": 25,\n      \"line\": 1,\n      \"offset\": 24,\n    },\n    \"source\": \"<div v-foo:[sef fsef] />\",\n    \"start\": {\n      \"column\": 1,\n      \"line\": 1,\n      \"offset\": 0,\n    },\n  },\n  \"source\": \"<div v-foo:[sef fsef] />\",\n  \"temps\": 0,\n  \"type\": 0,\n}\n`;\n\nexports[`compiler: parse > Errors > X_MISSING_END_TAG > <template><div> 1`] = `\n{\n  \"cached\": [],\n  \"children\": [\n    {\n      \"children\": [\n        {\n          \"children\": [],\n          \"codegenNode\": undefined,\n          \"loc\": {\n            \"end\": {\n              \"column\": 16,\n              \"line\": 1,\n              \"offset\": 15,\n            },\n            \"source\": \"<div>\",\n            \"start\": {\n              \"column\": 11,\n              \"line\": 1,\n              \"offset\": 10,\n            },\n          },\n          \"ns\": 0,\n          \"props\": [],\n          \"tag\": \"div\",\n          \"tagType\": 0,\n          \"type\": 1,\n        },\n      ],\n      \"codegenNode\": undefined,\n      \"loc\": {\n        \"end\": {\n          \"column\": 16,\n          \"line\": 1,\n          \"offset\": 15,\n        },\n        \"source\": \"<template><div>\",\n        \"start\": {\n          \"column\": 1,\n          \"line\": 1,\n          \"offset\": 0,\n        },\n      },\n      \"ns\": 0,\n      \"props\": [],\n      \"tag\": \"template\",\n      \"tagType\": 0,\n      \"type\": 1,\n    },\n  ],\n  \"codegenNode\": undefined,\n  \"components\": [],\n  \"directives\": [],\n  \"helpers\": Set {},\n  \"hoists\": [],\n  \"imports\": [],\n  \"loc\": {\n    \"end\": {\n      \"column\": 16,\n      \"line\": 1,\n      \"offset\": 15,\n    },\n    \"source\": \"<template><div>\",\n    \"start\": {\n      \"column\": 1,\n      \"line\": 1,\n      \"offset\": 0,\n    },\n  },\n  \"source\": \"<template><div>\",\n  \"temps\": 0,\n  \"type\": 0,\n}\n`;\n\nexports[`compiler: parse > Errors > X_MISSING_END_TAG > <template><div></template> 1`] = `\n{\n  \"cached\": [],\n  \"children\": [\n    {\n      \"children\": [\n        {\n          \"children\": [],\n          \"codegenNode\": undefined,\n          \"loc\": {\n            \"end\": {\n              \"column\": 16,\n              \"line\": 1,\n              \"offset\": 15,\n            },\n            \"source\": \"<div>\",\n            \"start\": {\n              \"column\": 11,\n              \"line\": 1,\n              \"offset\": 10,\n            },\n          },\n          \"ns\": 0,\n          \"props\": [],\n          \"tag\": \"div\",\n          \"tagType\": 0,\n          \"type\": 1,\n        },\n      ],\n      \"codegenNode\": undefined,\n      \"loc\": {\n        \"end\": {\n          \"column\": 27,\n          \"line\": 1,\n          \"offset\": 26,\n        },\n        \"source\": \"<template><div></template>\",\n        \"start\": {\n          \"column\": 1,\n          \"line\": 1,\n          \"offset\": 0,\n        },\n      },\n      \"ns\": 0,\n      \"props\": [],\n      \"tag\": \"template\",\n      \"tagType\": 0,\n      \"type\": 1,\n    },\n  ],\n  \"codegenNode\": undefined,\n  \"components\": [],\n  \"directives\": [],\n  \"helpers\": Set {},\n  \"hoists\": [],\n  \"imports\": [],\n  \"loc\": {\n    \"end\": {\n      \"column\": 27,\n      \"line\": 1,\n      \"offset\": 26,\n    },\n    \"source\": \"<template><div></template>\",\n    \"start\": {\n      \"column\": 1,\n      \"line\": 1,\n      \"offset\": 0,\n    },\n  },\n  \"source\": \"<template><div></template>\",\n  \"temps\": 0,\n  \"type\": 0,\n}\n`;\n\nexports[`compiler: parse > Errors > X_MISSING_INTERPOLATION_END > <div>{{ foo</div> 1`] = `\n{\n  \"cached\": [],\n  \"children\": [\n    {\n      \"children\": [\n        {\n          \"content\": \"{{ foo</div>\",\n          \"loc\": {\n            \"end\": {\n              \"column\": 18,\n              \"line\": 1,\n              \"offset\": 17,\n            },\n            \"source\": \"{{ foo</div>\",\n            \"start\": {\n              \"column\": 6,\n              \"line\": 1,\n              \"offset\": 5,\n            },\n          },\n          \"type\": 2,\n        },\n      ],\n      \"codegenNode\": undefined,\n      \"loc\": {\n        \"end\": {\n          \"column\": 18,\n          \"line\": 1,\n          \"offset\": 17,\n        },\n        \"source\": \"<div>{{ foo</div>\",\n        \"start\": {\n          \"column\": 1,\n          \"line\": 1,\n          \"offset\": 0,\n        },\n      },\n      \"ns\": 0,\n      \"props\": [],\n      \"tag\": \"div\",\n      \"tagType\": 0,\n      \"type\": 1,\n    },\n  ],\n  \"codegenNode\": undefined,\n  \"components\": [],\n  \"directives\": [],\n  \"helpers\": Set {},\n  \"hoists\": [],\n  \"imports\": [],\n  \"loc\": {\n    \"end\": {\n      \"column\": 18,\n      \"line\": 1,\n      \"offset\": 17,\n    },\n    \"source\": \"<div>{{ foo</div>\",\n    \"start\": {\n      \"column\": 1,\n      \"line\": 1,\n      \"offset\": 0,\n    },\n  },\n  \"source\": \"<div>{{ foo</div>\",\n  \"temps\": 0,\n  \"type\": 0,\n}\n`;\n\nexports[`compiler: parse > Errors > X_MISSING_INTERPOLATION_END > {{ 1`] = `\n{\n  \"cached\": [],\n  \"children\": [\n    {\n      \"content\": \"{{\",\n      \"loc\": {\n        \"end\": {\n          \"column\": 3,\n          \"line\": 1,\n          \"offset\": 2,\n        },\n        \"source\": \"{{\",\n        \"start\": {\n          \"column\": 1,\n          \"line\": 1,\n          \"offset\": 0,\n        },\n      },\n      \"type\": 2,\n    },\n  ],\n  \"codegenNode\": undefined,\n  \"components\": [],\n  \"directives\": [],\n  \"helpers\": Set {},\n  \"hoists\": [],\n  \"imports\": [],\n  \"loc\": {\n    \"end\": {\n      \"column\": 3,\n      \"line\": 1,\n      \"offset\": 2,\n    },\n    \"source\": \"{{\",\n    \"start\": {\n      \"column\": 1,\n      \"line\": 1,\n      \"offset\": 0,\n    },\n  },\n  \"source\": \"{{\",\n  \"temps\": 0,\n  \"type\": 0,\n}\n`;\n\nexports[`compiler: parse > Errors > X_MISSING_INTERPOLATION_END > {{ foo 1`] = `\n{\n  \"cached\": [],\n  \"children\": [\n    {\n      \"content\": \"{{ foo\",\n      \"loc\": {\n        \"end\": {\n          \"column\": 7,\n          \"line\": 1,\n          \"offset\": 6,\n        },\n        \"source\": \"{{ foo\",\n        \"start\": {\n          \"column\": 1,\n          \"line\": 1,\n          \"offset\": 0,\n        },\n      },\n      \"type\": 2,\n    },\n  ],\n  \"codegenNode\": undefined,\n  \"components\": [],\n  \"directives\": [],\n  \"helpers\": Set {},\n  \"hoists\": [],\n  \"imports\": [],\n  \"loc\": {\n    \"end\": {\n      \"column\": 7,\n      \"line\": 1,\n      \"offset\": 6,\n    },\n    \"source\": \"{{ foo\",\n    \"start\": {\n      \"column\": 1,\n      \"line\": 1,\n      \"offset\": 0,\n    },\n  },\n  \"source\": \"{{ foo\",\n  \"temps\": 0,\n  \"type\": 0,\n}\n`;\n\nexports[`compiler: parse > Errors > X_MISSING_INTERPOLATION_END > {{}} 1`] = `\n{\n  \"cached\": [],\n  \"children\": [\n    {\n      \"content\": {\n        \"constType\": 0,\n        \"content\": \"\",\n        \"isStatic\": false,\n        \"loc\": {\n          \"end\": {\n            \"column\": 3,\n            \"line\": 1,\n            \"offset\": 2,\n          },\n          \"source\": \"\",\n          \"start\": {\n            \"column\": 3,\n            \"line\": 1,\n            \"offset\": 2,\n          },\n        },\n        \"type\": 4,\n      },\n      \"loc\": {\n        \"end\": {\n          \"column\": 5,\n          \"line\": 1,\n          \"offset\": 4,\n        },\n        \"source\": \"{{}}\",\n        \"start\": {\n          \"column\": 1,\n          \"line\": 1,\n          \"offset\": 0,\n        },\n      },\n      \"type\": 5,\n    },\n  ],\n  \"codegenNode\": undefined,\n  \"components\": [],\n  \"directives\": [],\n  \"helpers\": Set {},\n  \"hoists\": [],\n  \"imports\": [],\n  \"loc\": {\n    \"end\": {\n      \"column\": 5,\n      \"line\": 1,\n      \"offset\": 4,\n    },\n    \"source\": \"{{}}\",\n    \"start\": {\n      \"column\": 1,\n      \"line\": 1,\n      \"offset\": 0,\n    },\n  },\n  \"source\": \"{{}}\",\n  \"temps\": 0,\n  \"type\": 0,\n}\n`;\n"
  },
  {
    "path": "packages/compiler-core/__tests__/__snapshots__/scopeId.spec.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`scopeId compiler support > should wrap default slot 1`] = `\n\"import { createElementVNode as _createElementVNode, resolveComponent as _resolveComponent, withCtx as _withCtx, openBlock as _openBlock, createBlock as _createBlock } from \"vue\"\n\nexport function render(_ctx, _cache) {\n  const _component_Child = _resolveComponent(\"Child\")\n\n  return (_openBlock(), _createBlock(_component_Child, null, {\n    default: _withCtx(() => [\n      _createElementVNode(\"div\")\n    ]),\n    _: 1 /* STABLE */\n  }))\n}\"\n`;\n\nexports[`scopeId compiler support > should wrap dynamic slots 1`] = `\n\"import { createElementVNode as _createElementVNode, resolveComponent as _resolveComponent, withCtx as _withCtx, renderList as _renderList, createSlots as _createSlots, openBlock as _openBlock, createBlock as _createBlock } from \"vue\"\n\nexport function render(_ctx, _cache) {\n  const _component_Child = _resolveComponent(\"Child\")\n\n  return (_openBlock(), _createBlock(_component_Child, null, _createSlots({ _: 2 /* DYNAMIC */ }, [\n    (_ctx.ok)\n      ? {\n          name: \"foo\",\n          fn: _withCtx(() => [\n            _createElementVNode(\"div\")\n          ]),\n          key: \"0\"\n        }\n      : undefined,\n    _renderList(_ctx.list, (i) => {\n      return {\n        name: i,\n        fn: _withCtx(() => [\n          _createElementVNode(\"div\")\n        ])\n      }\n    })\n  ]), 1024 /* DYNAMIC_SLOTS */))\n}\"\n`;\n\nexports[`scopeId compiler support > should wrap named slots 1`] = `\n\"import { toDisplayString as _toDisplayString, createTextVNode as _createTextVNode, createElementVNode as _createElementVNode, resolveComponent as _resolveComponent, withCtx as _withCtx, openBlock as _openBlock, createBlock as _createBlock } from \"vue\"\n\nexport function render(_ctx, _cache) {\n  const _component_Child = _resolveComponent(\"Child\")\n\n  return (_openBlock(), _createBlock(_component_Child, null, {\n    foo: _withCtx(({ msg }) => [\n      _createTextVNode(_toDisplayString(msg), 1 /* TEXT */)\n    ]),\n    bar: _withCtx(() => [\n      _createElementVNode(\"div\")\n    ]),\n    _: 1 /* STABLE */\n  }))\n}\"\n`;\n"
  },
  {
    "path": "packages/compiler-core/__tests__/codegen.spec.ts",
    "content": "import {\n  ConstantTypes,\n  type DirectiveArguments,\n  type ForCodegenNode,\n  type IfConditionalExpression,\n  NodeTypes,\n  type RootNode,\n  type VNodeCall,\n  createArrayExpression,\n  createAssignmentExpression,\n  createBlockStatement,\n  createCacheExpression,\n  createCallExpression,\n  createCompoundExpression,\n  createConditionalExpression,\n  createIfStatement,\n  createInterpolation,\n  createObjectExpression,\n  createObjectProperty,\n  createSimpleExpression,\n  createTemplateLiteral,\n  createVNodeCall,\n  generate,\n  locStub,\n} from '../src'\nimport {\n  CREATE_COMMENT,\n  CREATE_ELEMENT_VNODE,\n  CREATE_VNODE,\n  FRAGMENT,\n  RENDER_LIST,\n  RESOLVE_COMPONENT,\n  RESOLVE_DIRECTIVE,\n  TO_DISPLAY_STRING,\n  helperNameMap,\n} from '../src/runtimeHelpers'\nimport { createElementWithCodegen, genFlagText } from './testUtils'\nimport { PatchFlags } from '@vue/shared'\n\nfunction createRoot(options: Partial<RootNode> = {}): RootNode {\n  return {\n    type: NodeTypes.ROOT,\n    source: '',\n    children: [],\n    helpers: new Set(),\n    components: [],\n    directives: [],\n    imports: [],\n    hoists: [],\n    cached: [],\n    temps: 0,\n    codegenNode: createSimpleExpression(`null`, false),\n    loc: locStub,\n    ...options,\n  }\n}\n\ndescribe('compiler: codegen', () => {\n  test('module mode preamble', () => {\n    const root = createRoot({\n      helpers: new Set([CREATE_VNODE, RESOLVE_DIRECTIVE]),\n    })\n    const { code } = generate(root, { mode: 'module' })\n    expect(code).toMatch(\n      `import { ${helperNameMap[CREATE_VNODE]} as _${helperNameMap[CREATE_VNODE]}, ${helperNameMap[RESOLVE_DIRECTIVE]} as _${helperNameMap[RESOLVE_DIRECTIVE]} } from \"vue\"`,\n    )\n    expect(code).toMatchSnapshot()\n  })\n\n  test('module mode preamble w/ optimizeImports: true', () => {\n    const root = createRoot({\n      helpers: new Set([CREATE_VNODE, RESOLVE_DIRECTIVE]),\n    })\n    const { code } = generate(root, { mode: 'module', optimizeImports: true })\n    expect(code).toMatch(\n      `import { ${helperNameMap[CREATE_VNODE]}, ${helperNameMap[RESOLVE_DIRECTIVE]} } from \"vue\"`,\n    )\n    expect(code).toMatch(\n      `const _${helperNameMap[CREATE_VNODE]} = ${helperNameMap[CREATE_VNODE]}, _${helperNameMap[RESOLVE_DIRECTIVE]} = ${helperNameMap[RESOLVE_DIRECTIVE]}`,\n    )\n    expect(code).toMatchSnapshot()\n  })\n\n  test('function mode preamble', () => {\n    const root = createRoot({\n      helpers: new Set([CREATE_VNODE, RESOLVE_DIRECTIVE]),\n    })\n    const { code } = generate(root, { mode: 'function' })\n    expect(code).toMatch(`const _Vue = Vue`)\n    expect(code).toMatch(\n      `const { ${helperNameMap[CREATE_VNODE]}: _${helperNameMap[CREATE_VNODE]}, ${helperNameMap[RESOLVE_DIRECTIVE]}: _${helperNameMap[RESOLVE_DIRECTIVE]} } = _Vue`,\n    )\n    expect(code).toMatchSnapshot()\n  })\n\n  test('function mode preamble w/ prefixIdentifiers: true', () => {\n    const root = createRoot({\n      helpers: new Set([CREATE_VNODE, RESOLVE_DIRECTIVE]),\n    })\n    const { code } = generate(root, {\n      mode: 'function',\n      prefixIdentifiers: true,\n    })\n    expect(code).not.toMatch(`const _Vue = Vue`)\n    expect(code).toMatch(\n      `const { ${helperNameMap[CREATE_VNODE]}: _${helperNameMap[CREATE_VNODE]}, ${helperNameMap[RESOLVE_DIRECTIVE]}: _${helperNameMap[RESOLVE_DIRECTIVE]} } = Vue`,\n    )\n    expect(code).toMatchSnapshot()\n  })\n\n  test('assets + temps', () => {\n    const root = createRoot({\n      components: [`Foo`, `bar-baz`, `barbaz`, `Qux__self`],\n      directives: [`my_dir_0`, `my_dir_1`],\n      temps: 3,\n    })\n    const { code } = generate(root, { mode: 'function' })\n    expect(code).toMatch(\n      `const _component_Foo = _${helperNameMap[RESOLVE_COMPONENT]}(\"Foo\")\\n`,\n    )\n    expect(code).toMatch(\n      `const _component_bar_baz = _${helperNameMap[RESOLVE_COMPONENT]}(\"bar-baz\")\\n`,\n    )\n    expect(code).toMatch(\n      `const _component_barbaz = _${helperNameMap[RESOLVE_COMPONENT]}(\"barbaz\")\\n`,\n    )\n    // implicit self reference from SFC filename\n    expect(code).toMatch(\n      `const _component_Qux = _${helperNameMap[RESOLVE_COMPONENT]}(\"Qux\", true)\\n`,\n    )\n    expect(code).toMatch(\n      `const _directive_my_dir_0 = _${helperNameMap[RESOLVE_DIRECTIVE]}(\"my_dir_0\")\\n`,\n    )\n    expect(code).toMatch(\n      `const _directive_my_dir_1 = _${helperNameMap[RESOLVE_DIRECTIVE]}(\"my_dir_1\")\\n`,\n    )\n    expect(code).toMatch(`let _temp0, _temp1, _temp2`)\n    expect(code).toMatchSnapshot()\n  })\n\n  test('hoists', () => {\n    const root = createRoot({\n      hoists: [\n        createSimpleExpression(`hello`, false, locStub),\n        createObjectExpression(\n          [\n            createObjectProperty(\n              createSimpleExpression(`id`, true, locStub),\n              createSimpleExpression(`foo`, true, locStub),\n            ),\n          ],\n          locStub,\n        ),\n      ],\n    })\n    const { code } = generate(root)\n    expect(code).toMatch(`const _hoisted_1 = hello`)\n    expect(code).toMatch(`const _hoisted_2 = { id: \"foo\" }`)\n    expect(code).toMatchSnapshot()\n  })\n\n  test('temps', () => {\n    const root = createRoot({\n      temps: 3,\n    })\n    const { code } = generate(root)\n    expect(code).toMatch(`let _temp0, _temp1, _temp2`)\n    expect(code).toMatchSnapshot()\n  })\n\n  test('static text', () => {\n    const { code } = generate(\n      createRoot({\n        codegenNode: {\n          type: NodeTypes.TEXT,\n          content: 'hello',\n          loc: locStub,\n        },\n      }),\n    )\n    expect(code).toMatch(`return \"hello\"`)\n    expect(code).toMatchSnapshot()\n  })\n\n  test('interpolation', () => {\n    const { code } = generate(\n      createRoot({\n        codegenNode: createInterpolation(`hello`, locStub),\n      }),\n    )\n    expect(code).toMatch(`return _${helperNameMap[TO_DISPLAY_STRING]}(hello)`)\n    expect(code).toMatchSnapshot()\n  })\n\n  test('comment', () => {\n    const { code } = generate(\n      createRoot({\n        codegenNode: {\n          type: NodeTypes.COMMENT,\n          content: 'foo',\n          loc: locStub,\n        },\n      }),\n    )\n    expect(code).toMatch(`return _${helperNameMap[CREATE_COMMENT]}(\"foo\")`)\n    expect(code).toMatchSnapshot()\n  })\n\n  test('compound expression', () => {\n    const { code } = generate(\n      createRoot({\n        codegenNode: createCompoundExpression([\n          `_ctx.`,\n          createSimpleExpression(`foo`, false, locStub),\n          ` + `,\n          {\n            type: NodeTypes.INTERPOLATION,\n            loc: locStub,\n            content: createSimpleExpression(`bar`, false, locStub),\n          },\n          // nested compound\n          createCompoundExpression([` + `, `nested`]),\n        ]),\n      }),\n    )\n    expect(code).toMatch(\n      `return _ctx.foo + _${helperNameMap[TO_DISPLAY_STRING]}(bar) + nested`,\n    )\n    expect(code).toMatchSnapshot()\n  })\n\n  test('ifNode', () => {\n    const { code } = generate(\n      createRoot({\n        codegenNode: {\n          type: NodeTypes.IF,\n          loc: locStub,\n          branches: [],\n          codegenNode: createConditionalExpression(\n            createSimpleExpression('foo', false),\n            createSimpleExpression('bar', false),\n            createSimpleExpression('baz', false),\n          ) as IfConditionalExpression,\n        },\n      }),\n    )\n    expect(code).toMatch(/return foo\\s+\\? bar\\s+: baz/)\n    expect(code).toMatchSnapshot()\n  })\n\n  test('forNode', () => {\n    const { code } = generate(\n      createRoot({\n        codegenNode: {\n          type: NodeTypes.FOR,\n          loc: locStub,\n          source: createSimpleExpression('foo', false),\n          valueAlias: undefined,\n          keyAlias: undefined,\n          objectIndexAlias: undefined,\n          children: [],\n          parseResult: {} as any,\n          codegenNode: {\n            type: NodeTypes.VNODE_CALL,\n            tag: FRAGMENT,\n            isBlock: true,\n            disableTracking: true,\n            props: undefined,\n            children: createCallExpression(RENDER_LIST),\n            patchFlag: PatchFlags.TEXT,\n            dynamicProps: undefined,\n            directives: undefined,\n            loc: locStub,\n          } as ForCodegenNode,\n        },\n      }),\n    )\n    expect(code).toMatch(`openBlock(true)`)\n    expect(code).toMatchSnapshot()\n  })\n\n  test('forNode with constant expression', () => {\n    const { code } = generate(\n      createRoot({\n        codegenNode: {\n          type: NodeTypes.FOR,\n          loc: locStub,\n          source: createSimpleExpression(\n            '1 + 2',\n            false,\n            locStub,\n            ConstantTypes.CAN_STRINGIFY,\n          ),\n          valueAlias: undefined,\n          keyAlias: undefined,\n          objectIndexAlias: undefined,\n          children: [],\n          parseResult: {} as any,\n          codegenNode: {\n            type: NodeTypes.VNODE_CALL,\n            tag: FRAGMENT,\n            isBlock: true,\n            disableTracking: false,\n            props: undefined,\n            children: createCallExpression(RENDER_LIST),\n            patchFlag: PatchFlags.STABLE_FRAGMENT,\n            dynamicProps: undefined,\n            directives: undefined,\n            loc: locStub,\n          } as ForCodegenNode,\n        },\n      }),\n    )\n    expect(code).toMatch(`openBlock()`)\n    expect(code).toMatchSnapshot()\n  })\n\n  test('Element (callExpression + objectExpression + TemplateChildNode[])', () => {\n    const { code } = generate(\n      createRoot({\n        codegenNode: createElementWithCodegen(\n          // string\n          `\"div\"`,\n          // ObjectExpression\n          createObjectExpression(\n            [\n              createObjectProperty(\n                createSimpleExpression(`id`, true, locStub),\n                createSimpleExpression(`foo`, true, locStub),\n              ),\n              createObjectProperty(\n                createSimpleExpression(`prop`, false, locStub),\n                createSimpleExpression(`bar`, false, locStub),\n              ),\n              // compound expression as computed key\n              createObjectProperty(\n                {\n                  type: NodeTypes.COMPOUND_EXPRESSION,\n                  loc: locStub,\n                  children: [\n                    `foo + `,\n                    createSimpleExpression(`bar`, false, locStub),\n                  ],\n                },\n                createSimpleExpression(`bar`, false, locStub),\n              ),\n            ],\n            locStub,\n          ),\n          // ChildNode[]\n          [\n            createElementWithCodegen(\n              `\"p\"`,\n              createObjectExpression(\n                [\n                  createObjectProperty(\n                    // should quote the key!\n                    createSimpleExpression(`some-key`, true, locStub),\n                    createSimpleExpression(`foo`, true, locStub),\n                  ),\n                ],\n                locStub,\n              ),\n            ),\n          ],\n          // flag\n          PatchFlags.FULL_PROPS,\n        ),\n      }),\n    )\n    expect(code).toMatch(`\n    return _${helperNameMap[CREATE_ELEMENT_VNODE]}(\"div\", {\n      id: \"foo\",\n      [prop]: bar,\n      [foo + bar]: bar\n    }, [\n      _${helperNameMap[CREATE_ELEMENT_VNODE]}(\"p\", { \"some-key\": \"foo\" })\n    ], ${genFlagText(PatchFlags.FULL_PROPS)})`)\n    expect(code).toMatchSnapshot()\n  })\n\n  test('ArrayExpression', () => {\n    const { code } = generate(\n      createRoot({\n        codegenNode: createArrayExpression([\n          createSimpleExpression(`foo`, false),\n          createCallExpression(`bar`, [`baz`]),\n        ]),\n      }),\n    )\n    expect(code).toMatch(`return [\n      foo,\n      bar(baz)\n    ]`)\n    expect(code).toMatchSnapshot()\n  })\n\n  test('ConditionalExpression', () => {\n    const { code } = generate(\n      createRoot({\n        codegenNode: createConditionalExpression(\n          createSimpleExpression(`ok`, false),\n          createCallExpression(`foo`),\n          createConditionalExpression(\n            createSimpleExpression(`orNot`, false),\n            createCallExpression(`bar`),\n            createCallExpression(`baz`),\n          ),\n        ),\n      }),\n    )\n    expect(code).toMatch(\n      `return ok\n      ? foo()\n      : orNot\n        ? bar()\n        : baz()`,\n    )\n    expect(code).toMatchSnapshot()\n  })\n\n  test('CacheExpression', () => {\n    const { code } = generate(\n      createRoot({\n        cached: [],\n        codegenNode: createCacheExpression(\n          1,\n          createSimpleExpression(`foo`, false),\n        ),\n      }),\n      {\n        mode: 'module',\n        prefixIdentifiers: true,\n      },\n    )\n    expect(code).toMatch(`_cache[1] || (_cache[1] = foo)`)\n    expect(code).toMatchSnapshot()\n  })\n\n  test('CacheExpression w/ isVOnce: true', () => {\n    const { code } = generate(\n      createRoot({\n        cached: [],\n        codegenNode: createCacheExpression(\n          1,\n          createSimpleExpression(`foo`, false),\n          true,\n        ),\n      }),\n      {\n        mode: 'module',\n        prefixIdentifiers: true,\n      },\n    )\n    expect(code).toMatch(\n      `\n  _cache[1] || (\n    _setBlockTracking(-1),\n    (_cache[1] = foo).cacheIndex = 1,\n    _setBlockTracking(1),\n    _cache[1]\n  )\n    `.trim(),\n    )\n    expect(code).toMatchSnapshot()\n  })\n\n  test('TemplateLiteral', () => {\n    const { code } = generate(\n      createRoot({\n        codegenNode: createCallExpression(`_push`, [\n          createTemplateLiteral([\n            `foo`,\n            createCallExpression(`_renderAttr`, ['id', 'foo']),\n            `bar`,\n          ]),\n        ]),\n      }),\n      { ssr: true, mode: 'module' },\n    )\n    expect(code).toMatchInlineSnapshot(`\n      \"\n      export function ssrRender(_ctx, _push, _parent, _attrs) {\n        _push(\\`foo\\${_renderAttr(id, foo)}bar\\`)\n      }\"\n    `)\n  })\n\n  describe('IfStatement', () => {\n    test('if', () => {\n      const { code } = generate(\n        createRoot({\n          codegenNode: createBlockStatement([\n            createIfStatement(\n              createSimpleExpression('foo', false),\n              createBlockStatement([createCallExpression(`ok`)]),\n            ),\n          ]),\n        }),\n        { ssr: true, mode: 'module' },\n      )\n      expect(code).toMatchInlineSnapshot(`\n        \"\n        export function ssrRender(_ctx, _push, _parent, _attrs) {\n          if (foo) {\n            ok()\n          }\n        }\"\n      `)\n    })\n\n    test('if/else', () => {\n      const { code } = generate(\n        createRoot({\n          codegenNode: createBlockStatement([\n            createIfStatement(\n              createSimpleExpression('foo', false),\n              createBlockStatement([createCallExpression(`foo`)]),\n              createBlockStatement([createCallExpression('bar')]),\n            ),\n          ]),\n        }),\n        { ssr: true, mode: 'module' },\n      )\n      expect(code).toMatchInlineSnapshot(`\n        \"\n        export function ssrRender(_ctx, _push, _parent, _attrs) {\n          if (foo) {\n            foo()\n          } else {\n            bar()\n          }\n        }\"\n      `)\n    })\n\n    test('if/else-if', () => {\n      const { code } = generate(\n        createRoot({\n          codegenNode: createBlockStatement([\n            createIfStatement(\n              createSimpleExpression('foo', false),\n              createBlockStatement([createCallExpression(`foo`)]),\n              createIfStatement(\n                createSimpleExpression('bar', false),\n                createBlockStatement([createCallExpression(`bar`)]),\n              ),\n            ),\n          ]),\n        }),\n        { ssr: true, mode: 'module' },\n      )\n      expect(code).toMatchInlineSnapshot(`\n        \"\n        export function ssrRender(_ctx, _push, _parent, _attrs) {\n          if (foo) {\n            foo()\n          } else if (bar) {\n            bar()\n          }\n        }\"\n      `)\n    })\n\n    test('if/else-if/else', () => {\n      const { code } = generate(\n        createRoot({\n          codegenNode: createBlockStatement([\n            createIfStatement(\n              createSimpleExpression('foo', false),\n              createBlockStatement([createCallExpression(`foo`)]),\n              createIfStatement(\n                createSimpleExpression('bar', false),\n                createBlockStatement([createCallExpression(`bar`)]),\n                createBlockStatement([createCallExpression('baz')]),\n              ),\n            ),\n          ]),\n        }),\n        { ssr: true, mode: 'module' },\n      )\n      expect(code).toMatchInlineSnapshot(`\n        \"\n        export function ssrRender(_ctx, _push, _parent, _attrs) {\n          if (foo) {\n            foo()\n          } else if (bar) {\n            bar()\n          } else {\n            baz()\n          }\n        }\"\n      `)\n    })\n  })\n\n  test('AssignmentExpression', () => {\n    const { code } = generate(\n      createRoot({\n        codegenNode: createAssignmentExpression(\n          createSimpleExpression(`foo`, false),\n          createSimpleExpression(`bar`, false),\n        ),\n      }),\n    )\n    expect(code).toMatchInlineSnapshot(`\n      \"\n      return function render(_ctx, _cache) {\n        with (_ctx) {\n          return foo = bar\n        }\n      }\"\n    `)\n  })\n\n  describe('VNodeCall', () => {\n    function genCode(node: VNodeCall) {\n      return generate(\n        createRoot({\n          codegenNode: node,\n        }),\n      ).code.match(/with \\(_ctx\\) \\{\\s+([^]+)\\s+\\}\\s+\\}$/)![1]\n    }\n\n    const mockProps = createObjectExpression([\n      createObjectProperty(`foo`, createSimpleExpression(`bar`, true)),\n    ])\n    const mockChildren = createCompoundExpression(['children'])\n    const mockDirs = createArrayExpression([\n      createArrayExpression([`foo`, createSimpleExpression(`bar`, false)]),\n    ]) as DirectiveArguments\n\n    test('tag only', () => {\n      expect(genCode(createVNodeCall(null, `\"div\"`))).toMatchInlineSnapshot(`\n        \"return _createElementVNode(\"div\")\n         \"\n      `)\n      expect(genCode(createVNodeCall(null, FRAGMENT))).toMatchInlineSnapshot(`\n              \"return _createElementVNode(_Fragment)\n               \"\n          `)\n    })\n\n    test('with props', () => {\n      expect(genCode(createVNodeCall(null, `\"div\"`, mockProps)))\n        .toMatchInlineSnapshot(`\n          \"return _createElementVNode(\"div\", { foo: \"bar\" })\n           \"\n        `)\n    })\n\n    test('with children, no props', () => {\n      expect(genCode(createVNodeCall(null, `\"div\"`, undefined, mockChildren)))\n        .toMatchInlineSnapshot(`\n          \"return _createElementVNode(\"div\", null, children)\n           \"\n        `)\n    })\n\n    test('with children + props', () => {\n      expect(genCode(createVNodeCall(null, `\"div\"`, mockProps, mockChildren)))\n        .toMatchInlineSnapshot(`\n          \"return _createElementVNode(\"div\", { foo: \"bar\" }, children)\n           \"\n        `)\n    })\n\n    test('with patchFlag and no children/props', () => {\n      expect(\n        genCode(\n          createVNodeCall(null, `\"div\"`, undefined, undefined, PatchFlags.TEXT),\n        ),\n      ).toMatchInlineSnapshot(`\n        \"return _createElementVNode(\"div\", null, null, 1 /* TEXT */)\n         \"\n      `)\n    })\n\n    test('as block', () => {\n      expect(\n        genCode(\n          createVNodeCall(\n            null,\n            `\"div\"`,\n            mockProps,\n            mockChildren,\n            undefined,\n            undefined,\n            undefined,\n            true,\n          ),\n        ),\n      ).toMatchInlineSnapshot(`\n        \"return (_openBlock(), _createElementBlock(\"div\", { foo: \"bar\" }, children))\n         \"\n      `)\n    })\n\n    test('as for block', () => {\n      expect(\n        genCode(\n          createVNodeCall(\n            null,\n            `\"div\"`,\n            mockProps,\n            mockChildren,\n            undefined,\n            undefined,\n            undefined,\n            true,\n            true,\n          ),\n        ),\n      ).toMatchInlineSnapshot(`\n        \"return (_openBlock(true), _createElementBlock(\"div\", { foo: \"bar\" }, children))\n         \"\n      `)\n    })\n\n    test('with directives', () => {\n      expect(\n        genCode(\n          createVNodeCall(\n            null,\n            `\"div\"`,\n            mockProps,\n            mockChildren,\n            undefined,\n            undefined,\n            mockDirs,\n          ),\n        ),\n      ).toMatchInlineSnapshot(`\n        \"return _withDirectives(_createElementVNode(\"div\", { foo: \"bar\" }, children), [\n              [foo, bar]\n            ])\n         \"\n      `)\n    })\n\n    test('block + directives', () => {\n      expect(\n        genCode(\n          createVNodeCall(\n            null,\n            `\"div\"`,\n            mockProps,\n            mockChildren,\n            undefined,\n            undefined,\n            mockDirs,\n            true,\n          ),\n        ),\n      ).toMatchInlineSnapshot(`\n        \"return _withDirectives((_openBlock(), _createElementBlock(\"div\", { foo: \"bar\" }, children)), [\n              [foo, bar]\n            ])\n         \"\n      `)\n    })\n  })\n})\n"
  },
  {
    "path": "packages/compiler-core/__tests__/compile.spec.ts",
    "content": "import { baseCompile as compile } from '../src'\nimport { type RawSourceMap, SourceMapConsumer } from 'source-map-js'\n\ndescribe('compiler: integration tests', () => {\n  const source = `\n<div id=\"foo\" :class=\"bar.baz\">\n  {{ world.burn() }}\n  <div v-if=\"ok\">yes</div>\n  <template v-else>no</template>\n  <div v-for=\"(value, index) in list\"><span>{{ value + index }}</span></div>\n</div>\n`.trim()\n\n  interface Pos {\n    line: number\n    column: number\n    name?: string\n  }\n\n  function getPositionInCode(\n    code: string,\n    token: string,\n    expectName: string | boolean = false,\n  ): Pos {\n    const generatedOffset = code.indexOf(token)\n    let line = 1\n    let lastNewLinePos = -1\n    for (let i = 0; i < generatedOffset; i++) {\n      if (code.charCodeAt(i) === 10 /* newline char code */) {\n        line++\n        lastNewLinePos = i\n      }\n    }\n    const res: Pos = {\n      line,\n      column:\n        lastNewLinePos === -1\n          ? generatedOffset\n          : generatedOffset - lastNewLinePos - 1,\n    }\n    if (expectName) {\n      res.name = typeof expectName === 'string' ? expectName : token\n    }\n    return res\n  }\n\n  test('function mode', () => {\n    const { code, map } = compile(source, {\n      sourceMap: true,\n      filename: `foo.vue`,\n    })\n\n    expect(code).toMatchSnapshot()\n    expect(map!.sources).toEqual([`foo.vue`])\n    expect(map!.sourcesContent).toEqual([source])\n\n    const consumer = new SourceMapConsumer(map as RawSourceMap)\n\n    expect(\n      consumer.originalPositionFor(getPositionInCode(code, `id`)),\n    ).toMatchObject(getPositionInCode(source, `id`))\n\n    expect(\n      consumer.originalPositionFor(getPositionInCode(code, `\"foo\"`)),\n    ).toMatchObject(getPositionInCode(source, `\"foo\"`))\n\n    expect(\n      consumer.originalPositionFor(getPositionInCode(code, `class:`)),\n    ).toMatchObject(getPositionInCode(source, `class=`))\n\n    expect(\n      consumer.originalPositionFor(getPositionInCode(code, `bar`)),\n    ).toMatchObject(getPositionInCode(source, `bar`))\n\n    // without prefixIdentifiers: true, identifiers inside compound expressions\n    // are mapped to closest parent expression.\n    expect(\n      consumer.originalPositionFor(getPositionInCode(code, `baz`)),\n    ).toMatchObject(getPositionInCode(source, `bar`))\n\n    expect(\n      consumer.originalPositionFor(getPositionInCode(code, `world`)),\n    ).toMatchObject(getPositionInCode(source, `world`))\n\n    // without prefixIdentifiers: true, identifiers inside compound expressions\n    // are mapped to closest parent expression.\n    expect(\n      consumer.originalPositionFor(getPositionInCode(code, `burn()`)),\n    ).toMatchObject(getPositionInCode(source, `world`))\n\n    expect(\n      consumer.originalPositionFor(getPositionInCode(code, `ok`)),\n    ).toMatchObject(getPositionInCode(source, `ok`))\n\n    expect(\n      consumer.originalPositionFor(getPositionInCode(code, `list`)),\n    ).toMatchObject(getPositionInCode(source, `list`))\n\n    expect(\n      consumer.originalPositionFor(getPositionInCode(code, `value`)),\n    ).toMatchObject(getPositionInCode(source, `value`))\n\n    expect(\n      consumer.originalPositionFor(getPositionInCode(code, `index`)),\n    ).toMatchObject(getPositionInCode(source, `index`))\n\n    expect(\n      consumer.originalPositionFor(getPositionInCode(code, `value + index`)),\n    ).toMatchObject(getPositionInCode(source, `value + index`))\n  })\n\n  test('function mode w/ prefixIdentifiers: true', () => {\n    const { code, map } = compile(source, {\n      sourceMap: true,\n      filename: `foo.vue`,\n      prefixIdentifiers: true,\n    })\n\n    expect(code).toMatchSnapshot()\n    expect(map!.sources).toEqual([`foo.vue`])\n    expect(map!.sourcesContent).toEqual([source])\n\n    const consumer = new SourceMapConsumer(map as RawSourceMap)\n\n    expect(\n      consumer.originalPositionFor(getPositionInCode(code, `id`)),\n    ).toMatchObject(getPositionInCode(source, `id`))\n\n    expect(\n      consumer.originalPositionFor(getPositionInCode(code, `\"foo\"`)),\n    ).toMatchObject(getPositionInCode(source, `\"foo\"`))\n\n    expect(\n      consumer.originalPositionFor(getPositionInCode(code, `class:`)),\n    ).toMatchObject(getPositionInCode(source, `class=`))\n\n    expect(\n      consumer.originalPositionFor(getPositionInCode(code, `bar`)),\n    ).toMatchObject(getPositionInCode(source, `bar`))\n    expect(\n      consumer.originalPositionFor(getPositionInCode(code, `_ctx.bar`, `bar`)),\n    ).toMatchObject(getPositionInCode(source, `bar`, true))\n    expect(\n      consumer.originalPositionFor(getPositionInCode(code, `baz`)),\n    ).toMatchObject(getPositionInCode(source, `baz`))\n\n    expect(\n      consumer.originalPositionFor(getPositionInCode(code, `world`, true)),\n    ).toMatchObject(getPositionInCode(source, `world`, `world`))\n    expect(\n      consumer.originalPositionFor(\n        getPositionInCode(code, `_ctx.world`, `world`),\n      ),\n    ).toMatchObject(getPositionInCode(source, `world`, `world`))\n\n    expect(\n      consumer.originalPositionFor(getPositionInCode(code, `burn()`)),\n    ).toMatchObject(getPositionInCode(source, `burn()`))\n\n    expect(\n      consumer.originalPositionFor(getPositionInCode(code, `ok`)),\n    ).toMatchObject(getPositionInCode(source, `ok`))\n    expect(\n      consumer.originalPositionFor(getPositionInCode(code, `_ctx.ok`, `ok`)),\n    ).toMatchObject(getPositionInCode(source, `ok`, true))\n\n    expect(\n      consumer.originalPositionFor(getPositionInCode(code, `list`)),\n    ).toMatchObject(getPositionInCode(source, `list`))\n    expect(\n      consumer.originalPositionFor(\n        getPositionInCode(code, `_ctx.list`, `list`),\n      ),\n    ).toMatchObject(getPositionInCode(source, `list`, true))\n\n    expect(\n      consumer.originalPositionFor(getPositionInCode(code, `value`)),\n    ).toMatchObject(getPositionInCode(source, `value`))\n\n    expect(\n      consumer.originalPositionFor(getPositionInCode(code, `index`)),\n    ).toMatchObject(getPositionInCode(source, `index`))\n\n    expect(\n      consumer.originalPositionFor(getPositionInCode(code, `value + index`)),\n    ).toMatchObject(getPositionInCode(source, `value + index`))\n  })\n\n  test('module mode', () => {\n    const { code, map } = compile(source, {\n      mode: 'module',\n      sourceMap: true,\n      filename: `foo.vue`,\n    })\n\n    expect(code).toMatchSnapshot()\n    expect(map!.sources).toEqual([`foo.vue`])\n    expect(map!.sourcesContent).toEqual([source])\n\n    const consumer = new SourceMapConsumer(map as RawSourceMap)\n\n    expect(\n      consumer.originalPositionFor(getPositionInCode(code, `id`)),\n    ).toMatchObject(getPositionInCode(source, `id`))\n\n    expect(\n      consumer.originalPositionFor(getPositionInCode(code, `\"foo\"`)),\n    ).toMatchObject(getPositionInCode(source, `\"foo\"`))\n\n    expect(\n      consumer.originalPositionFor(getPositionInCode(code, `class:`)),\n    ).toMatchObject(getPositionInCode(source, `class=`))\n\n    expect(\n      consumer.originalPositionFor(getPositionInCode(code, `bar`)),\n    ).toMatchObject(getPositionInCode(source, `bar`))\n    expect(\n      consumer.originalPositionFor(getPositionInCode(code, `_ctx.bar`, `bar`)),\n    ).toMatchObject(getPositionInCode(source, `bar`, true))\n    expect(\n      consumer.originalPositionFor(getPositionInCode(code, `baz`)),\n    ).toMatchObject(getPositionInCode(source, `baz`))\n\n    expect(\n      consumer.originalPositionFor(getPositionInCode(code, `world`, true)),\n    ).toMatchObject(getPositionInCode(source, `world`, `world`))\n    expect(\n      consumer.originalPositionFor(\n        getPositionInCode(code, `_ctx.world`, `world`),\n      ),\n    ).toMatchObject(getPositionInCode(source, `world`, `world`))\n\n    expect(\n      consumer.originalPositionFor(getPositionInCode(code, `burn()`)),\n    ).toMatchObject(getPositionInCode(source, `burn()`))\n\n    expect(\n      consumer.originalPositionFor(getPositionInCode(code, `ok`)),\n    ).toMatchObject(getPositionInCode(source, `ok`))\n    expect(\n      consumer.originalPositionFor(getPositionInCode(code, `_ctx.ok`, `ok`)),\n    ).toMatchObject(getPositionInCode(source, `ok`, true))\n\n    expect(\n      consumer.originalPositionFor(getPositionInCode(code, `list`)),\n    ).toMatchObject(getPositionInCode(source, `list`))\n    expect(\n      consumer.originalPositionFor(\n        getPositionInCode(code, `_ctx.list`, `list`),\n      ),\n    ).toMatchObject(getPositionInCode(source, `list`, true))\n\n    expect(\n      consumer.originalPositionFor(getPositionInCode(code, `value`)),\n    ).toMatchObject(getPositionInCode(source, `value`))\n\n    expect(\n      consumer.originalPositionFor(getPositionInCode(code, `index`)),\n    ).toMatchObject(getPositionInCode(source, `index`))\n\n    expect(\n      consumer.originalPositionFor(getPositionInCode(code, `value + index`)),\n    ).toMatchObject(getPositionInCode(source, `value + index`))\n  })\n})\n"
  },
  {
    "path": "packages/compiler-core/__tests__/parse.spec.ts",
    "content": "import type { ParserOptions } from '../src/options'\nimport { ErrorCodes } from '../src/errors'\nimport {\n  type CommentNode,\n  ConstantTypes,\n  type DirectiveNode,\n  type ElementNode,\n  ElementTypes,\n  type InterpolationNode,\n  Namespaces,\n  NodeTypes,\n  type Position,\n  type TextNode,\n} from '../src/ast'\n\nimport { baseParse } from '../src/parser'\nimport type { Program } from '@babel/types'\n\ndescribe('compiler: parse', () => {\n  describe('Text', () => {\n    test('simple text', () => {\n      const ast = baseParse('some text')\n      const text = ast.children[0] as TextNode\n\n      expect(text).toStrictEqual({\n        type: NodeTypes.TEXT,\n        content: 'some text',\n        loc: {\n          start: { offset: 0, line: 1, column: 1 },\n          end: { offset: 9, line: 1, column: 10 },\n          source: 'some text',\n        },\n      })\n    })\n\n    test('simple text with invalid end tag', () => {\n      const onError = vi.fn()\n      const ast = baseParse('some text</div>', { onError })\n      const text = ast.children[0] as TextNode\n\n      expect(onError.mock.calls).toMatchObject([\n        [\n          {\n            code: ErrorCodes.X_INVALID_END_TAG,\n            loc: {\n              start: { column: 10, line: 1, offset: 9 },\n              end: { column: 10, line: 1, offset: 9 },\n            },\n          },\n        ],\n      ])\n\n      expect(text).toStrictEqual({\n        type: NodeTypes.TEXT,\n        content: 'some text',\n        loc: {\n          start: { offset: 0, line: 1, column: 1 },\n          end: { offset: 9, line: 1, column: 10 },\n          source: 'some text',\n        },\n      })\n    })\n\n    test('text with interpolation', () => {\n      const ast = baseParse('some {{ foo + bar }} text')\n      const text1 = ast.children[0] as TextNode\n      const text2 = ast.children[2] as TextNode\n\n      expect(text1).toStrictEqual({\n        type: NodeTypes.TEXT,\n        content: 'some ',\n        loc: {\n          start: { offset: 0, line: 1, column: 1 },\n          end: { offset: 5, line: 1, column: 6 },\n          source: 'some ',\n        },\n      })\n      expect(text2).toStrictEqual({\n        type: NodeTypes.TEXT,\n        content: ' text',\n        loc: {\n          start: { offset: 20, line: 1, column: 21 },\n          end: { offset: 25, line: 1, column: 26 },\n          source: ' text',\n        },\n      })\n    })\n\n    test('text with interpolation which has `<`', () => {\n      const ast = baseParse('some {{ a<b && c>d }} text')\n      const text1 = ast.children[0] as TextNode\n      const text2 = ast.children[2] as TextNode\n\n      expect(text1).toStrictEqual({\n        type: NodeTypes.TEXT,\n        content: 'some ',\n        loc: {\n          start: { offset: 0, line: 1, column: 1 },\n          end: { offset: 5, line: 1, column: 6 },\n          source: 'some ',\n        },\n      })\n      expect(text2).toStrictEqual({\n        type: NodeTypes.TEXT,\n        content: ' text',\n        loc: {\n          start: { offset: 21, line: 1, column: 22 },\n          end: { offset: 26, line: 1, column: 27 },\n          source: ' text',\n        },\n      })\n    })\n\n    test('text with mix of tags and interpolations', () => {\n      const ast = baseParse('some <span>{{ foo < bar + foo }} text</span>')\n      const text1 = ast.children[0] as TextNode\n      const text2 = (ast.children[1] as ElementNode).children![1] as TextNode\n\n      expect(text1).toStrictEqual({\n        type: NodeTypes.TEXT,\n        content: 'some ',\n        loc: {\n          start: { offset: 0, line: 1, column: 1 },\n          end: { offset: 5, line: 1, column: 6 },\n          source: 'some ',\n        },\n      })\n      expect(text2).toStrictEqual({\n        type: NodeTypes.TEXT,\n        content: ' text',\n        loc: {\n          start: { offset: 32, line: 1, column: 33 },\n          end: { offset: 37, line: 1, column: 38 },\n          source: ' text',\n        },\n      })\n    })\n\n    test('lonely \"<\" doesn\\'t separate nodes', () => {\n      const ast = baseParse('a < b', {\n        onError: err => {\n          if (err.code !== ErrorCodes.INVALID_FIRST_CHARACTER_OF_TAG_NAME) {\n            throw err\n          }\n        },\n      })\n      const text = ast.children[0] as TextNode\n\n      expect(text).toStrictEqual({\n        type: NodeTypes.TEXT,\n        content: 'a < b',\n        loc: {\n          start: { offset: 0, line: 1, column: 1 },\n          end: { offset: 5, line: 1, column: 6 },\n          source: 'a < b',\n        },\n      })\n    })\n\n    test('lonely \"{{\" doesn\\'t separate nodes', () => {\n      const ast = baseParse('a {{ b', {\n        onError: error => {\n          if (error.code !== ErrorCodes.X_MISSING_INTERPOLATION_END) {\n            throw error\n          }\n        },\n      })\n      const text = ast.children[0] as TextNode\n\n      expect(text).toStrictEqual({\n        type: NodeTypes.TEXT,\n        content: 'a {{ b',\n        loc: {\n          start: { offset: 0, line: 1, column: 1 },\n          end: { offset: 6, line: 1, column: 7 },\n          source: 'a {{ b',\n        },\n      })\n    })\n  })\n\n  describe('Interpolation', () => {\n    test('simple interpolation', () => {\n      const ast = baseParse('{{message}}')\n      const interpolation = ast.children[0] as InterpolationNode\n\n      expect(interpolation).toStrictEqual({\n        type: NodeTypes.INTERPOLATION,\n        content: {\n          type: NodeTypes.SIMPLE_EXPRESSION,\n          content: `message`,\n          isStatic: false,\n          constType: ConstantTypes.NOT_CONSTANT,\n          loc: {\n            start: { offset: 2, line: 1, column: 3 },\n            end: { offset: 9, line: 1, column: 10 },\n            source: 'message',\n          },\n        },\n        loc: {\n          start: { offset: 0, line: 1, column: 1 },\n          end: { offset: 11, line: 1, column: 12 },\n          source: '{{message}}',\n        },\n      })\n    })\n\n    test('it can have tag-like notation', () => {\n      const ast = baseParse('{{ a<b }}')\n      const interpolation = ast.children[0] as InterpolationNode\n\n      expect(interpolation).toStrictEqual({\n        type: NodeTypes.INTERPOLATION,\n        content: {\n          type: NodeTypes.SIMPLE_EXPRESSION,\n          content: `a<b`,\n          isStatic: false,\n          constType: ConstantTypes.NOT_CONSTANT,\n          loc: {\n            start: { offset: 3, line: 1, column: 4 },\n            end: { offset: 6, line: 1, column: 7 },\n            source: 'a<b',\n          },\n        },\n        loc: {\n          start: { offset: 0, line: 1, column: 1 },\n          end: { offset: 9, line: 1, column: 10 },\n          source: '{{ a<b }}',\n        },\n      })\n    })\n\n    test('it can have tag-like notation (2)', () => {\n      const ast = baseParse('{{ a<b }}{{ c>d }}')\n      const interpolation1 = ast.children[0] as InterpolationNode\n      const interpolation2 = ast.children[1] as InterpolationNode\n\n      expect(interpolation1).toStrictEqual({\n        type: NodeTypes.INTERPOLATION,\n        content: {\n          type: NodeTypes.SIMPLE_EXPRESSION,\n          content: `a<b`,\n          isStatic: false,\n          constType: ConstantTypes.NOT_CONSTANT,\n          loc: {\n            start: { offset: 3, line: 1, column: 4 },\n            end: { offset: 6, line: 1, column: 7 },\n            source: 'a<b',\n          },\n        },\n        loc: {\n          start: { offset: 0, line: 1, column: 1 },\n          end: { offset: 9, line: 1, column: 10 },\n          source: '{{ a<b }}',\n        },\n      })\n\n      expect(interpolation2).toStrictEqual({\n        type: NodeTypes.INTERPOLATION,\n        content: {\n          type: NodeTypes.SIMPLE_EXPRESSION,\n          isStatic: false,\n          constType: ConstantTypes.NOT_CONSTANT,\n          content: 'c>d',\n          loc: {\n            start: { offset: 12, line: 1, column: 13 },\n            end: { offset: 15, line: 1, column: 16 },\n            source: 'c>d',\n          },\n        },\n        loc: {\n          start: { offset: 9, line: 1, column: 10 },\n          end: { offset: 18, line: 1, column: 19 },\n          source: '{{ c>d }}',\n        },\n      })\n    })\n\n    test('it can have tag-like notation (3)', () => {\n      const ast = baseParse('<div>{{ \"</div>\" }}</div>')\n      const element = ast.children[0] as ElementNode\n      const interpolation = element.children[0] as InterpolationNode\n\n      expect(interpolation).toStrictEqual({\n        type: NodeTypes.INTERPOLATION,\n        content: {\n          type: NodeTypes.SIMPLE_EXPRESSION,\n          isStatic: false,\n          // The `constType` is the default value and will be determined in `transformExpression`.\n          constType: ConstantTypes.NOT_CONSTANT,\n          content: '\"</div>\"',\n          loc: {\n            start: { offset: 8, line: 1, column: 9 },\n            end: { offset: 16, line: 1, column: 17 },\n            source: '\"</div>\"',\n          },\n        },\n        loc: {\n          start: { offset: 5, line: 1, column: 6 },\n          end: { offset: 19, line: 1, column: 20 },\n          source: '{{ \"</div>\" }}',\n        },\n      })\n    })\n\n    test('custom delimiters', () => {\n      const ast = baseParse('<p>{msg}</p>', {\n        delimiters: ['{', '}'],\n      })\n      const element = ast.children[0] as ElementNode\n      const interpolation = element.children[0] as InterpolationNode\n\n      expect(interpolation).toStrictEqual({\n        type: NodeTypes.INTERPOLATION,\n        content: {\n          type: NodeTypes.SIMPLE_EXPRESSION,\n          content: `msg`,\n          isStatic: false,\n          constType: ConstantTypes.NOT_CONSTANT,\n          loc: {\n            start: { offset: 4, line: 1, column: 5 },\n            end: { offset: 7, line: 1, column: 8 },\n            source: 'msg',\n          },\n        },\n        loc: {\n          start: { offset: 3, line: 1, column: 4 },\n          end: { offset: 8, line: 1, column: 9 },\n          source: '{msg}',\n        },\n      })\n    })\n  })\n\n  describe('Comment', () => {\n    test('empty comment', () => {\n      const ast = baseParse('<!---->')\n      const comment = ast.children[0] as CommentNode\n\n      expect(comment).toStrictEqual({\n        type: NodeTypes.COMMENT,\n        content: '',\n        loc: {\n          start: { offset: 0, line: 1, column: 1 },\n          end: { offset: 7, line: 1, column: 8 },\n          source: '<!---->',\n        },\n      })\n    })\n\n    test('simple comment', () => {\n      const ast = baseParse('<!--abc-->')\n      const comment = ast.children[0] as CommentNode\n\n      expect(comment).toStrictEqual({\n        type: NodeTypes.COMMENT,\n        content: 'abc',\n        loc: {\n          start: { offset: 0, line: 1, column: 1 },\n          end: { offset: 10, line: 1, column: 11 },\n          source: '<!--abc-->',\n        },\n      })\n    })\n\n    test('two comments', () => {\n      const ast = baseParse('<!--abc--><!--def-->')\n      const comment1 = ast.children[0] as CommentNode\n      const comment2 = ast.children[1] as CommentNode\n\n      expect(comment1).toStrictEqual({\n        type: NodeTypes.COMMENT,\n        content: 'abc',\n        loc: {\n          start: { offset: 0, line: 1, column: 1 },\n          end: { offset: 10, line: 1, column: 11 },\n          source: '<!--abc-->',\n        },\n      })\n      expect(comment2).toStrictEqual({\n        type: NodeTypes.COMMENT,\n        content: 'def',\n        loc: {\n          start: { offset: 10, line: 1, column: 11 },\n          end: { offset: 20, line: 1, column: 21 },\n          source: '<!--def-->',\n        },\n      })\n    })\n\n    test('comments option', () => {\n      const astOptionNoComment = baseParse('<!--abc-->', { comments: false })\n      const astOptionWithComments = baseParse('<!--abc-->', { comments: true })\n\n      expect(astOptionNoComment.children).toHaveLength(0)\n      expect(astOptionWithComments.children).toHaveLength(1)\n    })\n\n    // #2217\n    test('comments in the <pre> tag should be removed when comments option requires it', () => {\n      const rawText = `<p/><!-- foo --><p/>`\n\n      const astWithComments = baseParse(`<pre>${rawText}</pre>`, {\n        comments: true,\n      })\n      expect(\n        (astWithComments.children[0] as ElementNode).children,\n      ).toMatchObject([\n        {\n          type: NodeTypes.ELEMENT,\n          tag: 'p',\n        },\n        {\n          type: NodeTypes.COMMENT,\n        },\n        {\n          type: NodeTypes.ELEMENT,\n          tag: 'p',\n        },\n      ])\n\n      const astWithoutComments = baseParse(`<pre>${rawText}</pre>`, {\n        comments: false,\n      })\n      expect(\n        (astWithoutComments.children[0] as ElementNode).children,\n      ).toMatchObject([\n        {\n          type: NodeTypes.ELEMENT,\n          tag: 'p',\n        },\n        {\n          type: NodeTypes.ELEMENT,\n          tag: 'p',\n        },\n      ])\n    })\n  })\n\n  describe('Element', () => {\n    test('simple div', () => {\n      const ast = baseParse('<div>hello</div>')\n      const element = ast.children[0] as ElementNode\n\n      expect(element).toStrictEqual({\n        type: NodeTypes.ELEMENT,\n        ns: Namespaces.HTML,\n        tag: 'div',\n        tagType: ElementTypes.ELEMENT,\n        codegenNode: undefined,\n        props: [],\n        children: [\n          {\n            type: NodeTypes.TEXT,\n            content: 'hello',\n            loc: {\n              start: { offset: 5, line: 1, column: 6 },\n              end: { offset: 10, line: 1, column: 11 },\n              source: 'hello',\n            },\n          },\n        ],\n        loc: {\n          start: { offset: 0, line: 1, column: 1 },\n          end: { offset: 16, line: 1, column: 17 },\n          source: '<div>hello</div>',\n        },\n      })\n    })\n\n    test('empty', () => {\n      const ast = baseParse('<div></div>')\n      const element = ast.children[0] as ElementNode\n\n      expect(element).toStrictEqual({\n        type: NodeTypes.ELEMENT,\n        ns: Namespaces.HTML,\n        tag: 'div',\n        tagType: ElementTypes.ELEMENT,\n        codegenNode: undefined,\n        props: [],\n        children: [],\n        loc: {\n          start: { offset: 0, line: 1, column: 1 },\n          end: { offset: 11, line: 1, column: 12 },\n          source: '<div></div>',\n        },\n      })\n    })\n\n    test('self closing', () => {\n      const ast = baseParse('<div/>after')\n      const element = ast.children[0] as ElementNode\n\n      expect(element).toStrictEqual({\n        type: NodeTypes.ELEMENT,\n        ns: Namespaces.HTML,\n        tag: 'div',\n        tagType: ElementTypes.ELEMENT,\n        codegenNode: undefined,\n        props: [],\n        children: [],\n        isSelfClosing: true,\n        loc: {\n          start: { offset: 0, line: 1, column: 1 },\n          end: { offset: 6, line: 1, column: 7 },\n          source: '<div/>',\n        },\n      })\n    })\n\n    test('void element', () => {\n      const ast = baseParse('<img>after', {\n        isVoidTag: tag => tag === 'img',\n      })\n      const element = ast.children[0] as ElementNode\n\n      expect(element).toStrictEqual({\n        type: NodeTypes.ELEMENT,\n        ns: Namespaces.HTML,\n        tag: 'img',\n        tagType: ElementTypes.ELEMENT,\n        codegenNode: undefined,\n        props: [],\n        children: [],\n        loc: {\n          start: { offset: 0, line: 1, column: 1 },\n          end: { offset: 5, line: 1, column: 6 },\n          source: '<img>',\n        },\n      })\n    })\n\n    test('self-closing void element', () => {\n      const ast = baseParse('<img/>after', {\n        isVoidTag: tag => tag === 'img',\n      })\n      const element = ast.children[0] as ElementNode\n\n      expect(element).toStrictEqual({\n        type: NodeTypes.ELEMENT,\n        ns: Namespaces.HTML,\n        tag: 'img',\n        tagType: ElementTypes.ELEMENT,\n        codegenNode: undefined,\n        props: [],\n        children: [],\n        isSelfClosing: true,\n        loc: {\n          start: { offset: 0, line: 1, column: 1 },\n          end: { offset: 6, line: 1, column: 7 },\n          source: '<img/>',\n        },\n      })\n    })\n\n    test('template element with directives', () => {\n      const ast = baseParse('<template v-if=\"ok\"></template>')\n      const element = ast.children[0]\n      expect(element).toMatchObject({\n        type: NodeTypes.ELEMENT,\n        tagType: ElementTypes.TEMPLATE,\n      })\n    })\n\n    test('template element without directives', () => {\n      const ast = baseParse('<template></template>')\n      const element = ast.children[0]\n      expect(element).toMatchObject({\n        type: NodeTypes.ELEMENT,\n        tagType: ElementTypes.ELEMENT,\n      })\n    })\n\n    test('native element with `isNativeTag`', () => {\n      const ast = baseParse('<div></div><comp></comp><Comp></Comp>', {\n        isNativeTag: tag => tag === 'div',\n      })\n\n      expect(ast.children[0]).toMatchObject({\n        type: NodeTypes.ELEMENT,\n        tag: 'div',\n        tagType: ElementTypes.ELEMENT,\n      })\n\n      expect(ast.children[1]).toMatchObject({\n        type: NodeTypes.ELEMENT,\n        tag: 'comp',\n        tagType: ElementTypes.COMPONENT,\n      })\n\n      expect(ast.children[2]).toMatchObject({\n        type: NodeTypes.ELEMENT,\n        tag: 'Comp',\n        tagType: ElementTypes.COMPONENT,\n      })\n    })\n\n    test('native element without `isNativeTag`', () => {\n      const ast = baseParse('<div></div><comp></comp><Comp></Comp>')\n\n      expect(ast.children[0]).toMatchObject({\n        type: NodeTypes.ELEMENT,\n        tag: 'div',\n        tagType: ElementTypes.ELEMENT,\n      })\n\n      expect(ast.children[1]).toMatchObject({\n        type: NodeTypes.ELEMENT,\n        tag: 'comp',\n        tagType: ElementTypes.ELEMENT,\n      })\n\n      expect(ast.children[2]).toMatchObject({\n        type: NodeTypes.ELEMENT,\n        tag: 'Comp',\n        tagType: ElementTypes.COMPONENT,\n      })\n    })\n\n    test('is casting with `isNativeTag`', () => {\n      const ast = baseParse(\n        `<div></div><div is=\"vue:foo\"></div><Comp></Comp>`,\n        {\n          isNativeTag: tag => tag === 'div',\n        },\n      )\n\n      expect(ast.children[0]).toMatchObject({\n        type: NodeTypes.ELEMENT,\n        tag: 'div',\n        tagType: ElementTypes.ELEMENT,\n      })\n\n      expect(ast.children[1]).toMatchObject({\n        type: NodeTypes.ELEMENT,\n        tag: 'div',\n        tagType: ElementTypes.COMPONENT,\n      })\n\n      expect(ast.children[2]).toMatchObject({\n        type: NodeTypes.ELEMENT,\n        tag: 'Comp',\n        tagType: ElementTypes.COMPONENT,\n      })\n    })\n\n    test('is casting without `isNativeTag`', () => {\n      const ast = baseParse(`<div></div><div is=\"vue:foo\"></div><Comp></Comp>`)\n\n      expect(ast.children[0]).toMatchObject({\n        type: NodeTypes.ELEMENT,\n        tag: 'div',\n        tagType: ElementTypes.ELEMENT,\n      })\n\n      expect(ast.children[1]).toMatchObject({\n        type: NodeTypes.ELEMENT,\n        tag: 'div',\n        tagType: ElementTypes.COMPONENT,\n      })\n\n      expect(ast.children[2]).toMatchObject({\n        type: NodeTypes.ELEMENT,\n        tag: 'Comp',\n        tagType: ElementTypes.COMPONENT,\n      })\n    })\n\n    test('custom element', () => {\n      const ast = baseParse('<div></div><comp></comp>', {\n        isNativeTag: tag => tag === 'div',\n        isCustomElement: tag => tag === 'comp',\n      })\n\n      expect(ast.children[0]).toMatchObject({\n        type: NodeTypes.ELEMENT,\n        tag: 'div',\n        tagType: ElementTypes.ELEMENT,\n      })\n\n      expect(ast.children[1]).toMatchObject({\n        type: NodeTypes.ELEMENT,\n        tag: 'comp',\n        tagType: ElementTypes.ELEMENT,\n      })\n    })\n\n    test('built-in component', () => {\n      const ast = baseParse('<div></div><comp></comp>', {\n        isBuiltInComponent: tag => (tag === 'comp' ? Symbol() : void 0),\n      })\n\n      expect(ast.children[0]).toMatchObject({\n        type: NodeTypes.ELEMENT,\n        tag: 'div',\n        tagType: ElementTypes.ELEMENT,\n      })\n\n      expect(ast.children[1]).toMatchObject({\n        type: NodeTypes.ELEMENT,\n        tag: 'comp',\n        tagType: ElementTypes.COMPONENT,\n      })\n    })\n\n    test('slot element', () => {\n      const ast = baseParse('<slot></slot><Comp></Comp>')\n\n      expect(ast.children[0]).toMatchObject({\n        type: NodeTypes.ELEMENT,\n        tag: 'slot',\n        tagType: ElementTypes.SLOT,\n      })\n\n      expect(ast.children[1]).toMatchObject({\n        type: NodeTypes.ELEMENT,\n        tag: 'Comp',\n        tagType: ElementTypes.COMPONENT,\n      })\n    })\n\n    test('attribute with no value', () => {\n      const ast = baseParse('<div id></div>')\n      const element = ast.children[0] as ElementNode\n\n      expect(element).toStrictEqual({\n        type: NodeTypes.ELEMENT,\n        ns: Namespaces.HTML,\n        tag: 'div',\n        tagType: ElementTypes.ELEMENT,\n        codegenNode: undefined,\n        props: [\n          {\n            type: NodeTypes.ATTRIBUTE,\n            name: 'id',\n            nameLoc: {\n              start: { offset: 5, line: 1, column: 6 },\n              end: { offset: 7, line: 1, column: 8 },\n              source: 'id',\n            },\n            value: undefined,\n            loc: {\n              start: { offset: 5, line: 1, column: 6 },\n              end: { offset: 7, line: 1, column: 8 },\n              source: 'id',\n            },\n          },\n        ],\n\n        children: [],\n        loc: {\n          start: { offset: 0, line: 1, column: 1 },\n          end: { offset: 14, line: 1, column: 15 },\n          source: '<div id></div>',\n        },\n      })\n    })\n\n    test('attribute with empty value, double quote', () => {\n      const ast = baseParse('<div id=\"\"></div>')\n      const element = ast.children[0] as ElementNode\n\n      expect(element).toStrictEqual({\n        type: NodeTypes.ELEMENT,\n        ns: Namespaces.HTML,\n        tag: 'div',\n        tagType: ElementTypes.ELEMENT,\n        codegenNode: undefined,\n        props: [\n          {\n            type: NodeTypes.ATTRIBUTE,\n            name: 'id',\n            nameLoc: {\n              start: { offset: 5, line: 1, column: 6 },\n              end: { offset: 7, line: 1, column: 8 },\n              source: 'id',\n            },\n            value: {\n              type: NodeTypes.TEXT,\n              content: '',\n              loc: {\n                start: { offset: 8, line: 1, column: 9 },\n                end: { offset: 10, line: 1, column: 11 },\n                source: '\"\"',\n              },\n            },\n            loc: {\n              start: { offset: 5, line: 1, column: 6 },\n              end: { offset: 10, line: 1, column: 11 },\n              source: 'id=\"\"',\n            },\n          },\n        ],\n\n        children: [],\n        loc: {\n          start: { offset: 0, line: 1, column: 1 },\n          end: { offset: 17, line: 1, column: 18 },\n          source: '<div id=\"\"></div>',\n        },\n      })\n    })\n\n    test('attribute with empty value, single quote', () => {\n      const ast = baseParse(\"<div id=''></div>\")\n      const element = ast.children[0] as ElementNode\n\n      expect(element).toStrictEqual({\n        type: NodeTypes.ELEMENT,\n        ns: Namespaces.HTML,\n        tag: 'div',\n        tagType: ElementTypes.ELEMENT,\n        codegenNode: undefined,\n        props: [\n          {\n            type: NodeTypes.ATTRIBUTE,\n            name: 'id',\n            nameLoc: {\n              start: { offset: 5, line: 1, column: 6 },\n              end: { offset: 7, line: 1, column: 8 },\n              source: 'id',\n            },\n            value: {\n              type: NodeTypes.TEXT,\n              content: '',\n              loc: {\n                start: { offset: 8, line: 1, column: 9 },\n                end: { offset: 10, line: 1, column: 11 },\n                source: \"''\",\n              },\n            },\n            loc: {\n              start: { offset: 5, line: 1, column: 6 },\n              end: { offset: 10, line: 1, column: 11 },\n              source: \"id=''\",\n            },\n          },\n        ],\n\n        children: [],\n        loc: {\n          start: { offset: 0, line: 1, column: 1 },\n          end: { offset: 17, line: 1, column: 18 },\n          source: \"<div id=''></div>\",\n        },\n      })\n    })\n\n    test('attribute with value, double quote', () => {\n      const ast = baseParse('<div id=\">\\'\"></div>')\n      const element = ast.children[0] as ElementNode\n\n      expect(element).toStrictEqual({\n        type: NodeTypes.ELEMENT,\n        ns: Namespaces.HTML,\n        tag: 'div',\n        tagType: ElementTypes.ELEMENT,\n        codegenNode: undefined,\n        props: [\n          {\n            type: NodeTypes.ATTRIBUTE,\n            name: 'id',\n            nameLoc: {\n              start: { offset: 5, line: 1, column: 6 },\n              end: { offset: 7, line: 1, column: 8 },\n              source: 'id',\n            },\n            value: {\n              type: NodeTypes.TEXT,\n              content: \">'\",\n              loc: {\n                start: { offset: 8, line: 1, column: 9 },\n                end: { offset: 12, line: 1, column: 13 },\n                source: '\">\\'\"',\n              },\n            },\n            loc: {\n              start: { offset: 5, line: 1, column: 6 },\n              end: { offset: 12, line: 1, column: 13 },\n              source: 'id=\">\\'\"',\n            },\n          },\n        ],\n\n        children: [],\n        loc: {\n          start: { offset: 0, line: 1, column: 1 },\n          end: { offset: 19, line: 1, column: 20 },\n          source: '<div id=\">\\'\"></div>',\n        },\n      })\n    })\n\n    test('attribute with value, single quote', () => {\n      const ast = baseParse(\"<div id='>\\\"'></div>\")\n      const element = ast.children[0] as ElementNode\n\n      expect(element).toStrictEqual({\n        type: NodeTypes.ELEMENT,\n        ns: Namespaces.HTML,\n        tag: 'div',\n        tagType: ElementTypes.ELEMENT,\n        codegenNode: undefined,\n        props: [\n          {\n            type: NodeTypes.ATTRIBUTE,\n            name: 'id',\n            nameLoc: {\n              start: { offset: 5, line: 1, column: 6 },\n              end: { offset: 7, line: 1, column: 8 },\n              source: 'id',\n            },\n            value: {\n              type: NodeTypes.TEXT,\n              content: '>\"',\n              loc: {\n                start: { offset: 8, line: 1, column: 9 },\n                end: { offset: 12, line: 1, column: 13 },\n                source: \"'>\\\"'\",\n              },\n            },\n            loc: {\n              start: { offset: 5, line: 1, column: 6 },\n              end: { offset: 12, line: 1, column: 13 },\n              source: \"id='>\\\"'\",\n            },\n          },\n        ],\n\n        children: [],\n        loc: {\n          start: { offset: 0, line: 1, column: 1 },\n          end: { offset: 19, line: 1, column: 20 },\n          source: \"<div id='>\\\"'></div>\",\n        },\n      })\n    })\n\n    test('attribute with value, unquoted', () => {\n      const ast = baseParse('<div id=a/></div>')\n      const element = ast.children[0] as ElementNode\n\n      expect(element).toStrictEqual({\n        type: NodeTypes.ELEMENT,\n        ns: Namespaces.HTML,\n        tag: 'div',\n        tagType: ElementTypes.ELEMENT,\n        codegenNode: undefined,\n        props: [\n          {\n            type: NodeTypes.ATTRIBUTE,\n            name: 'id',\n            nameLoc: {\n              start: { offset: 5, line: 1, column: 6 },\n              end: { offset: 7, line: 1, column: 8 },\n              source: 'id',\n            },\n            value: {\n              type: NodeTypes.TEXT,\n              content: 'a/',\n              loc: {\n                start: { offset: 8, line: 1, column: 9 },\n                end: { offset: 10, line: 1, column: 11 },\n                source: 'a/',\n              },\n            },\n            loc: {\n              start: { offset: 5, line: 1, column: 6 },\n              end: { offset: 10, line: 1, column: 11 },\n              source: 'id=a/',\n            },\n          },\n        ],\n\n        children: [],\n        loc: {\n          start: { offset: 0, line: 1, column: 1 },\n          end: { offset: 17, line: 1, column: 18 },\n          source: '<div id=a/></div>',\n        },\n      })\n    })\n\n    test('attribute value with >', () => {\n      const ast = baseParse(\n        '<script setup lang=\"ts\" generic=\"T extends Record<string,string>\"></script>',\n        { parseMode: 'sfc' },\n      )\n      const element = ast.children[0] as ElementNode\n      expect(element).toMatchObject({\n        type: NodeTypes.ELEMENT,\n        ns: Namespaces.HTML,\n        tag: 'script',\n        tagType: ElementTypes.ELEMENT,\n        codegenNode: undefined,\n        children: [],\n        innerLoc: {\n          start: { column: 67, line: 1, offset: 66 },\n          end: { column: 67, line: 1, offset: 66 },\n        },\n        props: [\n          {\n            loc: {\n              source: 'setup',\n              end: { column: 14, line: 1, offset: 13 },\n              start: { column: 9, line: 1, offset: 8 },\n            },\n            name: 'setup',\n            nameLoc: {\n              source: 'setup',\n              end: { column: 14, line: 1, offset: 13 },\n              start: { column: 9, line: 1, offset: 8 },\n            },\n            type: NodeTypes.ATTRIBUTE,\n            value: undefined,\n          },\n          {\n            loc: {\n              source: 'lang=\"ts\"',\n              end: { column: 24, line: 1, offset: 23 },\n              start: { column: 15, line: 1, offset: 14 },\n            },\n            name: 'lang',\n            nameLoc: {\n              source: 'lang',\n              end: { column: 19, line: 1, offset: 18 },\n              start: { column: 15, line: 1, offset: 14 },\n            },\n            type: NodeTypes.ATTRIBUTE,\n            value: {\n              content: 'ts',\n              loc: {\n                source: '\"ts\"',\n                end: { column: 24, line: 1, offset: 23 },\n                start: { column: 20, line: 1, offset: 19 },\n              },\n              type: NodeTypes.TEXT,\n            },\n          },\n          {\n            loc: {\n              source: 'generic=\"T extends Record<string,string>\"',\n              end: { column: 66, line: 1, offset: 65 },\n              start: { column: 25, line: 1, offset: 24 },\n            },\n            name: 'generic',\n            nameLoc: {\n              source: 'generic',\n              end: { column: 32, line: 1, offset: 31 },\n              start: { column: 25, line: 1, offset: 24 },\n            },\n            type: NodeTypes.ATTRIBUTE,\n            value: {\n              content: 'T extends Record<string,string>',\n              loc: {\n                source: '\"T extends Record<string,string>\"',\n                end: { column: 66, line: 1, offset: 65 },\n                start: { column: 33, line: 1, offset: 32 },\n              },\n              type: NodeTypes.TEXT,\n            },\n          },\n        ],\n      })\n    })\n\n    test('multiple attributes', () => {\n      const ast = baseParse('<div id=a class=\"c\" inert style=\\'\\'></div>')\n      const element = ast.children[0] as ElementNode\n\n      expect(element).toStrictEqual({\n        type: NodeTypes.ELEMENT,\n        ns: Namespaces.HTML,\n        tag: 'div',\n        tagType: ElementTypes.ELEMENT,\n        codegenNode: undefined,\n        props: [\n          {\n            type: NodeTypes.ATTRIBUTE,\n            name: 'id',\n            nameLoc: {\n              start: { offset: 5, line: 1, column: 6 },\n              end: { offset: 7, line: 1, column: 8 },\n              source: 'id',\n            },\n            value: {\n              type: NodeTypes.TEXT,\n              content: 'a',\n              loc: {\n                start: { offset: 8, line: 1, column: 9 },\n                end: { offset: 9, line: 1, column: 10 },\n                source: 'a',\n              },\n            },\n            loc: {\n              start: { offset: 5, line: 1, column: 6 },\n              end: { offset: 9, line: 1, column: 10 },\n              source: 'id=a',\n            },\n          },\n          {\n            type: NodeTypes.ATTRIBUTE,\n            name: 'class',\n            nameLoc: {\n              start: { offset: 10, line: 1, column: 11 },\n              end: { offset: 15, line: 1, column: 16 },\n              source: 'class',\n            },\n            value: {\n              type: NodeTypes.TEXT,\n              content: 'c',\n              loc: {\n                start: { offset: 16, line: 1, column: 17 },\n                end: { offset: 19, line: 1, column: 20 },\n                source: '\"c\"',\n              },\n            },\n            loc: {\n              start: { offset: 10, line: 1, column: 11 },\n              end: { offset: 19, line: 1, column: 20 },\n              source: 'class=\"c\"',\n            },\n          },\n          {\n            type: NodeTypes.ATTRIBUTE,\n            name: 'inert',\n            nameLoc: {\n              start: { offset: 20, line: 1, column: 21 },\n              end: { offset: 25, line: 1, column: 26 },\n              source: 'inert',\n            },\n            value: undefined,\n            loc: {\n              start: { offset: 20, line: 1, column: 21 },\n              end: { offset: 25, line: 1, column: 26 },\n              source: 'inert',\n            },\n          },\n          {\n            type: NodeTypes.ATTRIBUTE,\n            name: 'style',\n            nameLoc: {\n              start: { offset: 26, line: 1, column: 27 },\n              end: { offset: 31, line: 1, column: 32 },\n              source: 'style',\n            },\n            value: {\n              type: NodeTypes.TEXT,\n              content: '',\n              loc: {\n                start: { offset: 32, line: 1, column: 33 },\n                end: { offset: 34, line: 1, column: 35 },\n                source: \"''\",\n              },\n            },\n            loc: {\n              start: { offset: 26, line: 1, column: 27 },\n              end: { offset: 34, line: 1, column: 35 },\n              source: \"style=''\",\n            },\n          },\n        ],\n\n        children: [],\n        loc: {\n          start: { offset: 0, line: 1, column: 1 },\n          end: { offset: 41, line: 1, column: 42 },\n          source: '<div id=a class=\"c\" inert style=\\'\\'></div>',\n        },\n      })\n    })\n\n    // https://github.com/vuejs/core/issues/4251\n    test('class attribute should ignore whitespace when parsed', () => {\n      const ast = baseParse('<div class=\" \\n\\t c \\t\\n \"></div>')\n      const element = ast.children[0] as ElementNode\n\n      expect(element).toStrictEqual({\n        children: [],\n        codegenNode: undefined,\n        loc: {\n          start: { column: 1, line: 1, offset: 0 },\n          end: { column: 10, line: 3, offset: 29 },\n          source: '<div class=\" \\n\\t c \\t\\n \"></div>',\n        },\n        ns: Namespaces.HTML,\n        props: [\n          {\n            name: 'class',\n            nameLoc: {\n              start: { column: 6, line: 1, offset: 5 },\n              end: { column: 11, line: 1, offset: 10 },\n              source: 'class',\n            },\n            type: NodeTypes.ATTRIBUTE,\n            value: {\n              content: 'c',\n              loc: {\n                start: { column: 12, line: 1, offset: 11 },\n                end: { column: 3, line: 3, offset: 22 },\n                source: '\" \\n\\t c \\t\\n \"',\n              },\n              type: NodeTypes.TEXT,\n            },\n            loc: {\n              start: { column: 6, line: 1, offset: 5 },\n              end: { column: 3, line: 3, offset: 22 },\n              source: 'class=\" \\n\\t c \\t\\n \"',\n            },\n          },\n        ],\n        tag: 'div',\n        tagType: ElementTypes.ELEMENT,\n        type: NodeTypes.ELEMENT,\n      })\n    })\n\n    test('directive with no value', () => {\n      const ast = baseParse('<div v-if/>')\n      const directive = (ast.children[0] as ElementNode).props[0]\n\n      expect(directive).toStrictEqual({\n        type: NodeTypes.DIRECTIVE,\n        name: 'if',\n        rawName: 'v-if',\n        arg: undefined,\n        modifiers: [],\n        exp: undefined,\n        loc: {\n          start: { offset: 5, line: 1, column: 6 },\n          end: { offset: 9, line: 1, column: 10 },\n          source: 'v-if',\n        },\n      })\n    })\n\n    test('directive with value', () => {\n      const ast = baseParse('<div v-if=\"a\"/>')\n      const directive = (ast.children[0] as ElementNode).props[0]\n\n      expect(directive).toStrictEqual({\n        type: NodeTypes.DIRECTIVE,\n        name: 'if',\n        rawName: 'v-if',\n        arg: undefined,\n        modifiers: [],\n        exp: {\n          type: NodeTypes.SIMPLE_EXPRESSION,\n          content: 'a',\n          isStatic: false,\n          constType: ConstantTypes.NOT_CONSTANT,\n          loc: {\n            start: { offset: 11, line: 1, column: 12 },\n            end: { offset: 12, line: 1, column: 13 },\n            source: 'a',\n          },\n        },\n        loc: {\n          start: { offset: 5, line: 1, column: 6 },\n          end: { offset: 13, line: 1, column: 14 },\n          source: 'v-if=\"a\"',\n        },\n      })\n    })\n\n    test('directive with argument', () => {\n      const ast = baseParse('<div v-on:click/>')\n      const directive = (ast.children[0] as ElementNode).props[0]\n\n      expect(directive).toStrictEqual({\n        type: NodeTypes.DIRECTIVE,\n        name: 'on',\n        rawName: 'v-on:click',\n        arg: {\n          type: NodeTypes.SIMPLE_EXPRESSION,\n          content: 'click',\n          isStatic: true,\n          constType: ConstantTypes.CAN_STRINGIFY,\n          loc: {\n            start: { column: 11, line: 1, offset: 10 },\n            end: { column: 16, line: 1, offset: 15 },\n            source: 'click',\n          },\n        },\n        modifiers: [],\n        exp: undefined,\n        loc: {\n          start: { offset: 5, line: 1, column: 6 },\n          end: { offset: 15, line: 1, column: 16 },\n          source: 'v-on:click',\n        },\n      })\n    })\n\n    // #3494\n    test('directive argument edge case', () => {\n      const ast = baseParse('<div v-slot:slot />')\n      const directive = (ast.children[0] as ElementNode)\n        .props[0] as DirectiveNode\n      expect(directive.arg).toMatchObject({\n        loc: {\n          start: { offset: 12, line: 1, column: 13 },\n          end: { offset: 16, line: 1, column: 17 },\n        },\n      })\n    })\n\n    // https://github.com/vuejs/language-tools/issues/2710\n    test('directive argument edge case (2)', () => {\n      const ast = baseParse('<div #item.item />')\n      const directive = (ast.children[0] as ElementNode)\n        .props[0] as DirectiveNode\n      expect(directive.arg).toMatchObject({\n        content: 'item.item',\n        loc: {\n          start: { offset: 6, line: 1, column: 7 },\n          end: { offset: 15, line: 1, column: 16 },\n        },\n      })\n    })\n\n    test('directive with dynamic argument', () => {\n      const ast = baseParse('<div v-on:[event]/>')\n      const directive = (ast.children[0] as ElementNode).props[0]\n\n      expect(directive).toStrictEqual({\n        type: NodeTypes.DIRECTIVE,\n        name: 'on',\n        rawName: 'v-on:[event]',\n        arg: {\n          type: NodeTypes.SIMPLE_EXPRESSION,\n          content: 'event',\n          isStatic: false,\n          constType: ConstantTypes.NOT_CONSTANT,\n          loc: {\n            start: { column: 11, line: 1, offset: 10 },\n            end: { column: 18, line: 1, offset: 17 },\n            source: '[event]',\n          },\n        },\n        modifiers: [],\n        exp: undefined,\n        loc: {\n          start: { offset: 5, line: 1, column: 6 },\n          end: { offset: 17, line: 1, column: 18 },\n          source: 'v-on:[event]',\n        },\n      })\n    })\n\n    test('directive with a modifier', () => {\n      const ast = baseParse('<div v-on.enter/>')\n      const directive = (ast.children[0] as ElementNode).props[0]\n\n      expect(directive).toStrictEqual({\n        type: NodeTypes.DIRECTIVE,\n        name: 'on',\n        rawName: 'v-on.enter',\n        arg: undefined,\n        modifiers: [\n          {\n            constType: 3,\n            content: 'enter',\n            isStatic: true,\n            loc: {\n              end: {\n                column: 16,\n                line: 1,\n                offset: 15,\n              },\n              source: 'enter',\n              start: {\n                column: 11,\n                line: 1,\n                offset: 10,\n              },\n            },\n            type: 4,\n          },\n        ],\n        exp: undefined,\n        loc: {\n          start: { offset: 5, line: 1, column: 6 },\n          end: { offset: 15, line: 1, column: 16 },\n          source: 'v-on.enter',\n        },\n      })\n    })\n\n    test('directive with two modifiers', () => {\n      const ast = baseParse('<div v-on.enter.exact/>')\n      const directive = (ast.children[0] as ElementNode).props[0]\n\n      expect(directive).toStrictEqual({\n        type: NodeTypes.DIRECTIVE,\n        name: 'on',\n        rawName: 'v-on.enter.exact',\n        arg: undefined,\n        modifiers: [\n          {\n            constType: 3,\n            content: 'enter',\n            isStatic: true,\n            loc: {\n              end: {\n                column: 16,\n                line: 1,\n                offset: 15,\n              },\n              source: 'enter',\n              start: {\n                column: 11,\n                line: 1,\n                offset: 10,\n              },\n            },\n            type: 4,\n          },\n          {\n            constType: 3,\n            content: 'exact',\n            isStatic: true,\n            loc: {\n              end: {\n                column: 22,\n                line: 1,\n                offset: 21,\n              },\n              source: 'exact',\n              start: {\n                column: 17,\n                line: 1,\n                offset: 16,\n              },\n            },\n            type: 4,\n          },\n        ],\n        exp: undefined,\n        loc: {\n          start: { offset: 5, line: 1, column: 6 },\n          end: { offset: 21, line: 1, column: 22 },\n          source: 'v-on.enter.exact',\n        },\n      })\n    })\n\n    test('directive with argument and modifiers', () => {\n      const ast = baseParse('<div v-on:click.enter.exact/>')\n      const directive = (ast.children[0] as ElementNode).props[0]\n\n      expect(directive).toStrictEqual({\n        type: NodeTypes.DIRECTIVE,\n        name: 'on',\n        rawName: 'v-on:click.enter.exact',\n        arg: {\n          type: NodeTypes.SIMPLE_EXPRESSION,\n          content: 'click',\n          isStatic: true,\n          constType: ConstantTypes.CAN_STRINGIFY,\n          loc: {\n            start: { column: 11, line: 1, offset: 10 },\n            end: { column: 16, line: 1, offset: 15 },\n            source: 'click',\n          },\n        },\n        modifiers: [\n          {\n            constType: 3,\n            content: 'enter',\n            isStatic: true,\n            loc: {\n              end: {\n                column: 22,\n                line: 1,\n                offset: 21,\n              },\n              source: 'enter',\n              start: {\n                column: 17,\n                line: 1,\n                offset: 16,\n              },\n            },\n            type: 4,\n          },\n          {\n            constType: 3,\n            content: 'exact',\n            isStatic: true,\n            loc: {\n              end: {\n                column: 28,\n                line: 1,\n                offset: 27,\n              },\n              source: 'exact',\n              start: {\n                column: 23,\n                line: 1,\n                offset: 22,\n              },\n            },\n            type: 4,\n          },\n        ],\n        exp: undefined,\n        loc: {\n          start: { offset: 5, line: 1, column: 6 },\n          end: { offset: 27, line: 1, column: 28 },\n          source: 'v-on:click.enter.exact',\n        },\n      })\n    })\n\n    test('directive with dynamic argument and modifiers', () => {\n      const ast = baseParse('<div v-on:[a.b].camel/>')\n      const directive = (ast.children[0] as ElementNode).props[0]\n\n      expect(directive).toStrictEqual({\n        type: NodeTypes.DIRECTIVE,\n        name: 'on',\n        rawName: 'v-on:[a.b].camel',\n        arg: {\n          type: NodeTypes.SIMPLE_EXPRESSION,\n          content: 'a.b',\n          isStatic: false,\n          constType: ConstantTypes.NOT_CONSTANT,\n          loc: {\n            start: { column: 11, line: 1, offset: 10 },\n            end: { column: 16, line: 1, offset: 15 },\n            source: '[a.b]',\n          },\n        },\n        modifiers: [\n          {\n            constType: 3,\n            content: 'camel',\n            isStatic: true,\n            loc: {\n              end: {\n                column: 22,\n                line: 1,\n                offset: 21,\n              },\n              source: 'camel',\n              start: {\n                column: 17,\n                line: 1,\n                offset: 16,\n              },\n            },\n            type: 4,\n          },\n        ],\n        exp: undefined,\n        loc: {\n          start: { offset: 5, line: 1, column: 6 },\n          end: { offset: 21, line: 1, column: 22 },\n          source: 'v-on:[a.b].camel',\n        },\n      })\n    })\n\n    test('directive with no name', () => {\n      let errorCode = -1\n      const ast = baseParse('<div v-/>', {\n        onError: err => {\n          errorCode = err.code as number\n        },\n      })\n      const directive = (ast.children[0] as ElementNode).props[0]\n\n      expect(errorCode).toBe(ErrorCodes.X_MISSING_DIRECTIVE_NAME)\n      expect(directive).toStrictEqual({\n        type: NodeTypes.ATTRIBUTE,\n        name: 'v-',\n        value: undefined,\n        loc: {\n          start: { offset: 5, line: 1, column: 6 },\n          end: { offset: 7, line: 1, column: 8 },\n          source: 'v-',\n        },\n        nameLoc: {\n          start: { offset: 5, line: 1, column: 6 },\n          end: { offset: 7, line: 1, column: 8 },\n          source: 'v-',\n        },\n      })\n    })\n\n    test('v-bind shorthand', () => {\n      const ast = baseParse('<div :a=b />')\n      const directive = (ast.children[0] as ElementNode).props[0]\n\n      expect(directive).toStrictEqual({\n        type: NodeTypes.DIRECTIVE,\n        name: 'bind',\n        rawName: ':a',\n        arg: {\n          type: NodeTypes.SIMPLE_EXPRESSION,\n          content: 'a',\n          isStatic: true,\n          constType: ConstantTypes.CAN_STRINGIFY,\n          loc: {\n            start: { column: 7, line: 1, offset: 6 },\n            end: { column: 8, line: 1, offset: 7 },\n            source: 'a',\n          },\n        },\n        modifiers: [],\n        exp: {\n          type: NodeTypes.SIMPLE_EXPRESSION,\n          content: 'b',\n          isStatic: false,\n          constType: ConstantTypes.NOT_CONSTANT,\n          loc: {\n            start: { offset: 8, line: 1, column: 9 },\n            end: { offset: 9, line: 1, column: 10 },\n            source: 'b',\n          },\n        },\n        loc: {\n          start: { offset: 5, line: 1, column: 6 },\n          end: { offset: 9, line: 1, column: 10 },\n          source: ':a=b',\n        },\n      })\n    })\n\n    test('v-bind .prop shorthand', () => {\n      const ast = baseParse('<div .a=b />')\n      const directive = (ast.children[0] as ElementNode).props[0]\n\n      expect(directive).toStrictEqual({\n        type: NodeTypes.DIRECTIVE,\n        name: 'bind',\n        rawName: '.a',\n        arg: {\n          type: NodeTypes.SIMPLE_EXPRESSION,\n          content: 'a',\n          isStatic: true,\n          constType: ConstantTypes.CAN_STRINGIFY,\n          loc: {\n            start: { column: 7, line: 1, offset: 6 },\n            end: { column: 8, line: 1, offset: 7 },\n            source: 'a',\n          },\n        },\n        modifiers: [\n          {\n            constType: 0,\n            content: 'prop',\n            isStatic: false,\n            loc: {\n              end: {\n                column: 1,\n                line: 1,\n                offset: 0,\n              },\n              source: '',\n              start: {\n                column: 1,\n                line: 1,\n                offset: 0,\n              },\n            },\n            type: 4,\n          },\n        ],\n        exp: {\n          type: NodeTypes.SIMPLE_EXPRESSION,\n          content: 'b',\n          isStatic: false,\n          constType: ConstantTypes.NOT_CONSTANT,\n          loc: {\n            start: { offset: 8, line: 1, column: 9 },\n            end: { offset: 9, line: 1, column: 10 },\n            source: 'b',\n          },\n        },\n        loc: {\n          start: { offset: 5, line: 1, column: 6 },\n          end: { offset: 9, line: 1, column: 10 },\n          source: '.a=b',\n        },\n      })\n    })\n\n    test('v-bind shorthand with modifier', () => {\n      const ast = baseParse('<div :a.sync=b />')\n      const directive = (ast.children[0] as ElementNode).props[0]\n\n      expect(directive).toStrictEqual({\n        type: NodeTypes.DIRECTIVE,\n        name: 'bind',\n        rawName: ':a.sync',\n        arg: {\n          type: NodeTypes.SIMPLE_EXPRESSION,\n          content: 'a',\n          isStatic: true,\n          constType: ConstantTypes.CAN_STRINGIFY,\n          loc: {\n            start: { column: 7, line: 1, offset: 6 },\n            end: { column: 8, line: 1, offset: 7 },\n            source: 'a',\n          },\n        },\n        modifiers: [\n          {\n            constType: 3,\n            content: 'sync',\n            isStatic: true,\n            loc: {\n              end: {\n                column: 13,\n                line: 1,\n                offset: 12,\n              },\n              source: 'sync',\n              start: {\n                column: 9,\n                line: 1,\n                offset: 8,\n              },\n            },\n            type: 4,\n          },\n        ],\n        exp: {\n          type: NodeTypes.SIMPLE_EXPRESSION,\n          content: 'b',\n          isStatic: false,\n          constType: ConstantTypes.NOT_CONSTANT,\n\n          loc: {\n            start: { offset: 13, line: 1, column: 14 },\n            end: { offset: 14, line: 1, column: 15 },\n            source: 'b',\n          },\n        },\n        loc: {\n          start: { offset: 5, line: 1, column: 6 },\n          end: { offset: 14, line: 1, column: 15 },\n          source: ':a.sync=b',\n        },\n      })\n    })\n\n    test('v-on shorthand', () => {\n      const ast = baseParse('<div @a=b />')\n      const directive = (ast.children[0] as ElementNode).props[0]\n\n      expect(directive).toStrictEqual({\n        type: NodeTypes.DIRECTIVE,\n        name: 'on',\n        rawName: '@a',\n        arg: {\n          type: NodeTypes.SIMPLE_EXPRESSION,\n          content: 'a',\n          isStatic: true,\n          constType: ConstantTypes.CAN_STRINGIFY,\n          loc: {\n            start: { column: 7, line: 1, offset: 6 },\n            end: { column: 8, line: 1, offset: 7 },\n            source: 'a',\n          },\n        },\n        modifiers: [],\n        exp: {\n          type: NodeTypes.SIMPLE_EXPRESSION,\n          content: 'b',\n          isStatic: false,\n          constType: ConstantTypes.NOT_CONSTANT,\n\n          loc: {\n            start: { offset: 8, line: 1, column: 9 },\n            end: { offset: 9, line: 1, column: 10 },\n            source: 'b',\n          },\n        },\n        loc: {\n          start: { offset: 5, line: 1, column: 6 },\n          end: { offset: 9, line: 1, column: 10 },\n          source: '@a=b',\n        },\n      })\n    })\n\n    test('v-on shorthand with modifier', () => {\n      const ast = baseParse('<div @a.enter=b />')\n      const directive = (ast.children[0] as ElementNode).props[0]\n\n      expect(directive).toStrictEqual({\n        type: NodeTypes.DIRECTIVE,\n        name: 'on',\n        rawName: '@a.enter',\n        arg: {\n          type: NodeTypes.SIMPLE_EXPRESSION,\n          content: 'a',\n          isStatic: true,\n          constType: ConstantTypes.CAN_STRINGIFY,\n          loc: {\n            start: { column: 7, line: 1, offset: 6 },\n            end: { column: 8, line: 1, offset: 7 },\n            source: 'a',\n          },\n        },\n        modifiers: [\n          {\n            constType: 3,\n            content: 'enter',\n            isStatic: true,\n            loc: {\n              end: {\n                column: 14,\n                line: 1,\n                offset: 13,\n              },\n              source: 'enter',\n              start: {\n                column: 9,\n                line: 1,\n                offset: 8,\n              },\n            },\n            type: 4,\n          },\n        ],\n        exp: {\n          type: NodeTypes.SIMPLE_EXPRESSION,\n          content: 'b',\n          isStatic: false,\n          constType: ConstantTypes.NOT_CONSTANT,\n\n          loc: {\n            start: { offset: 14, line: 1, column: 15 },\n            end: { offset: 15, line: 1, column: 16 },\n            source: 'b',\n          },\n        },\n        loc: {\n          start: { offset: 5, line: 1, column: 6 },\n          end: { offset: 15, line: 1, column: 16 },\n          source: '@a.enter=b',\n        },\n      })\n    })\n\n    test('v-slot shorthand', () => {\n      const ast = baseParse('<Comp #a=\"{ b }\" />')\n      const directive = (ast.children[0] as ElementNode).props[0]\n\n      expect(directive).toStrictEqual({\n        type: NodeTypes.DIRECTIVE,\n        name: 'slot',\n        rawName: '#a',\n        arg: {\n          type: NodeTypes.SIMPLE_EXPRESSION,\n          content: 'a',\n          isStatic: true,\n          constType: ConstantTypes.CAN_STRINGIFY,\n          loc: {\n            start: { column: 8, line: 1, offset: 7 },\n            end: { column: 9, line: 1, offset: 8 },\n            source: 'a',\n          },\n        },\n        modifiers: [],\n        exp: {\n          type: NodeTypes.SIMPLE_EXPRESSION,\n          content: '{ b }',\n          isStatic: false,\n          // The `constType` is the default value and will be determined in transformExpression\n          constType: ConstantTypes.NOT_CONSTANT,\n          loc: {\n            start: { offset: 10, line: 1, column: 11 },\n            end: { offset: 15, line: 1, column: 16 },\n            source: '{ b }',\n          },\n        },\n        loc: {\n          start: { offset: 6, line: 1, column: 7 },\n          end: { offset: 16, line: 1, column: 17 },\n          source: '#a=\"{ b }\"',\n        },\n      })\n    })\n\n    // #1241 special case for 2.x compat\n    test('v-slot arg containing dots', () => {\n      const ast = baseParse('<Comp v-slot:foo.bar=\"{ a }\" />')\n      const directive = (ast.children[0] as ElementNode).props[0]\n\n      expect(directive).toMatchObject({\n        type: NodeTypes.DIRECTIVE,\n        name: 'slot',\n        rawName: 'v-slot:foo.bar',\n        arg: {\n          type: NodeTypes.SIMPLE_EXPRESSION,\n          content: 'foo.bar',\n          isStatic: true,\n          constType: ConstantTypes.CAN_STRINGIFY,\n          loc: {\n            start: {\n              column: 14,\n              line: 1,\n              offset: 13,\n            },\n            end: {\n              column: 21,\n              line: 1,\n              offset: 20,\n            },\n          },\n        },\n      })\n    })\n\n    test('v-pre', () => {\n      const ast = baseParse(\n        `<div v-pre :id=\"foo\"><Comp/>{{ bar }}</div>\\n` +\n          `<div :id=\"foo\"><Comp/>{{ bar }}</div>`,\n      )\n\n      const divWithPre = ast.children[0] as ElementNode\n      expect(divWithPre.props).toMatchObject([\n        {\n          type: NodeTypes.ATTRIBUTE,\n          name: `:id`,\n          value: {\n            type: NodeTypes.TEXT,\n            content: `foo`,\n          },\n          loc: {\n            start: { line: 1, column: 12 },\n            end: { line: 1, column: 21 },\n          },\n        },\n      ])\n      expect(divWithPre.children[0]).toMatchObject({\n        type: NodeTypes.ELEMENT,\n        tagType: ElementTypes.ELEMENT,\n        tag: `Comp`,\n      })\n      expect(divWithPre.children[1]).toMatchObject({\n        type: NodeTypes.TEXT,\n        content: `{{ bar }}`,\n      })\n\n      // should not affect siblings after it\n      const divWithoutPre = ast.children[1] as ElementNode\n      expect(divWithoutPre.props).toMatchObject([\n        {\n          type: NodeTypes.DIRECTIVE,\n          name: `bind`,\n          arg: {\n            type: NodeTypes.SIMPLE_EXPRESSION,\n            isStatic: true,\n            content: `id`,\n          },\n          exp: {\n            type: NodeTypes.SIMPLE_EXPRESSION,\n            isStatic: false,\n            content: `foo`,\n          },\n          loc: {\n            start: {\n              line: 2,\n              column: 6,\n            },\n            end: {\n              line: 2,\n              column: 15,\n            },\n          },\n        },\n      ])\n      expect(divWithoutPre.children[0]).toMatchObject({\n        type: NodeTypes.ELEMENT,\n        tagType: ElementTypes.COMPONENT,\n        tag: `Comp`,\n      })\n      expect(divWithoutPre.children[1]).toMatchObject({\n        type: NodeTypes.INTERPOLATION,\n        content: {\n          type: NodeTypes.SIMPLE_EXPRESSION,\n          content: `bar`,\n          isStatic: false,\n        },\n      })\n    })\n\n    // https://github.com/vuejs/docs/issues/2586\n    test('v-pre with half-open interpolation', () => {\n      const ast = baseParse(\n        `<div v-pre>\n          <span>{{ number </span>\n          <span>}}</span>\n        </div>\n        `,\n      )\n      expect((ast.children[0] as ElementNode).children).toMatchObject([\n        {\n          type: NodeTypes.ELEMENT,\n          children: [{ type: NodeTypes.TEXT, content: `{{ number ` }],\n        },\n        {\n          type: NodeTypes.ELEMENT,\n          children: [{ type: NodeTypes.TEXT, content: `}}` }],\n        },\n      ])\n\n      const ast2 = baseParse(`<div v-pre><span>{{ number </span></div>`)\n      expect((ast2.children[0] as ElementNode).children).toMatchObject([\n        {\n          type: NodeTypes.ELEMENT,\n          children: [{ type: NodeTypes.TEXT, content: `{{ number ` }],\n        },\n      ])\n\n      const ast3 = baseParse(`<div v-pre><textarea>{{ foo </textarea></div>`, {\n        parseMode: 'html',\n      })\n      expect((ast3.children[0] as ElementNode).children).toMatchObject([\n        {\n          type: NodeTypes.ELEMENT,\n          children: [\n            {\n              type: NodeTypes.TEXT,\n              content: `{{ foo `,\n            },\n          ],\n        },\n      ])\n    })\n\n    test('self-closing v-pre', () => {\n      const ast = baseParse(\n        `<div v-pre/>\\n<div :id=\"foo\"><Comp/>{{ bar }}</div>`,\n      )\n      // should not affect siblings after it\n      const divWithoutPre = ast.children[1] as ElementNode\n      expect(divWithoutPre.props).toMatchObject([\n        {\n          type: NodeTypes.DIRECTIVE,\n          name: `bind`,\n          arg: {\n            type: NodeTypes.SIMPLE_EXPRESSION,\n            isStatic: true,\n            content: `id`,\n          },\n          exp: {\n            type: NodeTypes.SIMPLE_EXPRESSION,\n            isStatic: false,\n            content: `foo`,\n          },\n          loc: {\n            start: {\n              line: 2,\n              column: 6,\n            },\n            end: {\n              line: 2,\n              column: 15,\n            },\n          },\n        },\n      ])\n      expect(divWithoutPre.children[0]).toMatchObject({\n        type: NodeTypes.ELEMENT,\n        tagType: ElementTypes.COMPONENT,\n        tag: `Comp`,\n      })\n      expect(divWithoutPre.children[1]).toMatchObject({\n        type: NodeTypes.INTERPOLATION,\n        content: {\n          type: NodeTypes.SIMPLE_EXPRESSION,\n          content: `bar`,\n          isStatic: false,\n        },\n      })\n    })\n\n    test('end tags are case-insensitive.', () => {\n      const ast = baseParse('<div>hello</DIV>after')\n      const element = ast.children[0] as ElementNode\n      const text = element.children[0] as TextNode\n\n      expect(text).toStrictEqual({\n        type: NodeTypes.TEXT,\n        content: 'hello',\n        loc: {\n          start: { offset: 5, line: 1, column: 6 },\n          end: { offset: 10, line: 1, column: 11 },\n          source: 'hello',\n        },\n      })\n    })\n  })\n\n  describe('Edge Cases', () => {\n    test('self closing single tag', () => {\n      const ast = baseParse('<div :class=\"{ some: condition }\" />')\n\n      expect(ast.children).toHaveLength(1)\n      expect(ast.children[0]).toMatchObject({ tag: 'div' })\n    })\n\n    test('self closing multiple tag', () => {\n      const ast = baseParse(\n        `<div :class=\"{ some: condition }\" />\\n` +\n          `<p v-bind:style=\"{ color: 'red' }\"/>`,\n      )\n\n      expect(ast).toMatchSnapshot()\n\n      expect(ast.children).toHaveLength(2)\n      expect(ast.children[0]).toMatchObject({ tag: 'div' })\n      expect(ast.children[1]).toMatchObject({ tag: 'p' })\n    })\n\n    test('valid html', () => {\n      const ast = baseParse(\n        `<div :class=\"{ some: condition }\">\\n` +\n          `  <p v-bind:style=\"{ color: 'red' }\"/>\\n` +\n          `  <!-- a comment with <html> inside it -->\\n` +\n          `</div>`,\n      )\n\n      expect(ast).toMatchSnapshot()\n\n      expect(ast.children).toHaveLength(1)\n      const el = ast.children[0] as any\n      expect(el).toMatchObject({\n        tag: 'div',\n      })\n      expect(el.children).toHaveLength(2)\n      expect(el.children[0]).toMatchObject({\n        tag: 'p',\n      })\n      expect(el.children[1]).toMatchObject({\n        type: NodeTypes.COMMENT,\n      })\n    })\n\n    test('invalid html', () => {\n      expect(() => {\n        baseParse(`<div>\\n<span>\\n</div>\\n</span>`)\n      }).toThrow('Element is missing end tag.')\n\n      const spy = vi.fn()\n      const ast = baseParse(`<div>\\n<span>\\n</div>\\n</span>`, {\n        onError: spy,\n      })\n\n      expect(spy.mock.calls).toMatchObject([\n        [\n          {\n            code: ErrorCodes.X_MISSING_END_TAG,\n            loc: {\n              start: {\n                offset: 6,\n                line: 2,\n                column: 1,\n              },\n            },\n          },\n        ],\n        [\n          {\n            code: ErrorCodes.X_INVALID_END_TAG,\n            loc: {\n              start: {\n                offset: 20,\n                line: 4,\n                column: 1,\n              },\n            },\n          },\n        ],\n      ])\n\n      expect(ast).toMatchSnapshot()\n    })\n\n    test('parse with correct location info', () => {\n      const fooSrc = `foo\\n is `\n      const barSrc = `{{ bar }}`\n      const butSrc = ` but `\n      const bazSrc = `{{ baz }}`\n      const [foo, bar, but, baz] = baseParse(\n        fooSrc + barSrc + butSrc + bazSrc,\n      ).children\n\n      let offset = 0\n      expect(foo.loc.start).toEqual({ line: 1, column: 1, offset })\n      offset += fooSrc.length\n      expect(foo.loc.end).toEqual({ line: 2, column: 5, offset })\n\n      expect(bar.loc.start).toEqual({ line: 2, column: 5, offset })\n      const barInner = (bar as InterpolationNode).content\n      offset += 3\n      expect(barInner.loc.start).toEqual({ line: 2, column: 8, offset })\n      offset += 3\n      expect(barInner.loc.end).toEqual({ line: 2, column: 11, offset })\n      offset += 3\n      expect(bar.loc.end).toEqual({ line: 2, column: 14, offset })\n\n      expect(but.loc.start).toEqual({ line: 2, column: 14, offset })\n      offset += butSrc.length\n      expect(but.loc.end).toEqual({ line: 2, column: 19, offset })\n\n      expect(baz.loc.start).toEqual({ line: 2, column: 19, offset })\n      const bazInner = (baz as InterpolationNode).content\n      offset += 3\n      expect(bazInner.loc.start).toEqual({ line: 2, column: 22, offset })\n      offset += 3\n      expect(bazInner.loc.end).toEqual({ line: 2, column: 25, offset })\n      offset += 3\n      expect(baz.loc.end).toEqual({ line: 2, column: 28, offset })\n    })\n\n    // With standard HTML parsing, the following input would ignore the slash\n    // and treat \"<\" and \"template\" as attributes on the open tag of \"Hello\",\n    // causing `<template>` to fail to close, and `<script>` being parsed as its\n    // child. This is would never be intended in actual templates, but is a common\n    // intermediate state from user input when parsing for IDE support. We want\n    // the `<script>` to be at root-level to keep the SFC structure stable for\n    // Volar to do incremental computations.\n    test('tag termination handling for IDE', () => {\n      const spy = vi.fn()\n      const ast = baseParse(\n        `<template><Hello\\n</template><script>console.log(1)</script>`,\n        {\n          onError: spy,\n        },\n      )\n      //\n      expect(ast.children.length).toBe(2)\n      expect(ast.children[1]).toMatchObject({\n        type: NodeTypes.ELEMENT,\n        tag: 'script',\n      })\n    })\n\n    test('arg should be undefined on shorthand dirs with no arg', () => {\n      const ast = baseParse(`<template #></template>`)\n      const el = ast.children[0] as ElementNode\n      expect(el.props[0]).toMatchObject({\n        type: NodeTypes.DIRECTIVE,\n        name: 'slot',\n        exp: undefined,\n        arg: undefined,\n      })\n    })\n\n    // edge case found in vue-macros where the input is TS or JSX\n    test('should reset inRCDATA state', () => {\n      baseParse(`<Foo>`, { parseMode: 'sfc', onError() {} })\n      expect(() => baseParse(`{ foo }`)).not.toThrow()\n    })\n\n    test('correct loc when the closing > is foarmatted', () => {\n      const [span] = baseParse(`<span></span\n      \n      >`).children\n\n      expect(span.loc.source).toBe('<span></span\\n      \\n      >')\n      expect(span.loc.start.offset).toBe(0)\n      expect(span.loc.end.offset).toBe(27)\n    })\n\n    test('correct loc when a line in attribute value ends with &', () => {\n      const [span] = baseParse(`<span v-if=\"foo &&\\nbar\"></span>`).children\n      expect(span.loc.end.line).toBe(2)\n    })\n  })\n\n  describe('decodeEntities option', () => {\n    test('use decode by default', () => {\n      const ast: any = baseParse('&gt;&lt;&amp;&apos;&quot;&foo;')\n\n      expect(ast.children.length).toBe(1)\n      expect(ast.children[0].type).toBe(NodeTypes.TEXT)\n      expect(ast.children[0].content).toBe('><&\\'\"&foo;')\n    })\n\n    test('should warn in non-browser build', () => {\n      baseParse('&amp;&cups;', {\n        decodeEntities: text => text.replace('&cups;', '\\u222A\\uFE00'),\n        onError: () => {}, // Ignore errors\n      })\n      expect(\n        `decodeEntities option is passed but will be ignored`,\n      ).toHaveBeenWarned()\n    })\n  })\n\n  describe('whitespace management when adopting strategy condense', () => {\n    const parse = (content: string, options?: ParserOptions) =>\n      baseParse(content, {\n        whitespace: 'condense',\n        ...options,\n      })\n\n    test('should remove whitespaces at start/end inside an element', () => {\n      const ast = parse(`<div>   <span/>    </div>`)\n      expect((ast.children[0] as ElementNode).children.length).toBe(1)\n    })\n\n    test('should remove whitespaces w/ newline between elements', () => {\n      const ast = parse(`<div/> \\n <div/> \\n <div/>`)\n      expect(ast.children.length).toBe(3)\n      expect(ast.children.every(c => c.type === NodeTypes.ELEMENT)).toBe(true)\n    })\n\n    test('should remove whitespaces adjacent to comments', () => {\n      const ast = parse(`<div/> \\n <!--foo--> <div/>`)\n      expect(ast.children.length).toBe(3)\n      expect(ast.children[0].type).toBe(NodeTypes.ELEMENT)\n      expect(ast.children[1].type).toBe(NodeTypes.COMMENT)\n      expect(ast.children[2].type).toBe(NodeTypes.ELEMENT)\n    })\n\n    test('should remove whitespaces w/ newline between comments and elements', () => {\n      const ast = parse(`<div/> \\n <!--foo--> \\n <div/>`)\n      expect(ast.children.length).toBe(3)\n      expect(ast.children[0].type).toBe(NodeTypes.ELEMENT)\n      expect(ast.children[1].type).toBe(NodeTypes.COMMENT)\n      expect(ast.children[2].type).toBe(NodeTypes.ELEMENT)\n    })\n\n    test('should NOT remove whitespaces w/ newline between interpolations', () => {\n      const ast = parse(`{{ foo }} \\n {{ bar }}`)\n      expect(ast.children.length).toBe(3)\n      expect(ast.children[0].type).toBe(NodeTypes.INTERPOLATION)\n      expect(ast.children[1]).toMatchObject({\n        type: NodeTypes.TEXT,\n        content: ' ',\n      })\n      expect(ast.children[2].type).toBe(NodeTypes.INTERPOLATION)\n    })\n\n    test('should NOT remove whitespaces w/ newline between interpolation and comment', () => {\n      const ast = parse(`<!-- foo --> \\n {{msg}}`)\n      expect(ast.children.length).toBe(3)\n      expect(ast.children[0].type).toBe(NodeTypes.COMMENT)\n      expect(ast.children[1]).toMatchObject({\n        type: NodeTypes.TEXT,\n        content: ' ',\n      })\n      expect(ast.children[2].type).toBe(NodeTypes.INTERPOLATION)\n    })\n\n    test('should NOT remove whitespaces w/o newline between elements', () => {\n      const ast = parse(`<div/> <div/> <div/>`)\n      expect(ast.children.length).toBe(5)\n      expect(ast.children.map(c => c.type)).toMatchObject([\n        NodeTypes.ELEMENT,\n        NodeTypes.TEXT,\n        NodeTypes.ELEMENT,\n        NodeTypes.TEXT,\n        NodeTypes.ELEMENT,\n      ])\n    })\n\n    test('should condense consecutive whitespaces in text', () => {\n      const ast = parse(`   foo  \\n    bar     baz     `)\n      expect((ast.children[0] as TextNode).content).toBe(` foo bar baz `)\n    })\n\n    test('should remove leading newline character immediately following the pre element start tag', () => {\n      const ast = parse(`<pre>\\n  foo  bar  </pre>`, {\n        isPreTag: tag => tag === 'pre',\n        isIgnoreNewlineTag: tag => tag === 'pre',\n      })\n      expect(ast.children).toHaveLength(1)\n      const preElement = ast.children[0] as ElementNode\n      expect(preElement.children).toHaveLength(1)\n      expect((preElement.children[0] as TextNode).content).toBe(`  foo  bar  `)\n    })\n\n    test('should NOT remove leading newline character immediately following child-tag of pre element', () => {\n      const ast = parse(`<pre><span></span>\\n  foo  bar  </pre>`, {\n        isPreTag: tag => tag === 'pre',\n      })\n      const preElement = ast.children[0] as ElementNode\n      expect(preElement.children).toHaveLength(2)\n      expect((preElement.children[1] as TextNode).content).toBe(\n        `\\n  foo  bar  `,\n      )\n    })\n\n    test('self-closing pre tag', () => {\n      const ast = parse(`<pre/><span>\\n  foo   bar</span>`, {\n        isPreTag: tag => tag === 'pre',\n      })\n      const elementAfterPre = ast.children[1] as ElementNode\n      // should not affect the <span> and condense its whitespace inside\n      expect((elementAfterPre.children[0] as TextNode).content).toBe(` foo bar`)\n    })\n\n    test('should NOT condense whitespaces in RCDATA text mode', () => {\n      const ast = parse(`<textarea>Text:\\n   foo</textarea>`, {\n        parseMode: 'html',\n      })\n      const preElement = ast.children[0] as ElementNode\n      expect(preElement.children).toHaveLength(1)\n      expect((preElement.children[0] as TextNode).content).toBe(`Text:\\n   foo`)\n    })\n  })\n\n  describe('whitespace management when adopting strategy preserve', () => {\n    const parse = (content: string, options?: ParserOptions) =>\n      baseParse(content, {\n        whitespace: 'preserve',\n        ...options,\n      })\n\n    test('should still remove whitespaces at start/end inside an element', () => {\n      const ast = parse(`<div>   <span/>    </div>`)\n      expect((ast.children[0] as ElementNode).children.length).toBe(1)\n    })\n\n    test('should preserve whitespaces w/ newline between elements', () => {\n      const ast = parse(`<div/> \\n <div/> \\n <div/>`)\n      expect(ast.children.length).toBe(5)\n      expect(ast.children.map(c => c.type)).toMatchObject([\n        NodeTypes.ELEMENT,\n        NodeTypes.TEXT,\n        NodeTypes.ELEMENT,\n        NodeTypes.TEXT,\n        NodeTypes.ELEMENT,\n      ])\n    })\n\n    test('should preserve whitespaces adjacent to comments', () => {\n      const ast = parse(`<div/> \\n <!--foo--> <div/>`)\n      expect(ast.children.length).toBe(5)\n      expect(ast.children.map(c => c.type)).toMatchObject([\n        NodeTypes.ELEMENT,\n        NodeTypes.TEXT,\n        NodeTypes.COMMENT,\n        NodeTypes.TEXT,\n        NodeTypes.ELEMENT,\n      ])\n    })\n\n    test('should preserve whitespaces w/ newline between comments and elements', () => {\n      const ast = parse(`<div/> \\n <!--foo--> \\n <div/>`)\n      expect(ast.children.length).toBe(5)\n      expect(ast.children.map(c => c.type)).toMatchObject([\n        NodeTypes.ELEMENT,\n        NodeTypes.TEXT,\n        NodeTypes.COMMENT,\n        NodeTypes.TEXT,\n        NodeTypes.ELEMENT,\n      ])\n    })\n\n    test('should preserve whitespaces w/ newline between interpolations', () => {\n      const ast = parse(`{{ foo }} \\n {{ bar }}`)\n      expect(ast.children.length).toBe(3)\n      expect(ast.children[0].type).toBe(NodeTypes.INTERPOLATION)\n      expect(ast.children[1]).toMatchObject({\n        type: NodeTypes.TEXT,\n        content: ' ',\n      })\n      expect(ast.children[2].type).toBe(NodeTypes.INTERPOLATION)\n    })\n\n    test('should preserve whitespaces w/o newline between elements', () => {\n      const ast = parse(`<div/> <div/> <div/>`)\n      expect(ast.children.length).toBe(5)\n      expect(ast.children.map(c => c.type)).toMatchObject([\n        NodeTypes.ELEMENT,\n        NodeTypes.TEXT,\n        NodeTypes.ELEMENT,\n        NodeTypes.TEXT,\n        NodeTypes.ELEMENT,\n      ])\n    })\n\n    test('should preserve consecutive whitespaces in text', () => {\n      const content = `   foo  \\n    bar     baz     `\n      const ast = parse(content)\n      expect((ast.children[0] as TextNode).content).toBe(content)\n    })\n  })\n\n  describe('expression parsing', () => {\n    test('interpolation', () => {\n      const ast = baseParse(`{{ a + b }}`, { prefixIdentifiers: true })\n      // @ts-expect-error\n      expect((ast.children[0] as InterpolationNode).content.ast?.type).toBe(\n        'BinaryExpression',\n      )\n    })\n\n    test('v-bind', () => {\n      const ast = baseParse(`<div :[key+1]=\"foo()\" />`, {\n        prefixIdentifiers: true,\n      })\n      const dir = (ast.children[0] as ElementNode).props[0] as DirectiveNode\n      // @ts-expect-error\n      expect(dir.arg?.ast?.type).toBe('BinaryExpression')\n      // @ts-expect-error\n      expect(dir.exp?.ast?.type).toBe('CallExpression')\n    })\n\n    test('v-on multi statements', () => {\n      const ast = baseParse(`<div @click=\"a++;b++\" />`, {\n        prefixIdentifiers: true,\n      })\n      const dir = (ast.children[0] as ElementNode).props[0] as DirectiveNode\n      // @ts-expect-error\n      expect(dir.exp?.ast?.type).toBe('Program')\n      expect((dir.exp?.ast as Program).body).toMatchObject([\n        { type: 'ExpressionStatement' },\n        { type: 'ExpressionStatement' },\n      ])\n    })\n\n    test('v-slot', () => {\n      const ast = baseParse(`<Comp #foo=\"{ a, b }\" />`, {\n        prefixIdentifiers: true,\n      })\n      const dir = (ast.children[0] as ElementNode).props[0] as DirectiveNode\n      // @ts-expect-error\n      expect(dir.exp?.ast?.type).toBe('ArrowFunctionExpression')\n    })\n\n    test('v-for', () => {\n      const ast = baseParse(`<div v-for=\"({ a, b }, key, index) of a.b\" />`, {\n        prefixIdentifiers: true,\n      })\n      const dir = (ast.children[0] as ElementNode).props[0] as DirectiveNode\n      const { source, value, key, index } = dir.forParseResult!\n      // @ts-expect-error\n      expect(source.ast?.type).toBe('MemberExpression')\n      // @ts-expect-error\n      expect(value?.ast?.type).toBe('ArrowFunctionExpression')\n      expect(key?.ast).toBeNull() // simple ident\n      expect(index?.ast).toBeNull() // simple ident\n    })\n  })\n\n  describe('Errors', () => {\n    // HTML parsing errors as specified at\n    // https://html.spec.whatwg.org/multipage/parsing.html#parse-errors\n    // We ignore some errors that do NOT affect parse result in meaningful ways\n    // but have non-trivial implementation cost.\n    const patterns: {\n      [key: string]: Array<{\n        code: string\n        errors: Array<{ type: ErrorCodes; loc: Position }>\n        options?: Partial<ParserOptions>\n      }>\n    } = {\n      // ABRUPT_CLOSING_OF_EMPTY_COMMENT: [\n      //   {\n      //     code: '<template><!--></template>',\n      //     errors: [\n      //       {\n      //         type: ErrorCodes.ABRUPT_CLOSING_OF_EMPTY_COMMENT,\n      //         loc: { offset: 10, line: 1, column: 11 }\n      //       }\n      //     ]\n      //   },\n      //   {\n      //     code: '<template><!---></template>',\n      //     errors: [\n      //       {\n      //         type: ErrorCodes.ABRUPT_CLOSING_OF_EMPTY_COMMENT,\n      //         loc: { offset: 10, line: 1, column: 11 }\n      //       }\n      //     ]\n      //   },\n      //   {\n      //     code: '<template><!----></template>',\n      //     errors: []\n      //   }\n      // ],\n      CDATA_IN_HTML_CONTENT: [\n        {\n          code: '<template><![CDATA[cdata]]></template>',\n          errors: [\n            {\n              type: ErrorCodes.CDATA_IN_HTML_CONTENT,\n              loc: { offset: 10, line: 1, column: 11 },\n            },\n          ],\n        },\n        {\n          code: '<template><svg><![CDATA[cdata]]></svg></template>',\n          errors: [],\n        },\n      ],\n      DUPLICATE_ATTRIBUTE: [\n        {\n          code: '<template><div id=\"\" id=\"\"></div></template>',\n          errors: [\n            {\n              type: ErrorCodes.DUPLICATE_ATTRIBUTE,\n              loc: { offset: 21, line: 1, column: 22 },\n            },\n          ],\n        },\n      ],\n      // END_TAG_WITH_ATTRIBUTES: [\n      //   {\n      //     code: '<template><div></div id=\"\"></template>',\n      //     errors: [\n      //       {\n      //         type: ErrorCodes.END_TAG_WITH_ATTRIBUTES,\n      //         loc: { offset: 21, line: 1, column: 22 }\n      //       }\n      //     ]\n      //   }\n      // ],\n      // END_TAG_WITH_TRAILING_SOLIDUS: [\n      //   {\n      //     code: '<template><div></div/></template>',\n      //     errors: [\n      //       {\n      //         type: ErrorCodes.END_TAG_WITH_TRAILING_SOLIDUS,\n      //         loc: { offset: 20, line: 1, column: 21 }\n      //       }\n      //     ]\n      //   }\n      // ],\n      EOF_BEFORE_TAG_NAME: [\n        {\n          code: '<template><',\n          errors: [\n            {\n              type: ErrorCodes.EOF_BEFORE_TAG_NAME,\n              loc: { offset: 11, line: 1, column: 12 },\n            },\n            {\n              type: ErrorCodes.X_MISSING_END_TAG,\n              loc: { offset: 0, line: 1, column: 1 },\n            },\n          ],\n        },\n        {\n          code: '<template></',\n          errors: [\n            {\n              type: ErrorCodes.EOF_BEFORE_TAG_NAME,\n              loc: { offset: 12, line: 1, column: 13 },\n            },\n            {\n              type: ErrorCodes.X_MISSING_END_TAG,\n              loc: { offset: 0, line: 1, column: 1 },\n            },\n          ],\n        },\n      ],\n      EOF_IN_CDATA: [\n        {\n          code: '<template><svg><![CDATA[cdata',\n          errors: [\n            {\n              type: ErrorCodes.EOF_IN_CDATA,\n              loc: { offset: 29, line: 1, column: 30 },\n            },\n            {\n              type: ErrorCodes.X_MISSING_END_TAG,\n              loc: { offset: 10, line: 1, column: 11 },\n            },\n            {\n              type: ErrorCodes.X_MISSING_END_TAG,\n              loc: { offset: 0, line: 1, column: 1 },\n            },\n          ],\n        },\n        {\n          code: '<template><svg><![CDATA[',\n          errors: [\n            {\n              type: ErrorCodes.EOF_IN_CDATA,\n              loc: { offset: 24, line: 1, column: 25 },\n            },\n            {\n              type: ErrorCodes.X_MISSING_END_TAG,\n              loc: { offset: 10, line: 1, column: 11 },\n            },\n            {\n              type: ErrorCodes.X_MISSING_END_TAG,\n              loc: { offset: 0, line: 1, column: 1 },\n            },\n          ],\n        },\n      ],\n      EOF_IN_COMMENT: [\n        {\n          code: '<template><!--comment',\n          errors: [\n            {\n              type: ErrorCodes.EOF_IN_COMMENT,\n              loc: { offset: 21, line: 1, column: 22 },\n            },\n            {\n              type: ErrorCodes.X_MISSING_END_TAG,\n              loc: { offset: 0, line: 1, column: 1 },\n            },\n          ],\n        },\n        {\n          code: '<template><!--',\n          errors: [\n            {\n              type: ErrorCodes.EOF_IN_COMMENT,\n              loc: { offset: 14, line: 1, column: 15 },\n            },\n            {\n              type: ErrorCodes.X_MISSING_END_TAG,\n              loc: { offset: 0, line: 1, column: 1 },\n            },\n          ],\n        },\n        // // Bogus comments don't throw eof-in-comment error.\n        // // https://html.spec.whatwg.org/multipage/parsing.html#bogus-comment-state\n        // {\n        //   code: '<template><!',\n        //   errors: [\n        //     {\n        //       type: ErrorCodes.INCORRECTLY_OPENED_COMMENT,\n        //       loc: { offset: 10, line: 1, column: 11 }\n        //     },\n        //     {\n        //       type: ErrorCodes.X_MISSING_END_TAG,\n        //       loc: { offset: 0, line: 1, column: 1 }\n        //     }\n        //   ]\n        // },\n        // {\n        //   code: '<template><!-',\n        //   errors: [\n        //     {\n        //       type: ErrorCodes.INCORRECTLY_OPENED_COMMENT,\n        //       loc: { offset: 10, line: 1, column: 11 }\n        //     },\n        //     {\n        //       type: ErrorCodes.X_MISSING_END_TAG,\n        //       loc: { offset: 0, line: 1, column: 1 }\n        //     }\n        //   ]\n        // },\n        // {\n        //   code: '<template><!abc',\n        //   errors: [\n        //     {\n        //       type: ErrorCodes.INCORRECTLY_OPENED_COMMENT,\n        //       loc: { offset: 10, line: 1, column: 11 }\n        //     },\n        //     {\n        //       type: ErrorCodes.X_MISSING_END_TAG,\n        //       loc: { offset: 0, line: 1, column: 1 }\n        //     }\n        //   ]\n        // }\n      ],\n      // EOF_IN_SCRIPT_HTML_COMMENT_LIKE_TEXT: [\n      //   {\n      //     code: \"<script><!--console.log('hello')\",\n      //     errors: [\n      //       {\n      //         type: ErrorCodes.X_MISSING_END_TAG,\n      //         loc: { offset: 0, line: 1, column: 1 }\n      //       },\n      //       {\n      //         type: ErrorCodes.EOF_IN_SCRIPT_HTML_COMMENT_LIKE_TEXT,\n      //         loc: { offset: 32, line: 1, column: 33 }\n      //       }\n      //     ]\n      //   },\n      //   {\n      //     code: \"<script>console.log('hello')\",\n      //     errors: [\n      //       {\n      //         type: ErrorCodes.X_MISSING_END_TAG,\n      //         loc: { offset: 0, line: 1, column: 1 }\n      //       }\n      //     ]\n      //   }\n      // ],\n      EOF_IN_TAG: [\n        {\n          code: '<template><div',\n          errors: [\n            {\n              type: ErrorCodes.EOF_IN_TAG,\n              loc: { offset: 14, line: 1, column: 15 },\n            },\n            {\n              type: ErrorCodes.X_MISSING_END_TAG,\n              loc: { offset: 0, line: 1, column: 1 },\n            },\n          ],\n        },\n        {\n          code: '<template><div ',\n          errors: [\n            {\n              type: ErrorCodes.EOF_IN_TAG,\n              loc: { offset: 15, line: 1, column: 16 },\n            },\n            {\n              type: ErrorCodes.X_MISSING_END_TAG,\n              loc: { offset: 0, line: 1, column: 1 },\n            },\n          ],\n        },\n        {\n          code: '<template><div id',\n          errors: [\n            {\n              type: ErrorCodes.EOF_IN_TAG,\n              loc: { offset: 17, line: 1, column: 18 },\n            },\n            {\n              type: ErrorCodes.X_MISSING_END_TAG,\n              loc: { offset: 0, line: 1, column: 1 },\n            },\n          ],\n        },\n        {\n          code: '<template><div id ',\n          errors: [\n            {\n              type: ErrorCodes.EOF_IN_TAG,\n              loc: { offset: 18, line: 1, column: 19 },\n            },\n            {\n              type: ErrorCodes.X_MISSING_END_TAG,\n              loc: { offset: 0, line: 1, column: 1 },\n            },\n          ],\n        },\n        {\n          code: '<template><div id =',\n          errors: [\n            // {\n            //   type: ErrorCodes.MISSING_ATTRIBUTE_VALUE,\n            //   loc: { offset: 19, line: 1, column: 20 }\n            // },\n            {\n              type: ErrorCodes.EOF_IN_TAG,\n              loc: { offset: 19, line: 1, column: 20 },\n            },\n            {\n              type: ErrorCodes.X_MISSING_END_TAG,\n              loc: { offset: 0, line: 1, column: 1 },\n            },\n          ],\n        },\n        {\n          code: \"<template><div id='abc\",\n          errors: [\n            {\n              type: ErrorCodes.EOF_IN_TAG,\n              loc: { offset: 22, line: 1, column: 23 },\n            },\n            {\n              type: ErrorCodes.X_MISSING_END_TAG,\n              loc: { offset: 0, line: 1, column: 1 },\n            },\n          ],\n        },\n        {\n          code: '<template><div id=\"abc',\n          errors: [\n            {\n              type: ErrorCodes.EOF_IN_TAG,\n              loc: { offset: 22, line: 1, column: 23 },\n            },\n            {\n              type: ErrorCodes.X_MISSING_END_TAG,\n              loc: { offset: 0, line: 1, column: 1 },\n            },\n          ],\n        },\n        {\n          code: \"<template><div id='abc'\",\n          errors: [\n            {\n              type: ErrorCodes.EOF_IN_TAG,\n              loc: { offset: 23, line: 1, column: 24 },\n            },\n            {\n              type: ErrorCodes.X_MISSING_END_TAG,\n              loc: { offset: 0, line: 1, column: 1 },\n            },\n          ],\n        },\n        {\n          code: '<template><div id=\"abc\"',\n          errors: [\n            {\n              type: ErrorCodes.EOF_IN_TAG,\n              loc: { offset: 23, line: 1, column: 24 },\n            },\n            {\n              type: ErrorCodes.X_MISSING_END_TAG,\n              loc: { offset: 0, line: 1, column: 1 },\n            },\n          ],\n        },\n        {\n          code: '<template><div id=abc',\n          errors: [\n            {\n              type: ErrorCodes.EOF_IN_TAG,\n              loc: { offset: 21, line: 1, column: 22 },\n            },\n            {\n              type: ErrorCodes.X_MISSING_END_TAG,\n              loc: { offset: 0, line: 1, column: 1 },\n            },\n          ],\n        },\n        {\n          code: \"<template><div id='abc'/\",\n          errors: [\n            {\n              type: ErrorCodes.UNEXPECTED_SOLIDUS_IN_TAG,\n              loc: { offset: 23, line: 1, column: 24 },\n            },\n            {\n              type: ErrorCodes.EOF_IN_TAG,\n              loc: { offset: 24, line: 1, column: 25 },\n            },\n            {\n              type: ErrorCodes.X_MISSING_END_TAG,\n              loc: { offset: 0, line: 1, column: 1 },\n            },\n          ],\n        },\n        {\n          code: '<template><div id=\"abc\"/',\n          errors: [\n            {\n              type: ErrorCodes.UNEXPECTED_SOLIDUS_IN_TAG,\n              loc: { offset: 23, line: 1, column: 24 },\n            },\n            {\n              type: ErrorCodes.EOF_IN_TAG,\n              loc: { offset: 24, line: 1, column: 25 },\n            },\n            {\n              type: ErrorCodes.X_MISSING_END_TAG,\n              loc: { offset: 0, line: 1, column: 1 },\n            },\n          ],\n        },\n        {\n          code: '<template><div id=abc /',\n          errors: [\n            {\n              type: ErrorCodes.UNEXPECTED_SOLIDUS_IN_TAG,\n              loc: { offset: 22, line: 1, column: 23 },\n            },\n            {\n              type: ErrorCodes.EOF_IN_TAG,\n              loc: { offset: 23, line: 1, column: 24 },\n            },\n            {\n              type: ErrorCodes.X_MISSING_END_TAG,\n              loc: { offset: 0, line: 1, column: 1 },\n            },\n          ],\n        },\n        {\n          code: '<div></div',\n          errors: [\n            {\n              type: ErrorCodes.EOF_IN_TAG,\n              loc: { offset: 10, line: 1, column: 11 },\n            },\n            {\n              type: ErrorCodes.X_MISSING_END_TAG,\n              loc: { offset: 0, line: 1, column: 1 },\n            },\n          ],\n        },\n      ],\n      // INCORRECTLY_CLOSED_COMMENT: [\n      //   {\n      //     code: '<template><!--comment--!></template>',\n      //     errors: [\n      //       {\n      //         type: ErrorCodes.INCORRECTLY_CLOSED_COMMENT,\n      //         loc: { offset: 10, line: 1, column: 11 }\n      //       }\n      //     ]\n      //   }\n      // ],\n      // INCORRECTLY_OPENED_COMMENT: [\n      //   {\n      //     code: '<template><!></template>',\n      //     errors: [\n      //       {\n      //         type: ErrorCodes.INCORRECTLY_OPENED_COMMENT,\n      //         loc: { offset: 10, line: 1, column: 11 }\n      //       }\n      //     ]\n      //   },\n      //   {\n      //     code: '<template><!-></template>',\n      //     errors: [\n      //       {\n      //         type: ErrorCodes.INCORRECTLY_OPENED_COMMENT,\n      //         loc: { offset: 10, line: 1, column: 11 }\n      //       }\n      //     ]\n      //   },\n      //   {\n      //     code: '<template><!ELEMENT br EMPTY></template>',\n      //     errors: [\n      //       {\n      //         type: ErrorCodes.INCORRECTLY_OPENED_COMMENT,\n      //         loc: { offset: 10, line: 1, column: 11 }\n      //       }\n      //     ]\n      //   },\n      //   // Just ignore doctype.\n      //   {\n      //     code: '<!DOCTYPE html>',\n      //     errors: []\n      //   }\n      // ],\n      // INVALID_FIRST_CHARACTER_OF_TAG_NAME: [\n      //   {\n      //     code: '<template>a < b</template>',\n      //     errors: [\n      //       {\n      //         type: ErrorCodes.INVALID_FIRST_CHARACTER_OF_TAG_NAME,\n      //         loc: { offset: 13, line: 1, column: 14 }\n      //       }\n      //     ]\n      //   },\n      //   {\n      //     code: '<template><�></template>',\n      //     errors: [\n      //       {\n      //         type: ErrorCodes.INVALID_FIRST_CHARACTER_OF_TAG_NAME,\n      //         loc: { offset: 11, line: 1, column: 12 }\n      //       }\n      //     ]\n      //   },\n      //   {\n      //     code: '<template>a </ b</template>',\n      //     errors: [\n      //       {\n      //         type: ErrorCodes.INVALID_FIRST_CHARACTER_OF_TAG_NAME,\n      //         loc: { offset: 14, line: 1, column: 15 }\n      //       },\n      //       {\n      //         type: ErrorCodes.X_MISSING_END_TAG,\n      //         loc: { offset: 0, line: 1, column: 1 }\n      //       }\n      //     ]\n      //   },\n      //   {\n      //     code: '<template></�></template>',\n      //     errors: [\n      //       {\n      //         type: ErrorCodes.INVALID_FIRST_CHARACTER_OF_TAG_NAME,\n      //         loc: { offset: 12, line: 1, column: 13 }\n      //       }\n      //     ]\n      //   },\n      //   // Don't throw invalid-first-character-of-tag-name in interpolation\n      //   {\n      //     code: '<template>{{a < b}}</template>',\n      //     errors: []\n      //   }\n      // ],\n      MISSING_ATTRIBUTE_VALUE: [\n        {\n          code: '<template><div id=></div></template>',\n          errors: [\n            {\n              type: ErrorCodes.MISSING_ATTRIBUTE_VALUE,\n              loc: { offset: 18, line: 1, column: 19 },\n            },\n          ],\n        },\n        {\n          code: '<template><div id= ></div></template>',\n          errors: [\n            {\n              type: ErrorCodes.MISSING_ATTRIBUTE_VALUE,\n              loc: { offset: 19, line: 1, column: 20 },\n            },\n          ],\n        },\n        {\n          code: '<template><div id= /></div></template>',\n          errors: [],\n        },\n      ],\n      MISSING_END_TAG_NAME: [\n        {\n          code: '<template></></template>',\n          errors: [\n            {\n              type: ErrorCodes.MISSING_END_TAG_NAME,\n              loc: { offset: 12, line: 1, column: 13 },\n            },\n          ],\n        },\n      ],\n      // MISSING_WHITESPACE_BETWEEN_ATTRIBUTES: [\n      //   {\n      //     code: '<template><div id=\"foo\"class=\"bar\"></div></template>',\n      //     errors: [\n      //       {\n      //         type: ErrorCodes.MISSING_WHITESPACE_BETWEEN_ATTRIBUTES,\n      //         loc: { offset: 23, line: 1, column: 24 }\n      //       }\n      //     ]\n      //   },\n      //   // CR doesn't appear in tokenization phase, but all CR are removed in preprocessing.\n      //   // https://html.spec.whatwg.org/multipage/parsing.html#preprocessing-the-input-stream\n      //   {\n      //     code: '<template><div id=\"foo\"\\r\\nclass=\"bar\"></div></template>',\n      //     errors: []\n      //   }\n      // ],\n      // NESTED_COMMENT: [\n      //   {\n      //     code: '<template><!--a<!--b--></template>',\n      //     errors: [\n      //       {\n      //         type: ErrorCodes.NESTED_COMMENT,\n      //         loc: { offset: 15, line: 1, column: 16 }\n      //       }\n      //     ]\n      //   },\n      //   {\n      //     code: '<template><!--a<!--b<!--c--></template>',\n      //     errors: [\n      //       {\n      //         type: ErrorCodes.NESTED_COMMENT,\n      //         loc: { offset: 15, line: 1, column: 16 }\n      //       },\n      //       {\n      //         type: ErrorCodes.NESTED_COMMENT,\n      //         loc: { offset: 20, line: 1, column: 21 }\n      //       }\n      //     ]\n      //   },\n      //   {\n      //     code: '<template><!--a<!--b<!----></template>',\n      //     errors: [\n      //       {\n      //         type: ErrorCodes.NESTED_COMMENT,\n      //         loc: { offset: 15, line: 1, column: 16 }\n      //       }\n      //     ]\n      //   },\n      //   {\n      //     code: '<template><!--a<!--></template>',\n      //     errors: []\n      //   },\n      //   {\n      //     code: '<template><!--a<!--',\n      //     errors: [\n      //       {\n      //         type: ErrorCodes.EOF_IN_COMMENT,\n      //         loc: { offset: 19, line: 1, column: 20 }\n      //       },\n      //       {\n      //         type: ErrorCodes.X_MISSING_END_TAG,\n      //         loc: { offset: 0, line: 1, column: 1 }\n      //       }\n      //     ]\n      //   }\n      // ],\n      UNEXPECTED_CHARACTER_IN_ATTRIBUTE_NAME: [\n        {\n          code: \"<template><div a\\\"bc=''></div></template>\",\n          errors: [\n            {\n              type: ErrorCodes.UNEXPECTED_CHARACTER_IN_ATTRIBUTE_NAME,\n              loc: { offset: 16, line: 1, column: 17 },\n            },\n          ],\n        },\n        {\n          code: \"<template><div a'bc=''></div></template>\",\n          errors: [\n            {\n              type: ErrorCodes.UNEXPECTED_CHARACTER_IN_ATTRIBUTE_NAME,\n              loc: { offset: 16, line: 1, column: 17 },\n            },\n          ],\n        },\n        {\n          code: \"<template><div a<bc=''></div></template>\",\n          errors: [\n            {\n              type: ErrorCodes.UNEXPECTED_CHARACTER_IN_ATTRIBUTE_NAME,\n              loc: { offset: 16, line: 1, column: 17 },\n            },\n          ],\n        },\n      ],\n      UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_VALUE: [\n        {\n          code: '<template><div foo=bar\"></div></template>',\n          errors: [\n            {\n              type: ErrorCodes.UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_VALUE,\n              loc: { offset: 22, line: 1, column: 23 },\n            },\n          ],\n        },\n        {\n          code: \"<template><div foo=bar'></div></template>\",\n          errors: [\n            {\n              type: ErrorCodes.UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_VALUE,\n              loc: { offset: 22, line: 1, column: 23 },\n            },\n          ],\n        },\n        {\n          code: '<template><div foo=bar<div></div></template>',\n          errors: [\n            {\n              type: ErrorCodes.UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_VALUE,\n              loc: { offset: 22, line: 1, column: 23 },\n            },\n          ],\n        },\n        {\n          code: '<template><div foo=bar=baz></div></template>',\n          errors: [\n            {\n              type: ErrorCodes.UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_VALUE,\n              loc: { offset: 22, line: 1, column: 23 },\n            },\n          ],\n        },\n        {\n          code: '<template><div foo=bar`></div></template>',\n          errors: [\n            {\n              type: ErrorCodes.UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_VALUE,\n              loc: { offset: 22, line: 1, column: 23 },\n            },\n          ],\n        },\n      ],\n      UNEXPECTED_EQUALS_SIGN_BEFORE_ATTRIBUTE_NAME: [\n        {\n          code: '<template><div =foo=bar></div></template>',\n          errors: [\n            {\n              type: ErrorCodes.UNEXPECTED_EQUALS_SIGN_BEFORE_ATTRIBUTE_NAME,\n              loc: { offset: 15, line: 1, column: 16 },\n            },\n          ],\n        },\n        {\n          code: '<template><div =></div></template>',\n          errors: [\n            {\n              type: ErrorCodes.UNEXPECTED_EQUALS_SIGN_BEFORE_ATTRIBUTE_NAME,\n              loc: { offset: 15, line: 1, column: 16 },\n            },\n          ],\n        },\n      ],\n      UNEXPECTED_QUESTION_MARK_INSTEAD_OF_TAG_NAME: [\n        {\n          code: '<template><?xml?></template>',\n          errors: [\n            {\n              type: ErrorCodes.UNEXPECTED_QUESTION_MARK_INSTEAD_OF_TAG_NAME,\n              loc: { offset: 11, line: 1, column: 12 },\n            },\n          ],\n        },\n      ],\n      UNEXPECTED_SOLIDUS_IN_TAG: [\n        {\n          code: '<template><div a/b></div></template>',\n          errors: [\n            {\n              type: ErrorCodes.UNEXPECTED_SOLIDUS_IN_TAG,\n              loc: { offset: 16, line: 1, column: 17 },\n            },\n          ],\n        },\n      ],\n      X_INVALID_END_TAG: [\n        {\n          code: '<template></div></template>',\n          errors: [\n            {\n              type: ErrorCodes.X_INVALID_END_TAG,\n              loc: { offset: 10, line: 1, column: 11 },\n            },\n          ],\n        },\n        {\n          code: '<template></div></div></template>',\n          errors: [\n            {\n              type: ErrorCodes.X_INVALID_END_TAG,\n              loc: { offset: 10, line: 1, column: 11 },\n            },\n            {\n              type: ErrorCodes.X_INVALID_END_TAG,\n              loc: { offset: 16, line: 1, column: 17 },\n            },\n          ],\n        },\n        {\n          code: '<template>a </ b</template>',\n          errors: [\n            {\n              type: ErrorCodes.X_INVALID_END_TAG,\n              loc: { offset: 12, line: 1, column: 13 },\n            },\n            {\n              type: ErrorCodes.X_MISSING_END_TAG,\n              loc: { offset: 0, line: 1, column: 1 },\n            },\n          ],\n        },\n        {\n          code: \"<template>{{'</div>'}}</template>\",\n          errors: [],\n        },\n        {\n          code: '<textarea></div></textarea>',\n          errors: [],\n        },\n        {\n          code: '<svg><![CDATA[</div>]]></svg>',\n          errors: [],\n        },\n        {\n          code: '<svg><!--</div>--></svg>',\n          errors: [],\n        },\n      ],\n      X_MISSING_END_TAG: [\n        {\n          code: '<template><div></template>',\n          errors: [\n            {\n              type: ErrorCodes.X_MISSING_END_TAG,\n              loc: { offset: 10, line: 1, column: 11 },\n            },\n          ],\n        },\n        {\n          code: '<template><div>',\n          errors: [\n            {\n              type: ErrorCodes.X_MISSING_END_TAG,\n              loc: { offset: 10, line: 1, column: 11 },\n            },\n            {\n              type: ErrorCodes.X_MISSING_END_TAG,\n              loc: { offset: 0, line: 1, column: 1 },\n            },\n          ],\n        },\n      ],\n      X_MISSING_INTERPOLATION_END: [\n        {\n          code: '{{ foo',\n          errors: [\n            {\n              type: ErrorCodes.X_MISSING_INTERPOLATION_END,\n              loc: { offset: 0, line: 1, column: 1 },\n            },\n          ],\n        },\n        {\n          code: '{{',\n          errors: [\n            {\n              type: ErrorCodes.X_MISSING_INTERPOLATION_END,\n              loc: { offset: 0, line: 1, column: 1 },\n            },\n          ],\n        },\n        {\n          code: '<div>{{ foo</div>',\n          errors: [\n            {\n              type: ErrorCodes.X_MISSING_INTERPOLATION_END,\n              loc: { offset: 5, line: 1, column: 6 },\n            },\n            {\n              type: ErrorCodes.X_MISSING_END_TAG,\n              loc: { offset: 0, line: 1, column: 1 },\n            },\n          ],\n        },\n        {\n          code: '{{}}',\n          errors: [],\n        },\n      ],\n      X_MISSING_DYNAMIC_DIRECTIVE_ARGUMENT_END: [\n        {\n          code: `<div v-foo:[sef fsef] />`,\n          errors: [\n            {\n              type: ErrorCodes.X_MISSING_DYNAMIC_DIRECTIVE_ARGUMENT_END,\n              loc: { offset: 15, line: 1, column: 16 },\n            },\n          ],\n        },\n      ],\n    }\n\n    for (const key of Object.keys(patterns)) {\n      describe(key, () => {\n        for (const { code, errors, options } of patterns[key]) {\n          test(\n            code.replace(\n              /[\\r\\n]/g,\n              c => `\\\\x0${c.codePointAt(0)!.toString(16)};`,\n            ),\n            () => {\n              const spy = vi.fn()\n              const ast = baseParse(code, {\n                parseMode: 'html',\n                getNamespace: tag =>\n                  tag === 'svg' ? Namespaces.SVG : Namespaces.HTML,\n                ...options,\n                onError: spy,\n              })\n\n              expect(\n                spy.mock.calls.map(([err]) => ({\n                  type: err.code,\n                  loc: err.loc.start,\n                })),\n              ).toMatchObject(errors)\n              expect(ast).toMatchSnapshot()\n            },\n          )\n        }\n      })\n    }\n  })\n})\n"
  },
  {
    "path": "packages/compiler-core/__tests__/scopeId.spec.ts",
    "content": "import { baseCompile } from '../src/compile'\n\n/**\n * Ensure all slot functions are wrapped with _withCtx\n * which sets the currentRenderingInstance and currentScopeId when rendering\n * the slot.\n */\ndescribe('scopeId compiler support', () => {\n  test('should only work in module mode', () => {\n    expect(() => {\n      baseCompile(``, { scopeId: 'test' })\n    }).toThrow(`\"scopeId\" option is only supported in module mode`)\n  })\n\n  test('should wrap default slot', () => {\n    const { code } = baseCompile(`<Child><div/></Child>`, {\n      mode: 'module',\n      scopeId: 'test',\n    })\n    expect(code).toMatch(`default: _withCtx(() => [`)\n    expect(code).toMatchSnapshot()\n  })\n\n  test('should wrap named slots', () => {\n    const { code } = baseCompile(\n      `<Child>\n        <template #foo=\"{ msg }\">{{ msg }}</template>\n        <template #bar><div/></template>\n      </Child>\n      `,\n      {\n        mode: 'module',\n        scopeId: 'test',\n      },\n    )\n    expect(code).toMatch(`foo: _withCtx(({ msg }) => [`)\n    expect(code).toMatch(`bar: _withCtx(() => [`)\n    expect(code).toMatchSnapshot()\n  })\n\n  test('should wrap dynamic slots', () => {\n    const { code } = baseCompile(\n      `<Child>\n        <template #foo v-if=\"ok\"><div/></template>\n        <template v-for=\"i in list\" #[i]><div/></template>\n      </Child>\n      `,\n      {\n        mode: 'module',\n        scopeId: 'test',\n      },\n    )\n    expect(code).toMatch(/name: \"foo\",\\s+fn: _withCtx\\(/)\n    expect(code).toMatch(/name: i,\\s+fn: _withCtx\\(/)\n    expect(code).toMatchSnapshot()\n  })\n})\n"
  },
  {
    "path": "packages/compiler-core/__tests__/testUtils.ts",
    "content": "import {\n  type ElementNode,\n  ElementTypes,\n  Namespaces,\n  NodeTypes,\n  type Property,\n  type SimpleExpressionNode,\n  type VNodeCall,\n  locStub,\n} from '../src'\nimport {\n  PatchFlagNames,\n  type PatchFlags,\n  type ShapeFlags,\n  isArray,\n  isString,\n} from '@vue/shared'\n\nconst leadingBracketRE = /^\\[/\nconst bracketsRE = /^\\[|\\]$/g\n\n// Create a matcher for an object\n// where non-static expressions should be wrapped in []\n// e.g.\n// - createObjectMatcher({ 'foo': '[bar]' }) matches { foo: bar }\n// - createObjectMatcher({ '[foo]': 'bar' }) matches { [foo]: \"bar\" }\nexport function createObjectMatcher(obj: Record<string, any>): {\n  type: NodeTypes\n  properties: Partial<Property>[]\n} {\n  return {\n    type: NodeTypes.JS_OBJECT_EXPRESSION,\n    properties: Object.keys(obj).map(key => ({\n      type: NodeTypes.JS_PROPERTY,\n      key: {\n        type: NodeTypes.SIMPLE_EXPRESSION,\n        content: key.replace(bracketsRE, ''),\n        isStatic: !leadingBracketRE.test(key),\n      } as SimpleExpressionNode,\n      value: isString(obj[key])\n        ? {\n            type: NodeTypes.SIMPLE_EXPRESSION,\n            content: obj[key].replace(bracketsRE, ''),\n            isStatic: !leadingBracketRE.test(obj[key]),\n          }\n        : obj[key],\n    })),\n  }\n}\n\nexport function createElementWithCodegen(\n  tag: VNodeCall['tag'],\n  props?: VNodeCall['props'],\n  children?: VNodeCall['children'],\n  patchFlag?: VNodeCall['patchFlag'],\n  dynamicProps?: VNodeCall['dynamicProps'],\n): ElementNode {\n  return {\n    type: NodeTypes.ELEMENT,\n    loc: locStub,\n    ns: Namespaces.HTML,\n    tag: 'div',\n    tagType: ElementTypes.ELEMENT,\n    props: [],\n    children: [],\n    codegenNode: {\n      type: NodeTypes.VNODE_CALL,\n      tag,\n      props,\n      children,\n      patchFlag,\n      dynamicProps,\n      directives: undefined,\n      isBlock: false,\n      disableTracking: false,\n      isComponent: false,\n      loc: locStub,\n    },\n  }\n}\n\ntype Flags = PatchFlags | ShapeFlags\nexport function genFlagText(\n  flag: Flags | Flags[],\n  names: { [k: number]: string } = PatchFlagNames,\n): string {\n  if (isArray(flag)) {\n    let f = 0\n    flag.forEach(ff => {\n      f |= ff\n    })\n    return `${f} /* ${flag.map(f => names[f]).join(', ')} */`\n  } else {\n    return `${flag} /* ${names[flag]} */`\n  }\n}\n"
  },
  {
    "path": "packages/compiler-core/__tests__/transform.spec.ts",
    "content": "import { baseParse } from '../src/parser'\nimport { type NodeTransform, transform } from '../src/transform'\nimport {\n  type DirectiveNode,\n  type ElementNode,\n  type ExpressionNode,\n  NodeTypes,\n  type VNodeCall,\n} from '../src/ast'\nimport { ErrorCodes, createCompilerError } from '../src/errors'\nimport {\n  CREATE_COMMENT,\n  FRAGMENT,\n  RENDER_SLOT,\n  TO_DISPLAY_STRING,\n} from '../src/runtimeHelpers'\nimport { transformIf } from '../src/transforms/vIf'\nimport { transformFor } from '../src/transforms/vFor'\nimport { transformElement } from '../src/transforms/transformElement'\nimport { transformSlotOutlet } from '../src/transforms/transformSlotOutlet'\nimport { transformText } from '../src/transforms/transformText'\nimport { PatchFlags } from '@vue/shared'\n\ndescribe('compiler: transform', () => {\n  test('context state', () => {\n    const ast = baseParse(`<div>hello {{ world }}</div>`)\n\n    // manually store call arguments because context is mutable and shared\n    // across calls\n    const calls: any[] = []\n    const plugin: NodeTransform = (node, context) => {\n      calls.push([node, { ...context }])\n    }\n\n    transform(ast, {\n      nodeTransforms: [plugin],\n    })\n\n    const div = ast.children[0] as ElementNode\n    expect(calls.length).toBe(4)\n    expect(calls[0]).toMatchObject([\n      ast,\n      {\n        parent: null,\n        currentNode: ast,\n      },\n    ])\n    expect(calls[1]).toMatchObject([\n      div,\n      {\n        parent: ast,\n        currentNode: div,\n      },\n    ])\n    expect(calls[2]).toMatchObject([\n      div.children[0],\n      {\n        parent: div,\n        currentNode: div.children[0],\n      },\n    ])\n    expect(calls[3]).toMatchObject([\n      div.children[1],\n      {\n        parent: div,\n        currentNode: div.children[1],\n      },\n    ])\n  })\n\n  test('context.replaceNode', () => {\n    const ast = baseParse(`<div/><span/>`)\n    const plugin: NodeTransform = (node, context) => {\n      if (node.type === NodeTypes.ELEMENT && node.tag === 'div') {\n        // change the node to <p>\n        context.replaceNode(\n          Object.assign({}, node, {\n            tag: 'p',\n            children: [\n              {\n                type: NodeTypes.TEXT,\n                content: 'hello',\n                isEmpty: false,\n              },\n            ],\n          }),\n        )\n      }\n    }\n    const spy = vi.fn(plugin)\n    transform(ast, {\n      nodeTransforms: [spy],\n    })\n\n    expect(ast.children.length).toBe(2)\n    const newElement = ast.children[0] as ElementNode\n    expect(newElement.tag).toBe('p')\n    expect(spy).toHaveBeenCalledTimes(4)\n    // should traverse the children of replaced node\n    expect(spy.mock.calls[2][0]).toBe(newElement.children[0])\n    // should traverse the node after the replaced node\n    expect(spy.mock.calls[3][0]).toBe(ast.children[1])\n  })\n\n  test('context.removeNode', () => {\n    const ast = baseParse(`<span/><div>hello</div><span/>`)\n    const c1 = ast.children[0]\n    const c2 = ast.children[2]\n\n    const plugin: NodeTransform = (node, context) => {\n      if (node.type === NodeTypes.ELEMENT && node.tag === 'div') {\n        context.removeNode()\n      }\n    }\n    const spy = vi.fn(plugin)\n    transform(ast, {\n      nodeTransforms: [spy],\n    })\n\n    expect(ast.children.length).toBe(2)\n    expect(ast.children[0]).toBe(c1)\n    expect(ast.children[1]).toBe(c2)\n\n    // should not traverse children of remove node\n    expect(spy).toHaveBeenCalledTimes(4)\n    // should traverse nodes around removed\n    expect(spy.mock.calls[1][0]).toBe(c1)\n    expect(spy.mock.calls[3][0]).toBe(c2)\n  })\n\n  test('context.removeNode (prev sibling)', () => {\n    const ast = baseParse(`<span/><div/><span/>`)\n    const c1 = ast.children[0]\n    const c2 = ast.children[2]\n\n    const plugin: NodeTransform = (node, context) => {\n      if (node.type === NodeTypes.ELEMENT && node.tag === 'div') {\n        context.removeNode()\n        // remove previous sibling\n        context.removeNode(context.parent!.children[0])\n      }\n    }\n    const spy = vi.fn(plugin)\n    transform(ast, {\n      nodeTransforms: [spy],\n    })\n\n    expect(ast.children.length).toBe(1)\n    expect(ast.children[0]).toBe(c2)\n\n    expect(spy).toHaveBeenCalledTimes(4)\n    // should still traverse first span before removal\n    expect(spy.mock.calls[1][0]).toBe(c1)\n    // should still traverse last span\n    expect(spy.mock.calls[3][0]).toBe(c2)\n  })\n\n  test('context.removeNode (next sibling)', () => {\n    const ast = baseParse(`<span/><div/><span/>`)\n    const c1 = ast.children[0]\n    const d1 = ast.children[1]\n\n    const plugin: NodeTransform = (node, context) => {\n      if (node.type === NodeTypes.ELEMENT && node.tag === 'div') {\n        context.removeNode()\n        // remove next sibling\n        context.removeNode(context.parent!.children[1])\n      }\n    }\n    const spy = vi.fn(plugin)\n    transform(ast, {\n      nodeTransforms: [spy],\n    })\n\n    expect(ast.children.length).toBe(1)\n    expect(ast.children[0]).toBe(c1)\n\n    expect(spy).toHaveBeenCalledTimes(3)\n    // should still traverse first span before removal\n    expect(spy.mock.calls[1][0]).toBe(c1)\n    // should not traverse last span\n    expect(spy.mock.calls[2][0]).toBe(d1)\n  })\n\n  test('context.hoist', () => {\n    const ast = baseParse(`<div :id=\"foo\"/><div :id=\"bar\"/>`)\n    const hoisted: ExpressionNode[] = []\n    const mock: NodeTransform = (node, context) => {\n      if (node.type === NodeTypes.ELEMENT) {\n        const dir = node.props[0] as DirectiveNode\n        hoisted.push(dir.exp!)\n        dir.exp = context.hoist(dir.exp!)\n      }\n    }\n    transform(ast, {\n      nodeTransforms: [mock],\n    })\n    expect(ast.hoists).toMatchObject(hoisted)\n    expect((ast as any).children[0].props[0].exp.content).toBe(`_hoisted_1`)\n    expect((ast as any).children[1].props[0].exp.content).toBe(`_hoisted_2`)\n  })\n\n  test('context.filename and selfName', () => {\n    const ast = baseParse(`<div />`)\n\n    const calls: any[] = []\n    const plugin: NodeTransform = (node, context) => {\n      calls.push({ ...context })\n    }\n\n    transform(ast, {\n      filename: '/the/fileName.vue',\n      nodeTransforms: [plugin],\n    })\n\n    expect(calls.length).toBe(2)\n    expect(calls[1]).toMatchObject({\n      filename: '/the/fileName.vue',\n      selfName: 'FileName',\n    })\n  })\n\n  test('onError option', () => {\n    const ast = baseParse(`<div/>`)\n    const loc = ast.children[0].loc\n    const plugin: NodeTransform = (node, context) => {\n      context.onError(\n        createCompilerError(ErrorCodes.X_INVALID_END_TAG, node.loc),\n      )\n    }\n    const spy = vi.fn()\n    transform(ast, {\n      nodeTransforms: [plugin],\n      onError: spy,\n    })\n    expect(spy.mock.calls[0]).toMatchObject([\n      {\n        code: ErrorCodes.X_INVALID_END_TAG,\n        loc,\n      },\n    ])\n  })\n\n  test('should inject toString helper for interpolations', () => {\n    const ast = baseParse(`{{ foo }}`)\n    transform(ast, {})\n    expect(ast.helpers).toContain(TO_DISPLAY_STRING)\n  })\n\n  test('should inject createVNode and Comment for comments', () => {\n    const ast = baseParse(`<!--foo-->`)\n    transform(ast, {})\n    expect(ast.helpers).toContain(CREATE_COMMENT)\n  })\n\n  describe('root codegenNode', () => {\n    function transformWithCodegen(template: string) {\n      const ast = baseParse(template)\n      transform(ast, {\n        nodeTransforms: [\n          transformIf,\n          transformFor,\n          transformText,\n          transformSlotOutlet,\n          transformElement,\n        ],\n      })\n      return ast\n    }\n\n    function createBlockMatcher(\n      tag: VNodeCall['tag'],\n      props?: VNodeCall['props'],\n      children?: VNodeCall['children'],\n      patchFlag?: VNodeCall['patchFlag'],\n    ) {\n      return {\n        type: NodeTypes.VNODE_CALL,\n        isBlock: true,\n        tag,\n        props,\n        children,\n        patchFlag,\n      }\n    }\n\n    test('no children', () => {\n      const ast = transformWithCodegen(``)\n      expect(ast.codegenNode).toBeUndefined()\n    })\n\n    test('single <slot/>', () => {\n      const ast = transformWithCodegen(`<slot/>`)\n      expect(ast.codegenNode).toMatchObject({\n        codegenNode: {\n          type: NodeTypes.JS_CALL_EXPRESSION,\n          callee: RENDER_SLOT,\n        },\n      })\n    })\n\n    test('single element', () => {\n      const ast = transformWithCodegen(`<div/>`)\n      expect(ast.codegenNode).toMatchObject(createBlockMatcher(`\"div\"`))\n    })\n\n    test('root v-if', () => {\n      const ast = transformWithCodegen(`<div v-if=\"ok\" />`)\n      expect(ast.codegenNode).toMatchObject({\n        type: NodeTypes.IF,\n      })\n    })\n\n    test('root v-for', () => {\n      const ast = transformWithCodegen(`<div v-for=\"i in list\" />`)\n      expect(ast.codegenNode).toMatchObject({\n        type: NodeTypes.FOR,\n      })\n    })\n\n    test('root element with custom directive', () => {\n      const ast = transformWithCodegen(`<div v-foo/>`)\n      expect(ast.codegenNode).toMatchObject({\n        type: NodeTypes.VNODE_CALL,\n        directives: { type: NodeTypes.JS_ARRAY_EXPRESSION },\n      })\n    })\n\n    test('single text', () => {\n      const ast = transformWithCodegen(`hello`)\n      expect(ast.codegenNode).toMatchObject({\n        type: NodeTypes.TEXT,\n      })\n    })\n\n    test('single interpolation', () => {\n      const ast = transformWithCodegen(`{{ foo }}`)\n      expect(ast.codegenNode).toMatchObject({\n        type: NodeTypes.INTERPOLATION,\n      })\n    })\n\n    test('single CompoundExpression', () => {\n      const ast = transformWithCodegen(`{{ foo }} bar baz`)\n      expect(ast.codegenNode).toMatchObject({\n        type: NodeTypes.COMPOUND_EXPRESSION,\n      })\n    })\n\n    test('multiple children', () => {\n      const ast = transformWithCodegen(`<div/><div/>`)\n      expect(ast.codegenNode).toMatchObject(\n        createBlockMatcher(\n          FRAGMENT,\n          undefined,\n          [\n            { type: NodeTypes.ELEMENT, tag: `div` },\n            { type: NodeTypes.ELEMENT, tag: `div` },\n          ] as any,\n          PatchFlags.STABLE_FRAGMENT,\n        ),\n      )\n    })\n\n    test('multiple children w/ single root + comments', () => {\n      const ast = transformWithCodegen(`<!--foo--><div/><!--bar-->`)\n      expect(ast.codegenNode).toMatchObject(\n        createBlockMatcher(\n          FRAGMENT,\n          undefined,\n          [\n            { type: NodeTypes.COMMENT },\n            { type: NodeTypes.ELEMENT, tag: `div` },\n            { type: NodeTypes.COMMENT },\n          ] as any,\n          PatchFlags.STABLE_FRAGMENT | PatchFlags.DEV_ROOT_FRAGMENT,\n        ),\n      )\n    })\n  })\n})\n"
  },
  {
    "path": "packages/compiler-core/__tests__/transforms/__snapshots__/cacheStatic.spec.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`compiler: cacheStatic transform > cache element with static key 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue\n\n    return (_openBlock(), _createElementBlock(\"div\", null, [...(_cache[0] || (_cache[0] = [\n      _createElementVNode(\"div\", { key: \"foo\" }, null, -1 /* CACHED */)\n    ]))]))\n  }\n}\"\n`;\n\nexports[`compiler: cacheStatic transform > cache nested children array 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue\n\n    return (_openBlock(), _createElementBlock(\"div\", null, [...(_cache[0] || (_cache[0] = [\n      _createElementVNode(\"p\", null, [\n        _createElementVNode(\"span\"),\n        _createElementVNode(\"span\")\n      ], -1 /* CACHED */),\n      _createElementVNode(\"p\", null, [\n        _createElementVNode(\"span\"),\n        _createElementVNode(\"span\")\n      ], -1 /* CACHED */)\n    ]))]))\n  }\n}\"\n`;\n\nexports[`compiler: cacheStatic transform > cache nested static tree with comments 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { createCommentVNode: _createCommentVNode, createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue\n\n    return (_openBlock(), _createElementBlock(\"div\", null, [...(_cache[0] || (_cache[0] = [\n      _createElementVNode(\"div\", null, [\n        _createCommentVNode(\"comment\")\n      ], -1 /* CACHED */)\n    ]))]))\n  }\n}\"\n`;\n\nexports[`compiler: cacheStatic transform > cache siblings including text with common non-hoistable parent 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { createElementVNode: _createElementVNode, createTextVNode: _createTextVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue\n\n    return (_openBlock(), _createElementBlock(\"div\", null, [...(_cache[0] || (_cache[0] = [\n      _createElementVNode(\"span\", null, null, -1 /* CACHED */),\n      _createTextVNode(\"foo\", -1 /* CACHED */),\n      _createElementVNode(\"div\", null, null, -1 /* CACHED */)\n    ]))]))\n  }\n}\"\n`;\n\nexports[`compiler: cacheStatic transform > cache single children array 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue\n\n    return (_openBlock(), _createElementBlock(\"div\", null, [...(_cache[0] || (_cache[0] = [\n      _createElementVNode(\"span\", { class: \"inline\" }, \"hello\", -1 /* CACHED */)\n    ]))]))\n  }\n}\"\n`;\n\nexports[`compiler: cacheStatic transform > hoist static props for elements with directives 1`] = `\n\"const _Vue = Vue\nconst { createElementVNode: _createElementVNode } = _Vue\n\nconst _hoisted_1 = { id: \"foo\" }\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { resolveDirective: _resolveDirective, createElementVNode: _createElementVNode, withDirectives: _withDirectives, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue\n\n    const _directive_foo = _resolveDirective(\"foo\")\n\n    return (_openBlock(), _createElementBlock(\"div\", null, [\n      _withDirectives(_createElementVNode(\"div\", _hoisted_1, null, 512 /* NEED_PATCH */), [\n        [_directive_foo]\n      ])\n    ]))\n  }\n}\"\n`;\n\nexports[`compiler: cacheStatic transform > hoist static props for elements with dynamic text children 1`] = `\n\"const _Vue = Vue\nconst { createElementVNode: _createElementVNode } = _Vue\n\nconst _hoisted_1 = { id: \"foo\" }\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { toDisplayString: _toDisplayString, createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue\n\n    return (_openBlock(), _createElementBlock(\"div\", null, [\n      _createElementVNode(\"div\", _hoisted_1, _toDisplayString(hello), 1 /* TEXT */)\n    ]))\n  }\n}\"\n`;\n\nexports[`compiler: cacheStatic transform > hoist static props for elements with unhoistable children 1`] = `\n\"const _Vue = Vue\nconst { createVNode: _createVNode, createElementVNode: _createElementVNode } = _Vue\n\nconst _hoisted_1 = { id: \"foo\" }\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { resolveComponent: _resolveComponent, createVNode: _createVNode, createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue\n\n    const _component_Comp = _resolveComponent(\"Comp\")\n\n    return (_openBlock(), _createElementBlock(\"div\", null, [\n      _createElementVNode(\"div\", _hoisted_1, [\n        _createVNode(_component_Comp)\n      ])\n    ]))\n  }\n}\"\n`;\n\nexports[`compiler: cacheStatic transform > prefixIdentifiers > cache nested static tree with static interpolation 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { toDisplayString: _toDisplayString, createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue\n\n    return (_openBlock(), _createElementBlock(\"div\", null, [...(_cache[0] || (_cache[0] = [\n      _createElementVNode(\"span\", null, \"foo \" + _toDisplayString(1) + \" \" + _toDisplayString(true), -1 /* CACHED */)\n    ]))]))\n  }\n}\"\n`;\n\nexports[`compiler: cacheStatic transform > prefixIdentifiers > cache nested static tree with static prop value 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { toDisplayString: _toDisplayString, createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue\n\n    return (_openBlock(), _createElementBlock(\"div\", null, [...(_cache[0] || (_cache[0] = [\n      _createElementVNode(\"span\", { foo: 0 }, _toDisplayString(1), -1 /* CACHED */)\n    ]))]))\n  }\n}\"\n`;\n\nexports[`compiler: cacheStatic transform > prefixIdentifiers > clone hoisted array children in v-for + HMR mode 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { renderList: _renderList, Fragment: _Fragment, openBlock: _openBlock, createElementBlock: _createElementBlock, createElementVNode: _createElementVNode } = _Vue\n\n    return (_openBlock(), _createElementBlock(\"div\", null, [\n      (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(1, (i) => {\n        return (_openBlock(), _createElementBlock(\"div\", null, [...(_cache[0] || (_cache[0] = [\n          _createElementVNode(\"span\", { class: \"hi\" }, null, -1 /* CACHED */)\n        ]))]))\n      }), 256 /* UNKEYED_FRAGMENT */))\n    ]))\n  }\n}\"\n`;\n\nexports[`compiler: cacheStatic transform > prefixIdentifiers > hoist class with static object value 1`] = `\n\"const _Vue = Vue\nconst { createElementVNode: _createElementVNode } = _Vue\n\nconst _hoisted_1 = {\n  class: /*@__PURE__*/_normalizeClass({ foo: true })\n}\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { toDisplayString: _toDisplayString, normalizeClass: _normalizeClass, createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue\n\n    return (_openBlock(), _createElementBlock(\"div\", null, [\n      _createElementVNode(\"span\", _hoisted_1, _toDisplayString(_ctx.bar), 1 /* TEXT */)\n    ]))\n  }\n}\"\n`;\n\nexports[`compiler: cacheStatic transform > prefixIdentifiers > should NOT cache SVG with directives 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { createElementVNode: _createElementVNode, resolveDirective: _resolveDirective, openBlock: _openBlock, createElementBlock: _createElementBlock, withDirectives: _withDirectives } = _Vue\n\n    const _directive_foo = _resolveDirective(\"foo\")\n\n    return (_openBlock(), _createElementBlock(\"div\", null, [\n      _withDirectives((_openBlock(), _createElementBlock(\"svg\", null, [...(_cache[0] || (_cache[0] = [\n        _createElementVNode(\"path\", { d: \"M2,3H5.5L12\" }, null, -1 /* CACHED */)\n      ]))])), [\n        [_directive_foo]\n      ])\n    ]))\n  }\n}\"\n`;\n\nexports[`compiler: cacheStatic transform > prefixIdentifiers > should NOT cache elements with cached handlers + other bindings 1`] = `\n\"import { normalizeClass as _normalizeClass, createElementVNode as _createElementVNode, openBlock as _openBlock, createElementBlock as _createElementBlock } from \"vue\"\n\nexport function render(_ctx, _cache) {\n  return (_openBlock(), _createElementBlock(\"div\", null, [\n    _createElementVNode(\"div\", null, [\n      _createElementVNode(\"div\", {\n        class: _normalizeClass({}),\n        onClick: _cache[0] || (_cache[0] = (...args) => (_ctx.foo && _ctx.foo(...args)))\n      })\n    ])\n  ]))\n}\"\n`;\n\nexports[`compiler: cacheStatic transform > prefixIdentifiers > should NOT cache elements with cached handlers 1`] = `\n\"import { createElementVNode as _createElementVNode, openBlock as _openBlock, createElementBlock as _createElementBlock } from \"vue\"\n\nexport function render(_ctx, _cache) {\n  return (_openBlock(), _createElementBlock(\"div\", null, [\n    _createElementVNode(\"div\", null, [\n      _createElementVNode(\"div\", {\n        onClick: _cache[0] || (_cache[0] = (...args) => (_ctx.foo && _ctx.foo(...args)))\n      })\n    ])\n  ]))\n}\"\n`;\n\nexports[`compiler: cacheStatic transform > prefixIdentifiers > should NOT cache expressions that refer scope variables (2) 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { renderList: _renderList, Fragment: _Fragment, openBlock: _openBlock, createElementBlock: _createElementBlock, toDisplayString: _toDisplayString, createElementVNode: _createElementVNode } = _Vue\n\n    return (_openBlock(), _createElementBlock(\"div\", null, [\n      (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(_ctx.list, (o) => {\n        return (_openBlock(), _createElementBlock(\"p\", null, [\n          _createElementVNode(\"span\", null, _toDisplayString(o + 'foo'), 1 /* TEXT */)\n        ]))\n      }), 256 /* UNKEYED_FRAGMENT */))\n    ]))\n  }\n}\"\n`;\n\nexports[`compiler: cacheStatic transform > prefixIdentifiers > should NOT cache expressions that refer scope variables (v-slot) 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { toDisplayString: _toDisplayString, createTextVNode: _createTextVNode, resolveComponent: _resolveComponent, withCtx: _withCtx, openBlock: _openBlock, createBlock: _createBlock } = _Vue\n\n    const _component_Comp = _resolveComponent(\"Comp\")\n\n    return (_openBlock(), _createBlock(_component_Comp, null, {\n      default: _withCtx(({ foo }) => [\n        _createTextVNode(_toDisplayString(_ctx.foo), 1 /* TEXT */)\n      ]),\n      _: 1 /* STABLE */\n    }))\n  }\n}\"\n`;\n\nexports[`compiler: cacheStatic transform > prefixIdentifiers > should NOT cache expressions that refer scope variables 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { renderList: _renderList, Fragment: _Fragment, openBlock: _openBlock, createElementBlock: _createElementBlock, toDisplayString: _toDisplayString, createElementVNode: _createElementVNode } = _Vue\n\n    return (_openBlock(), _createElementBlock(\"div\", null, [\n      (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(_ctx.list, (o) => {\n        return (_openBlock(), _createElementBlock(\"p\", null, [\n          _createElementVNode(\"span\", null, _toDisplayString(o), 1 /* TEXT */)\n        ]))\n      }), 256 /* UNKEYED_FRAGMENT */))\n    ]))\n  }\n}\"\n`;\n\nexports[`compiler: cacheStatic transform > prefixIdentifiers > should NOT cache keyed template v-for with plain element child 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { renderList: _renderList, Fragment: _Fragment, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue\n\n    return (_openBlock(), _createElementBlock(\"div\", null, [\n      (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(items, (item) => {\n        return (_openBlock(), _createElementBlock(\"span\", { key: item }))\n      }), 128 /* KEYED_FRAGMENT */))\n    ]))\n  }\n}\"\n`;\n\nexports[`compiler: cacheStatic transform > should NOT cache components 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { resolveComponent: _resolveComponent, createVNode: _createVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue\n\n    const _component_Comp = _resolveComponent(\"Comp\")\n\n    return (_openBlock(), _createElementBlock(\"div\", null, [\n      _createVNode(_component_Comp)\n    ]))\n  }\n}\"\n`;\n\nexports[`compiler: cacheStatic transform > should NOT cache element with dynamic key 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue\n\n    return (_openBlock(), _createElementBlock(\"div\", null, [\n      (_openBlock(), _createElementBlock(\"div\", { key: foo }))\n    ]))\n  }\n}\"\n`;\n\nexports[`compiler: cacheStatic transform > should NOT cache element with dynamic props (but hoist the props list) 1`] = `\n\"const _Vue = Vue\nconst { createElementVNode: _createElementVNode } = _Vue\n\nconst _hoisted_1 = [\"id\"]\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue\n\n    return (_openBlock(), _createElementBlock(\"div\", null, [\n      _createElementVNode(\"div\", { id: foo }, null, 8 /* PROPS */, _hoisted_1)\n    ]))\n  }\n}\"\n`;\n\nexports[`compiler: cacheStatic transform > should NOT cache element with dynamic ref 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue\n\n    return (_openBlock(), _createElementBlock(\"div\", null, [\n      _createElementVNode(\"div\", { ref: foo }, null, 512 /* NEED_PATCH */)\n    ]))\n  }\n}\"\n`;\n\nexports[`compiler: cacheStatic transform > should cache v-if props/children if static 1`] = `\n\"const _Vue = Vue\nconst { createElementVNode: _createElementVNode, createCommentVNode: _createCommentVNode } = _Vue\n\nconst _hoisted_1 = {\n  key: 0,\n  id: \"foo\"\n}\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock, createCommentVNode: _createCommentVNode } = _Vue\n\n    return (_openBlock(), _createElementBlock(\"div\", null, [\n      ok\n        ? (_openBlock(), _createElementBlock(\"div\", _hoisted_1, [...(_cache[0] || (_cache[0] = [\n            _createElementVNode(\"span\", null, null, -1 /* CACHED */)\n          ]))]))\n        : _createCommentVNode(\"v-if\", true)\n    ]))\n  }\n}\"\n`;\n\nexports[`compiler: cacheStatic transform > should hoist props for root with single element excluding comments 1`] = `\n\"const _Vue = Vue\nconst { createElementVNode: _createElementVNode, createCommentVNode: _createCommentVNode } = _Vue\n\nconst _hoisted_1 = { id: \"a\" }\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { createCommentVNode: _createCommentVNode, createElementVNode: _createElementVNode, Fragment: _Fragment, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue\n\n    return (_openBlock(), _createElementBlock(_Fragment, null, [\n      _createCommentVNode(\"comment\"),\n      _createElementVNode(\"div\", _hoisted_1, [...(_cache[0] || (_cache[0] = [\n        _createElementVNode(\"div\", { id: \"b\" }, [\n          _createElementVNode(\"div\", { id: \"c\" }, [\n            _createElementVNode(\"div\", { id: \"d\" }, [\n              _createElementVNode(\"div\", { id: \"e\" }, \"hello\")\n            ])\n          ])\n        ], -1 /* CACHED */)\n      ]))])\n    ], 2112 /* STABLE_FRAGMENT, DEV_ROOT_FRAGMENT */))\n  }\n}\"\n`;\n\nexports[`compiler: cacheStatic transform > should hoist v-for children if static 1`] = `\n\"const _Vue = Vue\nconst { createElementVNode: _createElementVNode } = _Vue\n\nconst _hoisted_1 = { id: \"foo\" }\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { renderList: _renderList, Fragment: _Fragment, openBlock: _openBlock, createElementBlock: _createElementBlock, createElementVNode: _createElementVNode } = _Vue\n\n    return (_openBlock(), _createElementBlock(\"div\", null, [\n      (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(list, (i) => {\n        return (_openBlock(), _createElementBlock(\"div\", _hoisted_1, [...(_cache[0] || (_cache[0] = [\n          _createElementVNode(\"span\", null, null, -1 /* CACHED */)\n        ]))]))\n      }), 256 /* UNKEYED_FRAGMENT */))\n    ]))\n  }\n}\"\n`;\n"
  },
  {
    "path": "packages/compiler-core/__tests__/transforms/__snapshots__/transformElement.spec.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`compiler: v-for > codegen > basic v-for 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { renderList: _renderList, Fragment: _Fragment, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue\n\n    return (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(items, (item) => {\n      return (_openBlock(), _createElementBlock(\"span\"))\n    }), 256 /* UNKEYED_FRAGMENT */))\n  }\n}\"\n`;\n\nexports[`compiler: v-for > codegen > keyed template v-for 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { renderList: _renderList, Fragment: _Fragment, openBlock: _openBlock, createElementBlock: _createElementBlock, createElementVNode: _createElementVNode } = _Vue\n\n    return (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(items, (item) => {\n      return (_openBlock(), _createElementBlock(_Fragment, { key: item }, [\n        \"hello\",\n        _createElementVNode(\"span\")\n      ], 64 /* STABLE_FRAGMENT */))\n    }), 128 /* KEYED_FRAGMENT */))\n  }\n}\"\n`;\n\nexports[`compiler: v-for > codegen > keyed v-for 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { renderList: _renderList, Fragment: _Fragment, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue\n\n    return (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(items, (item) => {\n      return (_openBlock(), _createElementBlock(\"span\", { key: item }))\n    }), 128 /* KEYED_FRAGMENT */))\n  }\n}\"\n`;\n\nexports[`compiler: v-for > codegen > skipped key 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { renderList: _renderList, Fragment: _Fragment, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue\n\n    return (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(items, (item, __, index) => {\n      return (_openBlock(), _createElementBlock(\"span\"))\n    }), 256 /* UNKEYED_FRAGMENT */))\n  }\n}\"\n`;\n\nexports[`compiler: v-for > codegen > skipped value & key 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { renderList: _renderList, Fragment: _Fragment, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue\n\n    return (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(items, (_, __, index) => {\n      return (_openBlock(), _createElementBlock(\"span\"))\n    }), 256 /* UNKEYED_FRAGMENT */))\n  }\n}\"\n`;\n\nexports[`compiler: v-for > codegen > skipped value 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { renderList: _renderList, Fragment: _Fragment, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue\n\n    return (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(items, (_, key, index) => {\n      return (_openBlock(), _createElementBlock(\"span\"))\n    }), 256 /* UNKEYED_FRAGMENT */))\n  }\n}\"\n`;\n\nexports[`compiler: v-for > codegen > template v-for 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { renderList: _renderList, Fragment: _Fragment, openBlock: _openBlock, createElementBlock: _createElementBlock, createElementVNode: _createElementVNode } = _Vue\n\n    return (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(items, (item) => {\n      return (_openBlock(), _createElementBlock(_Fragment, null, [\n        \"hello\",\n        _createElementVNode(\"span\")\n      ], 64 /* STABLE_FRAGMENT */))\n    }), 256 /* UNKEYED_FRAGMENT */))\n  }\n}\"\n`;\n\nexports[`compiler: v-for > codegen > template v-for key injection with single child 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { renderList: _renderList, Fragment: _Fragment, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue\n\n    return (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(items, (item) => {\n      return (_openBlock(), _createElementBlock(\"span\", {\n        key: item.id,\n        id: item.id\n      }, null, 8 /* PROPS */, [\"id\"]))\n    }), 128 /* KEYED_FRAGMENT */))\n  }\n}\"\n`;\n\nexports[`compiler: v-for > codegen > template v-for w/ <slot/> 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { renderList: _renderList, Fragment: _Fragment, openBlock: _openBlock, createElementBlock: _createElementBlock, renderSlot: _renderSlot } = _Vue\n\n    return (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(items, (item) => {\n      return _renderSlot($slots, \"default\")\n    }), 256 /* UNKEYED_FRAGMENT */))\n  }\n}\"\n`;\n\nexports[`compiler: v-for > codegen > v-for on <slot/> 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { renderList: _renderList, Fragment: _Fragment, openBlock: _openBlock, createElementBlock: _createElementBlock, renderSlot: _renderSlot } = _Vue\n\n    return (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(items, (item) => {\n      return _renderSlot($slots, \"default\")\n    }), 256 /* UNKEYED_FRAGMENT */))\n  }\n}\"\n`;\n\nexports[`compiler: v-for > codegen > v-for on element with custom directive 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { renderList: _renderList, Fragment: _Fragment, openBlock: _openBlock, createElementBlock: _createElementBlock, resolveDirective: _resolveDirective, withDirectives: _withDirectives } = _Vue\n\n    const _directive_foo = _resolveDirective(\"foo\")\n\n    return (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(list, (i) => {\n      return _withDirectives((_openBlock(), _createElementBlock(\"div\", null, null, 512 /* NEED_PATCH */)), [\n        [_directive_foo]\n      ])\n    }), 256 /* UNKEYED_FRAGMENT */))\n  }\n}\"\n`;\n\nexports[`compiler: v-for > codegen > v-for with constant expression 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { renderList: _renderList, Fragment: _Fragment, openBlock: _openBlock, createElementBlock: _createElementBlock, toDisplayString: _toDisplayString, createElementVNode: _createElementVNode } = _Vue\n\n    return (_openBlock(), _createElementBlock(_Fragment, null, _renderList(10, (item) => {\n      return _createElementVNode(\"p\", null, _toDisplayString(item), 1 /* TEXT */)\n    }), 64 /* STABLE_FRAGMENT */))\n  }\n}\"\n`;\n\nexports[`compiler: v-for > codegen > v-if + v-for 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { renderList: _renderList, Fragment: _Fragment, openBlock: _openBlock, createElementBlock: _createElementBlock, createCommentVNode: _createCommentVNode } = _Vue\n\n    return ok\n      ? (_openBlock(true), _createElementBlock(_Fragment, { key: 0 }, _renderList(list, (i) => {\n          return (_openBlock(), _createElementBlock(\"div\"))\n        }), 256 /* UNKEYED_FRAGMENT */))\n      : _createCommentVNode(\"v-if\", true)\n  }\n}\"\n`;\n\nexports[`compiler: v-for > codegen > v-if + v-for on <template> 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { renderList: _renderList, Fragment: _Fragment, openBlock: _openBlock, createElementBlock: _createElementBlock, createCommentVNode: _createCommentVNode } = _Vue\n\n    return ok\n      ? (_openBlock(true), _createElementBlock(_Fragment, { key: 0 }, _renderList(list, (i) => {\n          return (_openBlock(), _createElementBlock(_Fragment, null, [], 64 /* STABLE_FRAGMENT */))\n        }), 256 /* UNKEYED_FRAGMENT */))\n      : _createCommentVNode(\"v-if\", true)\n  }\n}\"\n`;\n\nexports[`compiler: v-for > codegen > value + key + index 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { renderList: _renderList, Fragment: _Fragment, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue\n\n    return (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(items, (item, key, index) => {\n      return (_openBlock(), _createElementBlock(\"span\"))\n    }), 256 /* UNKEYED_FRAGMENT */))\n  }\n}\"\n`;\n"
  },
  {
    "path": "packages/compiler-core/__tests__/transforms/__snapshots__/transformExpressions.spec.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`compiler: expression transform > bindingMetadata > inline mode 1`] = `\n\"(_ctx, _cache) => {\n  return (_openBlock(), _createElementBlock(\"div\", null, _toDisplayString(__props.props) + \" \" + _toDisplayString(_unref(setup)) + \" \" + _toDisplayString(setupConst) + \" \" + _toDisplayString(_ctx.data) + \" \" + _toDisplayString(_ctx.options) + \" \" + _toDisplayString(isNaN.value), 1 /* TEXT */))\n}\"\n`;\n\nexports[`compiler: expression transform > bindingMetadata > non-inline mode 1`] = `\n\"const { toDisplayString: _toDisplayString, openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue\n\nreturn function render(_ctx, _cache, $props, $setup, $data, $options) {\n  return (_openBlock(), _createElementBlock(\"div\", null, _toDisplayString($props.props) + \" \" + _toDisplayString($setup.setup) + \" \" + _toDisplayString($data.data) + \" \" + _toDisplayString($options.options) + \" \" + _toDisplayString($setup.isNaN), 1 /* TEXT */))\n}\"\n`;\n\nexports[`compiler: expression transform > should allow leak of var declarations in for loop 1`] = `\n\"const { openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue\n\nreturn function render(_ctx, _cache) {\n  return (_openBlock(), _createElementBlock(\"div\", {\n    onClick: () => {\n        for (var i = 0; i < _ctx.list.length; i++) {\n          _ctx.log(i)\n        }\n        _ctx.error(i)\n      }\n  }, null, 8 /* PROPS */, [\"onClick\"]))\n}\"\n`;\n\nexports[`compiler: expression transform > should not prefix catch block param 1`] = `\n\"const { openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue\n\nreturn function render(_ctx, _cache) {\n  return (_openBlock(), _createElementBlock(\"div\", {\n    onClick: () => {\n         try {} catch (err) { console.error(err) }\n        console.log(_ctx.err)\n      }\n  }, null, 8 /* PROPS */, [\"onClick\"]))\n}\"\n`;\n\nexports[`compiler: expression transform > should not prefix destructured catch block param 1`] = `\n\"const { openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue\n\nreturn function render(_ctx, _cache) {\n  return (_openBlock(), _createElementBlock(\"div\", {\n    onClick: () => {\n        try {\n          throw new Error('sup?')\n        } catch ({ message: { length } }) {\n          console.error(length)\n        }\n        console.log(_ctx.length)\n      }\n  }, null, 8 /* PROPS */, [\"onClick\"]))\n}\"\n`;\n\nexports[`compiler: expression transform > should not prefix temp variable of for loop 1`] = `\n\"const { openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue\n\nreturn function render(_ctx, _cache) {\n  return (_openBlock(), _createElementBlock(\"div\", {\n    onClick: () => {\n        for (let i = 0; i < _ctx.list.length; i++) {\n          _ctx.log(i)\n        }\n        _ctx.error(_ctx.i)\n      }\n  }, null, 8 /* PROPS */, [\"onClick\"]))\n}\"\n`;\n\nexports[`compiler: expression transform > should not prefix temp variable of for...in 1`] = `\n\"const { openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue\n\nreturn function render(_ctx, _cache) {\n  return (_openBlock(), _createElementBlock(\"div\", {\n    onClick: () => {\n        for (const x in _ctx.list) {\n          _ctx.log(x)\n        }\n        _ctx.error(_ctx.x)\n      }\n  }, null, 8 /* PROPS */, [\"onClick\"]))\n}\"\n`;\n\nexports[`compiler: expression transform > should not prefix temp variable of for...of 1`] = `\n\"const { openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue\n\nreturn function render(_ctx, _cache) {\n  return (_openBlock(), _createElementBlock(\"div\", {\n    onClick: () => {\n        for (const x of _ctx.list) {\n          _ctx.log(x)\n        }\n        _ctx.error(_ctx.x)\n      }\n  }, null, 8 /* PROPS */, [\"onClick\"]))\n}\"\n`;\n"
  },
  {
    "path": "packages/compiler-core/__tests__/transforms/__snapshots__/transformText.spec.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`compiler: transform text > <template v-for> 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { renderList: _renderList, Fragment: _Fragment, openBlock: _openBlock, createElementBlock: _createElementBlock, createTextVNode: _createTextVNode } = _Vue\n\n    return (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(list, (i) => {\n      return (_openBlock(), _createElementBlock(_Fragment, null, [\n        _createTextVNode(\"foo\")\n      ], 64 /* STABLE_FRAGMENT */))\n    }), 256 /* UNKEYED_FRAGMENT */))\n  }\n}\"\n`;\n\nexports[`compiler: transform text > consecutive text 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { toDisplayString: _toDisplayString } = _Vue\n\n    return _toDisplayString(foo) + \" bar \" + _toDisplayString(baz)\n  }\n}\"\n`;\n\nexports[`compiler: transform text > consecutive text between elements 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { createElementVNode: _createElementVNode, toDisplayString: _toDisplayString, createTextVNode: _createTextVNode, Fragment: _Fragment, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue\n\n    return (_openBlock(), _createElementBlock(_Fragment, null, [\n      _createElementVNode(\"div\"),\n      _createTextVNode(_toDisplayString(foo) + \" bar \" + _toDisplayString(baz), 1 /* TEXT */),\n      _createElementVNode(\"div\")\n    ], 64 /* STABLE_FRAGMENT */))\n  }\n}\"\n`;\n\nexports[`compiler: transform text > consecutive text mixed with elements 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { createElementVNode: _createElementVNode, toDisplayString: _toDisplayString, createTextVNode: _createTextVNode, Fragment: _Fragment, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue\n\n    return (_openBlock(), _createElementBlock(_Fragment, null, [\n      _createElementVNode(\"div\"),\n      _createTextVNode(_toDisplayString(foo) + \" bar \" + _toDisplayString(baz), 1 /* TEXT */),\n      _createElementVNode(\"div\"),\n      _createTextVNode(\"hello\"),\n      _createElementVNode(\"div\")\n    ], 64 /* STABLE_FRAGMENT */))\n  }\n}\"\n`;\n\nexports[`compiler: transform text > element with custom directives and only one text child node 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { toDisplayString: _toDisplayString, createTextVNode: _createTextVNode, resolveDirective: _resolveDirective, openBlock: _openBlock, createElementBlock: _createElementBlock, withDirectives: _withDirectives } = _Vue\n\n    const _directive_foo = _resolveDirective(\"foo\")\n\n    return _withDirectives((_openBlock(), _createElementBlock(\"p\", null, [\n      _createTextVNode(_toDisplayString(foo), 1 /* TEXT */)\n    ])), [\n      [_directive_foo]\n    ])\n  }\n}\"\n`;\n\nexports[`compiler: transform text > no consecutive text 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { toDisplayString: _toDisplayString } = _Vue\n\n    return _toDisplayString(foo)\n  }\n}\"\n`;\n\nexports[`compiler: transform text > text between elements (static) 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { createElementVNode: _createElementVNode, createTextVNode: _createTextVNode, Fragment: _Fragment, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue\n\n    return (_openBlock(), _createElementBlock(_Fragment, null, [\n      _createElementVNode(\"div\"),\n      _createTextVNode(\"hello\"),\n      _createElementVNode(\"div\")\n    ], 64 /* STABLE_FRAGMENT */))\n  }\n}\"\n`;\n\nexports[`compiler: transform text > with prefixIdentifiers: true 1`] = `\n\"const { toDisplayString: _toDisplayString } = Vue\n\nreturn function render(_ctx, _cache) {\n  return _toDisplayString(_ctx.foo) + \" bar \" + _toDisplayString(_ctx.baz + _ctx.qux)\n}\"\n`;\n"
  },
  {
    "path": "packages/compiler-core/__tests__/transforms/__snapshots__/vFor.spec.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`compiler: v-for > codegen > basic v-for 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { renderList: _renderList, Fragment: _Fragment, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue\n\n    return (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(items, (item) => {\n      return (_openBlock(), _createElementBlock(\"span\"))\n    }), 256 /* UNKEYED_FRAGMENT */))\n  }\n}\"\n`;\n\nexports[`compiler: v-for > codegen > keyed template v-for 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { renderList: _renderList, Fragment: _Fragment, openBlock: _openBlock, createElementBlock: _createElementBlock, createElementVNode: _createElementVNode } = _Vue\n\n    return (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(items, (item) => {\n      return (_openBlock(), _createElementBlock(_Fragment, { key: item }, [\n        \"hello\",\n        _createElementVNode(\"span\")\n      ], 64 /* STABLE_FRAGMENT */))\n    }), 128 /* KEYED_FRAGMENT */))\n  }\n}\"\n`;\n\nexports[`compiler: v-for > codegen > keyed v-for 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { renderList: _renderList, Fragment: _Fragment, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue\n\n    return (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(items, (item) => {\n      return (_openBlock(), _createElementBlock(\"span\", { key: item }))\n    }), 128 /* KEYED_FRAGMENT */))\n  }\n}\"\n`;\n\nexports[`compiler: v-for > codegen > skipped key 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { renderList: _renderList, Fragment: _Fragment, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue\n\n    return (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(items, (item, __, index) => {\n      return (_openBlock(), _createElementBlock(\"span\"))\n    }), 256 /* UNKEYED_FRAGMENT */))\n  }\n}\"\n`;\n\nexports[`compiler: v-for > codegen > skipped value & key 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { renderList: _renderList, Fragment: _Fragment, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue\n\n    return (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(items, (_, __, index) => {\n      return (_openBlock(), _createElementBlock(\"span\"))\n    }), 256 /* UNKEYED_FRAGMENT */))\n  }\n}\"\n`;\n\nexports[`compiler: v-for > codegen > skipped value 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { renderList: _renderList, Fragment: _Fragment, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue\n\n    return (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(items, (_, key, index) => {\n      return (_openBlock(), _createElementBlock(\"span\"))\n    }), 256 /* UNKEYED_FRAGMENT */))\n  }\n}\"\n`;\n\nexports[`compiler: v-for > codegen > template v-for 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { renderList: _renderList, Fragment: _Fragment, openBlock: _openBlock, createElementBlock: _createElementBlock, createElementVNode: _createElementVNode } = _Vue\n\n    return (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(items, (item) => {\n      return (_openBlock(), _createElementBlock(_Fragment, null, [\n        \"hello\",\n        _createElementVNode(\"span\")\n      ], 64 /* STABLE_FRAGMENT */))\n    }), 256 /* UNKEYED_FRAGMENT */))\n  }\n}\"\n`;\n\nexports[`compiler: v-for > codegen > template v-for key injection with single child 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { renderList: _renderList, Fragment: _Fragment, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue\n\n    return (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(items, (item) => {\n      return (_openBlock(), _createElementBlock(\"span\", {\n        key: item.id,\n        id: item.id\n      }, null, 8 /* PROPS */, [\"id\"]))\n    }), 128 /* KEYED_FRAGMENT */))\n  }\n}\"\n`;\n\nexports[`compiler: v-for > codegen > template v-for w/ <slot/> 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { renderList: _renderList, Fragment: _Fragment, openBlock: _openBlock, createElementBlock: _createElementBlock, renderSlot: _renderSlot } = _Vue\n\n    return (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(items, (item) => {\n      return _renderSlot($slots, \"default\")\n    }), 256 /* UNKEYED_FRAGMENT */))\n  }\n}\"\n`;\n\nexports[`compiler: v-for > codegen > v-for on <slot/> 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { renderList: _renderList, Fragment: _Fragment, openBlock: _openBlock, createElementBlock: _createElementBlock, renderSlot: _renderSlot } = _Vue\n\n    return (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(items, (item) => {\n      return _renderSlot($slots, \"default\")\n    }), 256 /* UNKEYED_FRAGMENT */))\n  }\n}\"\n`;\n\nexports[`compiler: v-for > codegen > v-for on element with custom directive 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { renderList: _renderList, Fragment: _Fragment, openBlock: _openBlock, createElementBlock: _createElementBlock, resolveDirective: _resolveDirective, withDirectives: _withDirectives } = _Vue\n\n    const _directive_foo = _resolveDirective(\"foo\")\n\n    return (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(list, (i) => {\n      return _withDirectives((_openBlock(), _createElementBlock(\"div\", null, null, 512 /* NEED_PATCH */)), [\n        [_directive_foo]\n      ])\n    }), 256 /* UNKEYED_FRAGMENT */))\n  }\n}\"\n`;\n\nexports[`compiler: v-for > codegen > v-for with constant expression 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { renderList: _renderList, Fragment: _Fragment, openBlock: _openBlock, createElementBlock: _createElementBlock, toDisplayString: _toDisplayString, createElementVNode: _createElementVNode } = _Vue\n\n    return (_openBlock(), _createElementBlock(_Fragment, null, _renderList(10, (item) => {\n      return _createElementVNode(\"p\", null, _toDisplayString(item), 1 /* TEXT */)\n    }), 64 /* STABLE_FRAGMENT */))\n  }\n}\"\n`;\n\nexports[`compiler: v-for > codegen > v-if + v-for 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { renderList: _renderList, Fragment: _Fragment, openBlock: _openBlock, createElementBlock: _createElementBlock, createCommentVNode: _createCommentVNode } = _Vue\n\n    return ok\n      ? (_openBlock(true), _createElementBlock(_Fragment, { key: 0 }, _renderList(list, (i) => {\n          return (_openBlock(), _createElementBlock(\"div\"))\n        }), 256 /* UNKEYED_FRAGMENT */))\n      : _createCommentVNode(\"v-if\", true)\n  }\n}\"\n`;\n\nexports[`compiler: v-for > codegen > v-if + v-for on <template> 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { renderList: _renderList, Fragment: _Fragment, openBlock: _openBlock, createElementBlock: _createElementBlock, createCommentVNode: _createCommentVNode } = _Vue\n\n    return ok\n      ? (_openBlock(true), _createElementBlock(_Fragment, { key: 0 }, _renderList(list, (i) => {\n          return (_openBlock(), _createElementBlock(_Fragment, null, [], 64 /* STABLE_FRAGMENT */))\n        }), 256 /* UNKEYED_FRAGMENT */))\n      : _createCommentVNode(\"v-if\", true)\n  }\n}\"\n`;\n\nexports[`compiler: v-for > codegen > value + key + index 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { renderList: _renderList, Fragment: _Fragment, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue\n\n    return (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(items, (item, key, index) => {\n      return (_openBlock(), _createElementBlock(\"span\"))\n    }), 256 /* UNKEYED_FRAGMENT */))\n  }\n}\"\n`;\n"
  },
  {
    "path": "packages/compiler-core/__tests__/transforms/__snapshots__/vIf.spec.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`compiler: v-if > codegen > basic v-if 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { openBlock: _openBlock, createElementBlock: _createElementBlock, createCommentVNode: _createCommentVNode } = _Vue\n\n    return ok\n      ? (_openBlock(), _createElementBlock(\"div\", { key: 0 }))\n      : _createCommentVNode(\"v-if\", true)\n  }\n}\"\n`;\n\nexports[`compiler: v-if > codegen > increasing key: v-if + v-else-if + v-else 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { openBlock: _openBlock, createElementBlock: _createElementBlock, createCommentVNode: _createCommentVNode, Fragment: _Fragment } = _Vue\n\n    return (_openBlock(), _createElementBlock(_Fragment, null, [\n      ok\n        ? (_openBlock(), _createElementBlock(\"div\", { key: 0 }))\n        : (_openBlock(), _createElementBlock(\"p\", { key: 1 })),\n      another\n        ? (_openBlock(), _createElementBlock(\"div\", { key: 2 }))\n        : orNot\n          ? (_openBlock(), _createElementBlock(\"p\", { key: 3 }))\n          : (_openBlock(), _createElementBlock(\"p\", { key: 4 }))\n    ], 64 /* STABLE_FRAGMENT */))\n  }\n}\"\n`;\n\nexports[`compiler: v-if > codegen > multiple v-if that are sibling nodes should have different keys 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { openBlock: _openBlock, createElementBlock: _createElementBlock, createCommentVNode: _createCommentVNode, Fragment: _Fragment } = _Vue\n\n    return (_openBlock(), _createElementBlock(_Fragment, null, [\n      ok\n        ? (_openBlock(), _createElementBlock(\"div\", { key: 0 }))\n        : _createCommentVNode(\"v-if\", true),\n      orNot\n        ? (_openBlock(), _createElementBlock(\"p\", { key: 1 }))\n        : _createCommentVNode(\"v-if\", true)\n    ], 64 /* STABLE_FRAGMENT */))\n  }\n}\"\n`;\n\nexports[`compiler: v-if > codegen > template v-if 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { createElementVNode: _createElementVNode, Fragment: _Fragment, openBlock: _openBlock, createElementBlock: _createElementBlock, createCommentVNode: _createCommentVNode } = _Vue\n\n    return ok\n      ? (_openBlock(), _createElementBlock(_Fragment, { key: 0 }, [\n          _createElementVNode(\"div\"),\n          \"hello\",\n          _createElementVNode(\"p\")\n        ], 64 /* STABLE_FRAGMENT */))\n      : _createCommentVNode(\"v-if\", true)\n  }\n}\"\n`;\n\nexports[`compiler: v-if > codegen > template v-if w/ single <slot/> child 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { renderSlot: _renderSlot, createCommentVNode: _createCommentVNode } = _Vue\n\n    return ok\n      ? _renderSlot($slots, \"default\", { key: 0 })\n      : _createCommentVNode(\"v-if\", true)\n  }\n}\"\n`;\n\nexports[`compiler: v-if > codegen > v-if + v-else 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { openBlock: _openBlock, createElementBlock: _createElementBlock, createCommentVNode: _createCommentVNode } = _Vue\n\n    return ok\n      ? (_openBlock(), _createElementBlock(\"div\", { key: 0 }))\n      : (_openBlock(), _createElementBlock(\"p\", { key: 1 }))\n  }\n}\"\n`;\n\nexports[`compiler: v-if > codegen > v-if + v-else-if + v-else 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { openBlock: _openBlock, createElementBlock: _createElementBlock, createCommentVNode: _createCommentVNode, Fragment: _Fragment } = _Vue\n\n    return ok\n      ? (_openBlock(), _createElementBlock(\"div\", { key: 0 }))\n      : orNot\n        ? (_openBlock(), _createElementBlock(\"p\", { key: 1 }))\n        : (_openBlock(), _createElementBlock(_Fragment, { key: 2 }, [\"fine\"], 64 /* STABLE_FRAGMENT */))\n  }\n}\"\n`;\n\nexports[`compiler: v-if > codegen > v-if + v-else-if 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { openBlock: _openBlock, createElementBlock: _createElementBlock, createCommentVNode: _createCommentVNode } = _Vue\n\n    return ok\n      ? (_openBlock(), _createElementBlock(\"div\", { key: 0 }))\n      : orNot\n        ? (_openBlock(), _createElementBlock(\"p\", { key: 1 }))\n        : _createCommentVNode(\"v-if\", true)\n  }\n}\"\n`;\n\nexports[`compiler: v-if > codegen > v-if on <slot/> 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { renderSlot: _renderSlot, createCommentVNode: _createCommentVNode } = _Vue\n\n    return ok\n      ? _renderSlot($slots, \"default\", { key: 0 })\n      : _createCommentVNode(\"v-if\", true)\n  }\n}\"\n`;\n"
  },
  {
    "path": "packages/compiler-core/__tests__/transforms/__snapshots__/vMemo.spec.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`compiler: v-memo transform > element v-for key expression prefixing + v-memo 1`] = `\n\"import { renderList as _renderList, Fragment as _Fragment, openBlock as _openBlock, createElementBlock as _createElementBlock, isMemoSame as _isMemoSame, withMemo as _withMemo } from \"vue\"\n\nexport function render(_ctx, _cache) {\n  return (_openBlock(), _createElementBlock(\"div\", null, [\n    (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(_ctx.tableData, (data, __, ___, _cached) => {\n      const _memo = (_ctx.getLetter(data))\n      if (_cached && _cached.key === _ctx.getId(data) && _isMemoSame(_cached, _memo)) return _cached\n      const _item = (_openBlock(), _createElementBlock(\"span\", {\n        key: _ctx.getId(data)\n      }))\n      _item.memo = _memo\n      return _item\n    }, _cache, 0), 128 /* KEYED_FRAGMENT */))\n  ]))\n}\"\n`;\n\nexports[`compiler: v-memo transform > on component 1`] = `\n\"import { resolveComponent as _resolveComponent, createVNode as _createVNode, withMemo as _withMemo, openBlock as _openBlock, createElementBlock as _createElementBlock } from \"vue\"\n\nexport function render(_ctx, _cache) {\n  const _component_Comp = _resolveComponent(\"Comp\")\n\n  return (_openBlock(), _createElementBlock(\"div\", null, [\n    _withMemo([_ctx.x], () => _createVNode(_component_Comp), _cache, 0)\n  ]))\n}\"\n`;\n\nexports[`compiler: v-memo transform > on normal element 1`] = `\n\"import { openBlock as _openBlock, createElementBlock as _createElementBlock, withMemo as _withMemo } from \"vue\"\n\nexport function render(_ctx, _cache) {\n  return (_openBlock(), _createElementBlock(\"div\", null, [\n    _withMemo([_ctx.x], () => (_openBlock(), _createElementBlock(\"div\")), _cache, 0)\n  ]))\n}\"\n`;\n\nexports[`compiler: v-memo transform > on root element 1`] = `\n\"import { openBlock as _openBlock, createElementBlock as _createElementBlock, withMemo as _withMemo } from \"vue\"\n\nexport function render(_ctx, _cache) {\n  return _withMemo([_ctx.x], () => (_openBlock(), _createElementBlock(\"div\")), _cache, 0)\n}\"\n`;\n\nexports[`compiler: v-memo transform > on template v-for 1`] = `\n\"import { renderList as _renderList, Fragment as _Fragment, openBlock as _openBlock, createElementBlock as _createElementBlock, isMemoSame as _isMemoSame, withMemo as _withMemo } from \"vue\"\n\nexport function render(_ctx, _cache) {\n  return (_openBlock(), _createElementBlock(\"div\", null, [\n    (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(_ctx.list, ({ x, y }, __, ___, _cached) => {\n      const _memo = ([x, y === _ctx.z])\n      if (_cached && _cached.key === x && _isMemoSame(_cached, _memo)) return _cached\n      const _item = (_openBlock(), _createElementBlock(\"span\", { key: x }, \"foobar\"))\n      _item.memo = _memo\n      return _item\n    }, _cache, 0), 128 /* KEYED_FRAGMENT */))\n  ]))\n}\"\n`;\n\nexports[`compiler: v-memo transform > on v-for 1`] = `\n\"import { renderList as _renderList, Fragment as _Fragment, openBlock as _openBlock, createElementBlock as _createElementBlock, createElementVNode as _createElementVNode, isMemoSame as _isMemoSame, withMemo as _withMemo } from \"vue\"\n\nexport function render(_ctx, _cache) {\n  return (_openBlock(), _createElementBlock(\"div\", null, [\n    (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(_ctx.list, ({ x, y }, __, ___, _cached) => {\n      const _memo = ([x, y === _ctx.z])\n      if (_cached && _cached.key === x && _isMemoSame(_cached, _memo)) return _cached\n      const _item = (_openBlock(), _createElementBlock(\"div\", { key: x }, [\n        _createElementVNode(\"span\", null, \"foobar\")\n      ]))\n      _item.memo = _memo\n      return _item\n    }, _cache, 0), 128 /* KEYED_FRAGMENT */))\n  ]))\n}\"\n`;\n\nexports[`compiler: v-memo transform > on v-if 1`] = `\n\"import { createElementVNode as _createElementVNode, createTextVNode as _createTextVNode, openBlock as _openBlock, createElementBlock as _createElementBlock, withMemo as _withMemo, createCommentVNode as _createCommentVNode, resolveComponent as _resolveComponent, createBlock as _createBlock } from \"vue\"\n\nexport function render(_ctx, _cache) {\n  const _component_Comp = _resolveComponent(\"Comp\")\n\n  return (_openBlock(), _createElementBlock(\"div\", null, [\n    (_ctx.ok)\n      ? _withMemo([_ctx.x], () => (_openBlock(), _createElementBlock(\"div\", { key: 0 }, [\n          _createElementVNode(\"span\", null, \"foo\"),\n          _createTextVNode(\"bar\")\n        ])), _cache, 0)\n      : _withMemo([_ctx.x], () => (_openBlock(), _createBlock(_component_Comp, { key: 1 })), _cache, 1)\n  ]))\n}\"\n`;\n"
  },
  {
    "path": "packages/compiler-core/__tests__/transforms/__snapshots__/vModel.spec.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`compiler: transform v-model > compound expression (with prefixIdentifiers) 1`] = `\n\"import { openBlock as _openBlock, createElementBlock as _createElementBlock } from \"vue\"\n\nexport function render(_ctx, _cache) {\n  return (_openBlock(), _createElementBlock(\"input\", {\n    modelValue: _ctx.model[_ctx.index],\n    \"onUpdate:modelValue\": $event => ((_ctx.model[_ctx.index]) = $event)\n  }, null, 8 /* PROPS */, [\"modelValue\", \"onUpdate:modelValue\"]))\n}\"\n`;\n\nexports[`compiler: transform v-model > compound expression 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue\n\n    return (_openBlock(), _createElementBlock(\"input\", {\n      modelValue: model[index],\n      \"onUpdate:modelValue\": $event => ((model[index]) = $event)\n    }, null, 8 /* PROPS */, [\"modelValue\", \"onUpdate:modelValue\"]))\n  }\n}\"\n`;\n\nexports[`compiler: transform v-model > simple expression (with multilines) 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue\n\n    return (_openBlock(), _createElementBlock(\"input\", {\n      modelValue: \n model\n.\nfoo \n,\n      \"onUpdate:modelValue\": $event => ((\n model\n.\nfoo \n) = $event)\n    }, null, 8 /* PROPS */, [\"modelValue\", \"onUpdate:modelValue\"]))\n  }\n}\"\n`;\n\nexports[`compiler: transform v-model > simple expression (with prefixIdentifiers) 1`] = `\n\"import { openBlock as _openBlock, createElementBlock as _createElementBlock } from \"vue\"\n\nexport function render(_ctx, _cache) {\n  return (_openBlock(), _createElementBlock(\"input\", {\n    modelValue: _ctx.model,\n    \"onUpdate:modelValue\": $event => ((_ctx.model) = $event)\n  }, null, 8 /* PROPS */, [\"modelValue\", \"onUpdate:modelValue\"]))\n}\"\n`;\n\nexports[`compiler: transform v-model > simple expression 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue\n\n    return (_openBlock(), _createElementBlock(\"input\", {\n      modelValue: model,\n      \"onUpdate:modelValue\": $event => ((model) = $event)\n    }, null, 8 /* PROPS */, [\"modelValue\", \"onUpdate:modelValue\"]))\n  }\n}\"\n`;\n\nexports[`compiler: transform v-model > with argument 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue\n\n    return (_openBlock(), _createElementBlock(\"input\", {\n      \"foo-value\": model,\n      \"onUpdate:fooValue\": $event => ((model) = $event)\n    }, null, 40 /* PROPS, NEED_HYDRATION */, [\"foo-value\", \"onUpdate:fooValue\"]))\n  }\n}\"\n`;\n\nexports[`compiler: transform v-model > with dynamic argument (with prefixIdentifiers) 1`] = `\n\"import { normalizeProps as _normalizeProps, openBlock as _openBlock, createElementBlock as _createElementBlock } from \"vue\"\n\nexport function render(_ctx, _cache) {\n  return (_openBlock(), _createElementBlock(\"input\", _normalizeProps({\n    [_ctx.value]: _ctx.model,\n    [\"onUpdate:\" + _ctx.value]: $event => ((_ctx.model) = $event)\n  }), null, 16 /* FULL_PROPS */))\n}\"\n`;\n\nexports[`compiler: transform v-model > with dynamic argument 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { normalizeProps: _normalizeProps, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue\n\n    return (_openBlock(), _createElementBlock(\"input\", _normalizeProps({\n      [value]: model,\n      [\"onUpdate:\" + value]: $event => ((model) = $event)\n    }), null, 16 /* FULL_PROPS */))\n  }\n}\"\n`;\n"
  },
  {
    "path": "packages/compiler-core/__tests__/transforms/__snapshots__/vOnce.spec.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`compiler: v-once transform > as root node 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { setBlockTracking: _setBlockTracking, createElementVNode: _createElementVNode } = _Vue\n\n    return _cache[0] || (\n      _setBlockTracking(-1, true),\n      (_cache[0] = _createElementVNode(\"div\", { id: foo }, null, 8 /* PROPS */, [\"id\"])).cacheIndex = 0,\n      _setBlockTracking(1),\n      _cache[0]\n    )\n  }\n}\"\n`;\n\nexports[`compiler: v-once transform > on component 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { setBlockTracking: _setBlockTracking, resolveComponent: _resolveComponent, createVNode: _createVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue\n\n    const _component_Comp = _resolveComponent(\"Comp\")\n\n    return (_openBlock(), _createElementBlock(\"div\", null, [\n      _cache[0] || (\n        _setBlockTracking(-1, true),\n        (_cache[0] = _createVNode(_component_Comp, { id: foo }, null, 8 /* PROPS */, [\"id\"])).cacheIndex = 0,\n        _setBlockTracking(1),\n        _cache[0]\n      )\n    ]))\n  }\n}\"\n`;\n\nexports[`compiler: v-once transform > on nested plain element 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { setBlockTracking: _setBlockTracking, createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue\n\n    return (_openBlock(), _createElementBlock(\"div\", null, [\n      _cache[0] || (\n        _setBlockTracking(-1, true),\n        (_cache[0] = _createElementVNode(\"div\", { id: foo }, null, 8 /* PROPS */, [\"id\"])).cacheIndex = 0,\n        _setBlockTracking(1),\n        _cache[0]\n      )\n    ]))\n  }\n}\"\n`;\n\nexports[`compiler: v-once transform > on slot outlet 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { setBlockTracking: _setBlockTracking, renderSlot: _renderSlot, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue\n\n    return (_openBlock(), _createElementBlock(\"div\", null, [\n      _cache[0] || (\n        _setBlockTracking(-1, true),\n        (_cache[0] = _renderSlot($slots, \"default\")).cacheIndex = 0,\n        _setBlockTracking(1),\n        _cache[0]\n      )\n    ]))\n  }\n}\"\n`;\n\nexports[`compiler: v-once transform > with hoistStatic: true 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { setBlockTracking: _setBlockTracking, createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue\n\n    return (_openBlock(), _createElementBlock(\"div\", null, [\n      _cache[0] || (\n        _setBlockTracking(-1, true),\n        (_cache[0] = _createElementVNode(\"div\")).cacheIndex = 0,\n        _setBlockTracking(1),\n        _cache[0]\n      )\n    ]))\n  }\n}\"\n`;\n"
  },
  {
    "path": "packages/compiler-core/__tests__/transforms/__snapshots__/vSlot.spec.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`compiler: transform component slots > dynamically named slots 1`] = `\n\"const { toDisplayString: _toDisplayString, resolveComponent: _resolveComponent, withCtx: _withCtx, openBlock: _openBlock, createBlock: _createBlock } = Vue\n\nreturn function render(_ctx, _cache) {\n  const _component_Comp = _resolveComponent(\"Comp\")\n\n  return (_openBlock(), _createBlock(_component_Comp, null, {\n    [_ctx.one]: _withCtx(({ foo }) => [_toDisplayString(foo), _toDisplayString(_ctx.bar)]),\n    [_ctx.two]: _withCtx(({ bar }) => [_toDisplayString(_ctx.foo), _toDisplayString(bar)]),\n    _: 2 /* DYNAMIC */\n  }, 1024 /* DYNAMIC_SLOTS */))\n}\"\n`;\n\nexports[`compiler: transform component slots > implicit default slot 1`] = `\n\"const { createElementVNode: _createElementVNode, resolveComponent: _resolveComponent, withCtx: _withCtx, openBlock: _openBlock, createBlock: _createBlock } = Vue\n\nreturn function render(_ctx, _cache) {\n  const _component_Comp = _resolveComponent(\"Comp\")\n\n  return (_openBlock(), _createBlock(_component_Comp, null, {\n    default: _withCtx(() => [\n      _createElementVNode(\"div\")\n    ]),\n    _: 1 /* STABLE */\n  }))\n}\"\n`;\n\nexports[`compiler: transform component slots > named slot with v-for w/ prefixIdentifiers: true 1`] = `\n\"const { toDisplayString: _toDisplayString, resolveComponent: _resolveComponent, withCtx: _withCtx, renderList: _renderList, createSlots: _createSlots, openBlock: _openBlock, createBlock: _createBlock } = Vue\n\nreturn function render(_ctx, _cache) {\n  const _component_Comp = _resolveComponent(\"Comp\")\n\n  return (_openBlock(), _createBlock(_component_Comp, null, _createSlots({ _: 2 /* DYNAMIC */ }, [\n    _renderList(_ctx.list, (name) => {\n      return {\n        name: name,\n        fn: _withCtx(() => [_toDisplayString(name)])\n      }\n    })\n  ]), 1024 /* DYNAMIC_SLOTS */))\n}\"\n`;\n\nexports[`compiler: transform component slots > named slot with v-if + prefixIdentifiers: true 1`] = `\n\"const { toDisplayString: _toDisplayString, resolveComponent: _resolveComponent, withCtx: _withCtx, createSlots: _createSlots, openBlock: _openBlock, createBlock: _createBlock } = Vue\n\nreturn function render(_ctx, _cache) {\n  const _component_Comp = _resolveComponent(\"Comp\")\n\n  return (_openBlock(), _createBlock(_component_Comp, null, _createSlots({ _: 2 /* DYNAMIC */ }, [\n    (_ctx.ok)\n      ? {\n          name: \"one\",\n          fn: _withCtx((props) => [_toDisplayString(props)]),\n          key: \"0\"\n        }\n      : undefined\n  ]), 1024 /* DYNAMIC_SLOTS */))\n}\"\n`;\n\nexports[`compiler: transform component slots > named slot with v-if + v-else-if + v-else 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { resolveComponent: _resolveComponent, withCtx: _withCtx, createSlots: _createSlots, openBlock: _openBlock, createBlock: _createBlock } = _Vue\n\n    const _component_Comp = _resolveComponent(\"Comp\")\n\n    return (_openBlock(), _createBlock(_component_Comp, null, _createSlots({ _: 2 /* DYNAMIC */ }, [\n      ok\n        ? {\n            name: \"one\",\n            fn: _withCtx(() => [\"foo\"]),\n            key: \"0\"\n          }\n        : orNot\n          ? {\n              name: \"two\",\n              fn: _withCtx((props) => [\"bar\"]),\n              key: \"1\"\n            }\n          : {\n              name: \"one\",\n              fn: _withCtx(() => [\"baz\"]),\n              key: \"2\"\n            }\n    ]), 1024 /* DYNAMIC_SLOTS */))\n  }\n}\"\n`;\n\nexports[`compiler: transform component slots > named slot with v-if 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { resolveComponent: _resolveComponent, withCtx: _withCtx, createSlots: _createSlots, openBlock: _openBlock, createBlock: _createBlock } = _Vue\n\n    const _component_Comp = _resolveComponent(\"Comp\")\n\n    return (_openBlock(), _createBlock(_component_Comp, null, _createSlots({ _: 2 /* DYNAMIC */ }, [\n      ok\n        ? {\n            name: \"one\",\n            fn: _withCtx(() => [\"hello\"]),\n            key: \"0\"\n          }\n        : undefined\n    ]), 1024 /* DYNAMIC_SLOTS */))\n  }\n}\"\n`;\n\nexports[`compiler: transform component slots > named slots w/ implicit default slot 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { createElementVNode: _createElementVNode, resolveComponent: _resolveComponent, withCtx: _withCtx, openBlock: _openBlock, createBlock: _createBlock } = _Vue\n\n    const _component_Comp = _resolveComponent(\"Comp\")\n\n    return (_openBlock(), _createBlock(_component_Comp, null, {\n      one: _withCtx(() => [\"foo\"]),\n      default: _withCtx(() => [\n        \"bar\",\n        _createElementVNode(\"span\")\n      ]),\n      _: 1 /* STABLE */\n    }))\n  }\n}\"\n`;\n\nexports[`compiler: transform component slots > named slots w/ implicit default slot containing non-breaking space 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { resolveComponent: _resolveComponent, withCtx: _withCtx, openBlock: _openBlock, createBlock: _createBlock } = _Vue\n\n    const _component_Comp = _resolveComponent(\"Comp\")\n\n    return (_openBlock(), _createBlock(_component_Comp, null, {\n      one: _withCtx(() => [\"foo\"]),\n      default: _withCtx(() => [\"   \"]),\n      _: 1 /* STABLE */\n    }))\n  }\n}\"\n`;\n\nexports[`compiler: transform component slots > nested slots scoping 1`] = `\n\"const { toDisplayString: _toDisplayString, resolveComponent: _resolveComponent, withCtx: _withCtx, createVNode: _createVNode, openBlock: _openBlock, createBlock: _createBlock } = Vue\n\nreturn function render(_ctx, _cache) {\n  const _component_Inner = _resolveComponent(\"Inner\")\n  const _component_Comp = _resolveComponent(\"Comp\")\n\n  return (_openBlock(), _createBlock(_component_Comp, null, {\n    default: _withCtx(({ foo }) => [\n      _createVNode(_component_Inner, null, {\n        default: _withCtx(({ bar }) => [_toDisplayString(foo), _toDisplayString(bar), _toDisplayString(_ctx.baz)]),\n        _: 2 /* DYNAMIC */\n      }, 1024 /* DYNAMIC_SLOTS */),\n      \" \",\n      _toDisplayString(foo),\n      _toDisplayString(_ctx.bar),\n      _toDisplayString(_ctx.baz)\n    ]),\n    _: 1 /* STABLE */\n  }))\n}\"\n`;\n\nexports[`compiler: transform component slots > on component dynamically named slot 1`] = `\n\"const { toDisplayString: _toDisplayString, resolveComponent: _resolveComponent, withCtx: _withCtx, openBlock: _openBlock, createBlock: _createBlock } = Vue\n\nreturn function render(_ctx, _cache) {\n  const _component_Comp = _resolveComponent(\"Comp\")\n\n  return (_openBlock(), _createBlock(_component_Comp, null, {\n    [_ctx.named]: _withCtx(({ foo }) => [_toDisplayString(foo), _toDisplayString(_ctx.bar)]),\n    _: 2 /* DYNAMIC */\n  }, 1024 /* DYNAMIC_SLOTS */))\n}\"\n`;\n\nexports[`compiler: transform component slots > on component named slot 1`] = `\n\"const { toDisplayString: _toDisplayString, resolveComponent: _resolveComponent, withCtx: _withCtx, openBlock: _openBlock, createBlock: _createBlock } = Vue\n\nreturn function render(_ctx, _cache) {\n  const _component_Comp = _resolveComponent(\"Comp\")\n\n  return (_openBlock(), _createBlock(_component_Comp, null, {\n    named: _withCtx(({ foo }) => [_toDisplayString(foo), _toDisplayString(_ctx.bar)]),\n    _: 1 /* STABLE */\n  }))\n}\"\n`;\n\nexports[`compiler: transform component slots > on-component default slot 1`] = `\n\"const { toDisplayString: _toDisplayString, resolveComponent: _resolveComponent, withCtx: _withCtx, openBlock: _openBlock, createBlock: _createBlock } = Vue\n\nreturn function render(_ctx, _cache) {\n  const _component_Comp = _resolveComponent(\"Comp\")\n\n  return (_openBlock(), _createBlock(_component_Comp, null, {\n    default: _withCtx(({ foo }) => [_toDisplayString(foo), _toDisplayString(_ctx.bar)]),\n    _: 1 /* STABLE */\n  }))\n}\"\n`;\n\nexports[`compiler: transform component slots > template named slots 1`] = `\n\"const { toDisplayString: _toDisplayString, resolveComponent: _resolveComponent, withCtx: _withCtx, openBlock: _openBlock, createBlock: _createBlock } = Vue\n\nreturn function render(_ctx, _cache) {\n  const _component_Comp = _resolveComponent(\"Comp\")\n\n  return (_openBlock(), _createBlock(_component_Comp, null, {\n    one: _withCtx(({ foo }) => [_toDisplayString(foo), _toDisplayString(_ctx.bar)]),\n    two: _withCtx(({ bar }) => [_toDisplayString(_ctx.foo), _toDisplayString(bar)]),\n    _: 1 /* STABLE */\n  }))\n}\"\n`;\n\nexports[`compiler: transform component slots > with whitespace: 'preserve' > implicit default slot 1`] = `\n\"const { createElementVNode: _createElementVNode, resolveComponent: _resolveComponent, withCtx: _withCtx, openBlock: _openBlock, createBlock: _createBlock } = Vue\n\nreturn function render(_ctx, _cache) {\n  const _component_Comp = _resolveComponent(\"Comp\")\n\n  return (_openBlock(), _createBlock(_component_Comp, null, {\n    header: _withCtx(() => [\" Header \"]),\n    default: _withCtx(() => [\n      \" \",\n      _createElementVNode(\"p\")\n    ]),\n    _: 1 /* STABLE */\n  }))\n}\"\n`;\n\nexports[`compiler: transform component slots > with whitespace: 'preserve' > implicit default slot with non-breaking space 1`] = `\n\"const { resolveComponent: _resolveComponent, withCtx: _withCtx, openBlock: _openBlock, createBlock: _createBlock } = Vue\n\nreturn function render(_ctx, _cache) {\n  const _component_Comp = _resolveComponent(\"Comp\")\n\n  return (_openBlock(), _createBlock(_component_Comp, null, {\n    header: _withCtx(() => [\" Header \"]),\n    default: _withCtx(() => [\"\\\\n         \\\\n        \"]),\n    _: 1 /* STABLE */\n  }))\n}\"\n`;\n\nexports[`compiler: transform component slots > with whitespace: 'preserve' > named default slot + implicit whitespace content 1`] = `\n\"const { resolveComponent: _resolveComponent, withCtx: _withCtx, openBlock: _openBlock, createBlock: _createBlock } = Vue\n\nreturn function render(_ctx, _cache) {\n  const _component_Comp = _resolveComponent(\"Comp\")\n\n  return (_openBlock(), _createBlock(_component_Comp, null, {\n    header: _withCtx(() => [\" Header \"]),\n    default: _withCtx(() => [\" Default \"]),\n    _: 1 /* STABLE */\n  }))\n}\"\n`;\n\nexports[`compiler: transform component slots > with whitespace: 'preserve' > named slot with v-if + v-else 1`] = `\n\"const { resolveComponent: _resolveComponent, withCtx: _withCtx, createSlots: _createSlots, openBlock: _openBlock, createBlock: _createBlock } = Vue\n\nreturn function render(_ctx, _cache) {\n  const _component_Comp = _resolveComponent(\"Comp\")\n\n  return (_openBlock(), _createBlock(_component_Comp, null, _createSlots({ _: 2 /* DYNAMIC */ }, [\n    ok\n      ? {\n          name: \"one\",\n          fn: _withCtx(() => [\"foo\"]),\n          key: \"0\"\n        }\n      : {\n          name: \"two\",\n          fn: _withCtx(() => [\"baz\"]),\n          key: \"1\"\n        }\n  ]), 1024 /* DYNAMIC_SLOTS */))\n}\"\n`;\n\nexports[`compiler: transform component slots > with whitespace: 'preserve' > named slot with v-if + v-else and comments 1`] = `\n\"const { createTextVNode: _createTextVNode, createCommentVNode: _createCommentVNode, resolveComponent: _resolveComponent, withCtx: _withCtx, createSlots: _createSlots, openBlock: _openBlock, createBlock: _createBlock } = Vue\n\nreturn function render(_ctx, _cache) {\n  const _component_Comp = _resolveComponent(\"Comp\")\n\n  return (_openBlock(), _createBlock(_component_Comp, null, _createSlots({ _: 2 /* DYNAMIC */ }, [\n    ok\n      ? {\n          name: \"one\",\n          fn: _withCtx(() => [\n            _createTextVNode(\"foo\")\n          ]),\n          key: \"0\"\n        }\n      : {\n          name: \"two\",\n          fn: _withCtx(() => [\n            _createTextVNode(\"baz\")\n          ]),\n          key: \"1\"\n        }\n  ]), 1024 /* DYNAMIC_SLOTS */))\n}\"\n`;\n\nexports[`compiler: transform component slots > with whitespace: 'preserve' > should not generate whitespace only default slot 1`] = `\n\"const { resolveComponent: _resolveComponent, withCtx: _withCtx, openBlock: _openBlock, createBlock: _createBlock } = Vue\n\nreturn function render(_ctx, _cache) {\n  const _component_Comp = _resolveComponent(\"Comp\")\n\n  return (_openBlock(), _createBlock(_component_Comp, null, {\n    header: _withCtx(() => [\" Header \"]),\n    footer: _withCtx(() => [\" Footer \"]),\n    _: 1 /* STABLE */\n  }))\n}\"\n`;\n"
  },
  {
    "path": "packages/compiler-core/__tests__/transforms/cacheStatic.spec.ts",
    "content": "import {\n  type CompilerOptions,\n  ConstantTypes,\n  type ElementNode,\n  type ForNode,\n  type IfNode,\n  NodeTypes,\n  type VNodeCall,\n  generate,\n  baseParse as parse,\n  transform,\n} from '../../src'\nimport {\n  FRAGMENT,\n  NORMALIZE_CLASS,\n  RENDER_LIST,\n} from '../../src/runtimeHelpers'\nimport { transformElement } from '../../src/transforms/transformElement'\nimport { transformExpression } from '../../src/transforms/transformExpression'\nimport { transformIf } from '../../src/transforms/vIf'\nimport { transformFor } from '../../src/transforms/vFor'\nimport { transformBind } from '../../src/transforms/vBind'\nimport { transformOn } from '../../src/transforms/vOn'\nimport { createObjectMatcher } from '../testUtils'\nimport { transformText } from '../../src/transforms/transformText'\nimport { PatchFlags } from '@vue/shared'\n\nconst cachedChildrenArrayMatcher = (\n  tags: string[],\n  needArraySpread = true,\n) => ({\n  type: NodeTypes.JS_CACHE_EXPRESSION,\n  needArraySpread,\n  value: {\n    type: NodeTypes.JS_ARRAY_EXPRESSION,\n    elements: tags.map(tag => {\n      if (tag === '') {\n        return {\n          type: NodeTypes.TEXT_CALL,\n        }\n      } else {\n        return {\n          type: NodeTypes.ELEMENT,\n          codegenNode: {\n            type: NodeTypes.VNODE_CALL,\n            tag: JSON.stringify(tag),\n          },\n        }\n      }\n    }),\n  },\n})\n\nfunction transformWithCache(template: string, options: CompilerOptions = {}) {\n  const ast = parse(template)\n  transform(ast, {\n    hoistStatic: true,\n    nodeTransforms: [\n      transformIf,\n      transformFor,\n      ...(options.prefixIdentifiers ? [transformExpression] : []),\n      transformElement,\n      transformText,\n    ],\n    directiveTransforms: {\n      on: transformOn,\n      bind: transformBind,\n    },\n    ...options,\n  })\n  expect(ast.codegenNode).toMatchObject({\n    type: NodeTypes.VNODE_CALL,\n    isBlock: true,\n  })\n  return ast\n}\n\ndescribe('compiler: cacheStatic transform', () => {\n  test('should NOT cache root node', () => {\n    // if the whole tree is static, the root still needs to be a block\n    // so that it's patched in optimized mode to skip children\n    const root = transformWithCache(`<div/>`)\n    expect(root.codegenNode).toMatchObject({\n      type: NodeTypes.VNODE_CALL,\n      tag: `\"div\"`,\n    })\n    expect(root.cached.length).toBe(0)\n  })\n\n  test('cache root node children', () => {\n    // we don't have access to the root codegenNode during the transform\n    // so we only cache each child individually\n    const root = transformWithCache(\n      `<span class=\"inline\">hello</span><span class=\"inline\">hello</span>`,\n    )\n    expect(root.codegenNode).toMatchObject({\n      type: NodeTypes.VNODE_CALL,\n      children: [\n        { codegenNode: { type: NodeTypes.JS_CACHE_EXPRESSION } },\n        { codegenNode: { type: NodeTypes.JS_CACHE_EXPRESSION } },\n      ],\n    })\n    expect(root.cached.length).toBe(2)\n  })\n\n  test('cache single children array', () => {\n    const root = transformWithCache(\n      `<div><span class=\"inline\">hello</span></div>`,\n    )\n    expect(root.codegenNode).toMatchObject({\n      tag: `\"div\"`,\n      props: undefined,\n      children: cachedChildrenArrayMatcher(['span']),\n    })\n    expect(root.cached.length).toBe(1)\n    expect(generate(root).code).toMatchSnapshot()\n  })\n\n  test('cache nested children array', () => {\n    const root = transformWithCache(\n      `<div><p><span/><span/></p><p><span/><span/></p></div>`,\n    )\n    expect((root.codegenNode as VNodeCall).children).toMatchObject(\n      cachedChildrenArrayMatcher(['p', 'p']),\n    )\n    expect(root.cached.length).toBe(1)\n    expect(generate(root).code).toMatchSnapshot()\n  })\n\n  test('cache nested static tree with comments', () => {\n    const root = transformWithCache(`<div><div><!--comment--></div></div>`)\n    expect((root.codegenNode as VNodeCall).children).toMatchObject(\n      cachedChildrenArrayMatcher(['div']),\n    )\n    expect(root.cached.length).toBe(1)\n    expect(generate(root).code).toMatchSnapshot()\n  })\n\n  test('cache siblings including text with common non-hoistable parent', () => {\n    const root = transformWithCache(`<div><span/>foo<div/></div>`)\n    expect((root.codegenNode as VNodeCall).children).toMatchObject(\n      cachedChildrenArrayMatcher(['span', '', 'div']),\n    )\n    expect(root.cached.length).toBe(1)\n    expect(generate(root).code).toMatchSnapshot()\n  })\n\n  test('cache inside default slot', () => {\n    const root = transformWithCache(`<Foo>{{x}}<span/></Foo>`)\n    expect((root.codegenNode as VNodeCall).children).toMatchObject({\n      properties: [\n        {\n          key: { content: 'default' },\n          value: {\n            type: NodeTypes.JS_FUNCTION_EXPRESSION,\n            returns: [\n              {\n                type: NodeTypes.TEXT_CALL,\n              },\n              // first slot child cached\n              {\n                type: NodeTypes.ELEMENT,\n                codegenNode: {\n                  type: NodeTypes.JS_CACHE_EXPRESSION,\n                },\n              },\n            ],\n          },\n        },\n        {\n          /* _ slot flag */\n        },\n      ],\n    })\n  })\n\n  test('cache default slot as a whole', () => {\n    const root = transformWithCache(`<Foo><span/><span/></Foo>`)\n    expect((root.codegenNode as VNodeCall).children).toMatchObject({\n      properties: [\n        {\n          key: { content: 'default' },\n          value: {\n            type: NodeTypes.JS_FUNCTION_EXPRESSION,\n            returns: {\n              type: NodeTypes.JS_CACHE_EXPRESSION,\n              value: {\n                type: NodeTypes.JS_ARRAY_EXPRESSION,\n                elements: [\n                  { type: NodeTypes.ELEMENT },\n                  { type: NodeTypes.ELEMENT },\n                ],\n              },\n            },\n          },\n        },\n        {\n          /* _ slot flag */\n        },\n      ],\n    })\n  })\n\n  test('cache inside named slot', () => {\n    const root = transformWithCache(\n      `<Foo><template #foo>{{x}}<span/></template></Foo>`,\n    )\n    expect((root.codegenNode as VNodeCall).children).toMatchObject({\n      properties: [\n        {\n          key: { content: 'foo' },\n          value: {\n            type: NodeTypes.JS_FUNCTION_EXPRESSION,\n            returns: [\n              {\n                type: NodeTypes.TEXT_CALL,\n              },\n              // first slot child cached\n              {\n                type: NodeTypes.ELEMENT,\n                codegenNode: {\n                  type: NodeTypes.JS_CACHE_EXPRESSION,\n                },\n              },\n            ],\n          },\n        },\n        {\n          /* _ slot flag */\n        },\n      ],\n    })\n  })\n\n  test('cache named slot as a whole', () => {\n    const root = transformWithCache(\n      `<Foo><template #foo><span/><span/></template></Foo>`,\n    )\n    expect((root.codegenNode as VNodeCall).children).toMatchObject({\n      properties: [\n        {\n          key: { content: 'foo' },\n          value: {\n            type: NodeTypes.JS_FUNCTION_EXPRESSION,\n            returns: {\n              type: NodeTypes.JS_CACHE_EXPRESSION,\n              value: {\n                type: NodeTypes.JS_ARRAY_EXPRESSION,\n                elements: [\n                  { type: NodeTypes.ELEMENT },\n                  { type: NodeTypes.ELEMENT },\n                ],\n              },\n            },\n          },\n        },\n        {\n          /* _ slot flag */\n        },\n      ],\n    })\n  })\n\n  test('cache dynamically named slot as a whole', () => {\n    const root = transformWithCache(\n      `<Foo><template #[foo]><span/><span/></template></Foo>`,\n    )\n    expect((root.codegenNode as VNodeCall).children).toMatchObject({\n      properties: [\n        {\n          key: { content: 'foo', isStatic: false },\n          value: {\n            type: NodeTypes.JS_FUNCTION_EXPRESSION,\n            returns: {\n              type: NodeTypes.JS_CACHE_EXPRESSION,\n              value: {\n                type: NodeTypes.JS_ARRAY_EXPRESSION,\n                elements: [\n                  { type: NodeTypes.ELEMENT },\n                  { type: NodeTypes.ELEMENT },\n                ],\n              },\n            },\n          },\n        },\n        {\n          /* _ slot flag */\n        },\n      ],\n    })\n  })\n\n  test('cache dynamically named (expression) slot as a whole', () => {\n    const root = transformWithCache(\n      `<Foo><template #[foo+1]><span/><span/></template></Foo>`,\n      { prefixIdentifiers: true },\n    )\n    expect((root.codegenNode as VNodeCall).children).toMatchObject({\n      properties: [\n        {\n          key: { type: NodeTypes.COMPOUND_EXPRESSION },\n          value: {\n            type: NodeTypes.JS_FUNCTION_EXPRESSION,\n            returns: {\n              type: NodeTypes.JS_CACHE_EXPRESSION,\n              value: {\n                type: NodeTypes.JS_ARRAY_EXPRESSION,\n                elements: [\n                  { type: NodeTypes.ELEMENT },\n                  { type: NodeTypes.ELEMENT },\n                ],\n              },\n            },\n          },\n        },\n        {\n          /* _ slot flag */\n        },\n      ],\n    })\n  })\n\n  test('should NOT cache components', () => {\n    const root = transformWithCache(`<div><Comp/></div>`)\n    expect((root.codegenNode as VNodeCall).children).toMatchObject([\n      {\n        type: NodeTypes.ELEMENT,\n        codegenNode: {\n          type: NodeTypes.VNODE_CALL,\n          tag: `_component_Comp`,\n        },\n      },\n    ])\n    expect(root.cached.length).toBe(0)\n    expect(generate(root).code).toMatchSnapshot()\n  })\n\n  test('should NOT cache element with dynamic props (but hoist the props list)', () => {\n    const root = transformWithCache(`<div><div :id=\"foo\"/></div>`)\n    expect(root.hoists.length).toBe(1)\n    expect((root.codegenNode as VNodeCall).children).toMatchObject([\n      {\n        type: NodeTypes.ELEMENT,\n        codegenNode: {\n          type: NodeTypes.VNODE_CALL,\n          tag: `\"div\"`,\n          props: createObjectMatcher({\n            id: `[foo]`,\n          }),\n          children: undefined,\n          patchFlag: PatchFlags.PROPS,\n          dynamicProps: {\n            type: NodeTypes.SIMPLE_EXPRESSION,\n            content: `_hoisted_1`,\n            isStatic: false,\n          },\n        },\n      },\n    ])\n    expect(root.cached.length).toBe(0)\n    expect(generate(root).code).toMatchSnapshot()\n  })\n\n  test('cache element with static key', () => {\n    const root = transformWithCache(`<div><div key=\"foo\"/></div>`)\n    expect(root.codegenNode).toMatchObject({\n      tag: `\"div\"`,\n      props: undefined,\n      children: cachedChildrenArrayMatcher(['div']),\n    })\n    expect(root.cached.length).toBe(1)\n    expect(generate(root).code).toMatchSnapshot()\n  })\n\n  test('should NOT cache element with dynamic key', () => {\n    const root = transformWithCache(`<div><div :key=\"foo\"/></div>`)\n    expect((root.codegenNode as VNodeCall).children).toMatchObject([\n      {\n        type: NodeTypes.ELEMENT,\n        codegenNode: {\n          type: NodeTypes.VNODE_CALL,\n          tag: `\"div\"`,\n          props: createObjectMatcher({\n            key: `[foo]`,\n          }),\n        },\n      },\n    ])\n    expect(root.cached.length).toBe(0)\n    expect(generate(root).code).toMatchSnapshot()\n  })\n\n  test('should NOT cache element with dynamic ref', () => {\n    const root = transformWithCache(`<div><div :ref=\"foo\"/></div>`)\n    expect((root.codegenNode as VNodeCall).children).toMatchObject([\n      {\n        type: NodeTypes.ELEMENT,\n        codegenNode: {\n          type: NodeTypes.VNODE_CALL,\n          tag: `\"div\"`,\n          props: createObjectMatcher({\n            ref: `[foo]`,\n          }),\n          children: undefined,\n          patchFlag: PatchFlags.NEED_PATCH,\n        },\n      },\n    ])\n    expect(root.cached.length).toBe(0)\n    expect(generate(root).code).toMatchSnapshot()\n  })\n\n  test('hoist static props for elements with directives', () => {\n    const root = transformWithCache(`<div><div id=\"foo\" v-foo/></div>`)\n    expect(root.hoists).toMatchObject([createObjectMatcher({ id: 'foo' })])\n    expect((root.codegenNode as VNodeCall).children).toMatchObject([\n      {\n        type: NodeTypes.ELEMENT,\n        codegenNode: {\n          type: NodeTypes.VNODE_CALL,\n          tag: `\"div\"`,\n          props: {\n            type: NodeTypes.SIMPLE_EXPRESSION,\n            content: `_hoisted_1`,\n          },\n          children: undefined,\n          patchFlag: PatchFlags.NEED_PATCH,\n          directives: {\n            type: NodeTypes.JS_ARRAY_EXPRESSION,\n          },\n        },\n      },\n    ])\n    expect(root.cached.length).toBe(0)\n    expect(generate(root).code).toMatchSnapshot()\n  })\n\n  test('hoist static props for elements with dynamic text children', () => {\n    const root = transformWithCache(\n      `<div><div id=\"foo\">{{ hello }}</div></div>`,\n    )\n    expect(root.hoists).toMatchObject([createObjectMatcher({ id: 'foo' })])\n    expect((root.codegenNode as VNodeCall).children).toMatchObject([\n      {\n        type: NodeTypes.ELEMENT,\n        codegenNode: {\n          type: NodeTypes.VNODE_CALL,\n          tag: `\"div\"`,\n          props: { content: `_hoisted_1` },\n          children: { type: NodeTypes.INTERPOLATION },\n          patchFlag: PatchFlags.TEXT,\n        },\n      },\n    ])\n    expect(root.cached.length).toBe(0)\n    expect(generate(root).code).toMatchSnapshot()\n  })\n\n  test('hoist static props for elements with unhoistable children', () => {\n    const root = transformWithCache(`<div><div id=\"foo\"><Comp/></div></div>`)\n    expect(root.hoists).toMatchObject([createObjectMatcher({ id: 'foo' })])\n    expect((root.codegenNode as VNodeCall).children).toMatchObject([\n      {\n        type: NodeTypes.ELEMENT,\n        codegenNode: {\n          type: NodeTypes.VNODE_CALL,\n          tag: `\"div\"`,\n          props: { content: `_hoisted_1` },\n          children: [{ type: NodeTypes.ELEMENT, tag: `Comp` }],\n        },\n      },\n    ])\n    expect(root.cached.length).toBe(0)\n    expect(generate(root).code).toMatchSnapshot()\n  })\n\n  test('should cache v-if props/children if static', () => {\n    const root = transformWithCache(\n      `<div><div v-if=\"ok\" id=\"foo\"><span/></div></div>`,\n    )\n    expect(root.hoists).toMatchObject([\n      createObjectMatcher({\n        key: `[0]`, // key injected by v-if branch\n        id: 'foo',\n      }),\n    ])\n    expect(\n      ((root.children[0] as ElementNode).children[0] as IfNode).codegenNode,\n    ).toMatchObject({\n      type: NodeTypes.JS_CONDITIONAL_EXPRESSION,\n      consequent: {\n        // blocks should NOT be cached\n        type: NodeTypes.VNODE_CALL,\n        tag: `\"div\"`,\n        props: { content: `_hoisted_1` },\n        children: cachedChildrenArrayMatcher(['span']),\n      },\n    })\n    expect(root.cached.length).toBe(1)\n    expect(generate(root).code).toMatchSnapshot()\n  })\n\n  test('should hoist v-for children if static', () => {\n    const root = transformWithCache(\n      `<div><div v-for=\"i in list\" id=\"foo\"><span/></div></div>`,\n    )\n    expect(root.hoists).toMatchObject([\n      createObjectMatcher({\n        id: 'foo',\n      }),\n    ])\n    const forBlockCodegen = (\n      (root.children[0] as ElementNode).children[0] as ForNode\n    ).codegenNode\n    expect(forBlockCodegen).toMatchObject({\n      type: NodeTypes.VNODE_CALL,\n      tag: FRAGMENT,\n      props: undefined,\n      children: {\n        type: NodeTypes.JS_CALL_EXPRESSION,\n        callee: RENDER_LIST,\n      },\n      patchFlag: PatchFlags.UNKEYED_FRAGMENT,\n    })\n    const innerBlockCodegen = forBlockCodegen!.children.arguments[1]\n    expect(innerBlockCodegen.returns).toMatchObject({\n      type: NodeTypes.VNODE_CALL,\n      tag: `\"div\"`,\n      props: { content: `_hoisted_1` },\n      children: cachedChildrenArrayMatcher(['span']),\n    })\n    expect(root.cached.length).toBe(1)\n    expect(generate(root).code).toMatchSnapshot()\n  })\n\n  test('should hoist props for root with single element excluding comments', () => {\n    // deeply nested div to trigger stringification condition\n    const root = transformWithCache(\n      `<!--comment--><div id=\"a\"><div id=\"b\"><div id=\"c\"><div id=\"d\"><div id=\"e\">hello</div></div></div></div></div>`,\n    )\n    expect(root.cached.length).toBe(1)\n    expect(root.hoists).toMatchObject([createObjectMatcher({ id: 'a' })])\n\n    expect((root.codegenNode as VNodeCall).children).toMatchObject([\n      {\n        type: NodeTypes.COMMENT,\n        content: 'comment',\n      },\n      {\n        type: NodeTypes.ELEMENT,\n        codegenNode: {\n          type: NodeTypes.VNODE_CALL,\n          tag: `\"div\"`,\n          props: { content: `_hoisted_1` },\n          children: { type: NodeTypes.JS_CACHE_EXPRESSION },\n        },\n      },\n    ])\n    expect(generate(root).code).toMatchSnapshot()\n  })\n\n  describe('prefixIdentifiers', () => {\n    test('cache nested static tree with static interpolation', () => {\n      const root = transformWithCache(\n        `<div><span>foo {{ 1 }} {{ true }}</span></div>`,\n        {\n          prefixIdentifiers: true,\n        },\n      )\n      expect(root.codegenNode).toMatchObject({\n        tag: `\"div\"`,\n        props: undefined,\n        children: cachedChildrenArrayMatcher(['span']),\n      })\n      expect(root.cached.length).toBe(1)\n      expect(generate(root).code).toMatchSnapshot()\n    })\n\n    test('cache nested static tree with static prop value', () => {\n      const root = transformWithCache(\n        `<div><span :foo=\"0\">{{ 1 }}</span></div>`,\n        {\n          prefixIdentifiers: true,\n        },\n      )\n      expect(root.codegenNode).toMatchObject({\n        tag: `\"div\"`,\n        props: undefined,\n        children: cachedChildrenArrayMatcher(['span']),\n      })\n      expect(root.cached.length).toBe(1)\n      expect(generate(root).code).toMatchSnapshot()\n    })\n\n    test('hoist class with static object value', () => {\n      const root = transformWithCache(\n        `<div><span :class=\"{ foo: true }\">{{ bar }}</span></div>`,\n        {\n          prefixIdentifiers: true,\n        },\n      )\n\n      expect(root.hoists).toMatchObject([\n        {\n          type: NodeTypes.JS_OBJECT_EXPRESSION,\n          properties: [\n            {\n              key: {\n                content: `class`,\n                isStatic: true,\n                constType: ConstantTypes.CAN_STRINGIFY,\n              },\n              value: {\n                type: NodeTypes.JS_CALL_EXPRESSION,\n                callee: NORMALIZE_CLASS,\n                arguments: [\n                  {\n                    content: `{ foo: true }`,\n                    isStatic: false,\n                    constType: ConstantTypes.CAN_STRINGIFY,\n                  },\n                ],\n              },\n            },\n          ],\n        },\n      ])\n      expect(root.codegenNode).toMatchObject({\n        tag: `\"div\"`,\n        props: undefined,\n        children: [\n          {\n            type: NodeTypes.ELEMENT,\n            codegenNode: {\n              type: NodeTypes.VNODE_CALL,\n              tag: `\"span\"`,\n              props: {\n                type: NodeTypes.SIMPLE_EXPRESSION,\n                content: `_hoisted_1`,\n              },\n              children: {\n                type: NodeTypes.INTERPOLATION,\n                content: {\n                  content: `_ctx.bar`,\n                  isStatic: false,\n                  constType: ConstantTypes.NOT_CONSTANT,\n                },\n              },\n              patchFlag: PatchFlags.TEXT,\n            },\n          },\n        ],\n      })\n      expect(generate(root).code).toMatchSnapshot()\n    })\n\n    test('should NOT cache expressions that refer scope variables', () => {\n      const root = transformWithCache(\n        `<div><p v-for=\"o in list\"><span>{{ o }}</span></p></div>`,\n        {\n          prefixIdentifiers: true,\n        },\n      )\n\n      expect(root.cached.length).toBe(0)\n      expect(generate(root).code).toMatchSnapshot()\n    })\n\n    test('should NOT cache expressions that refer scope variables (2)', () => {\n      const root = transformWithCache(\n        `<div><p v-for=\"o in list\"><span>{{ o + 'foo' }}</span></p></div>`,\n        {\n          prefixIdentifiers: true,\n        },\n      )\n\n      expect(root.cached.length).toBe(0)\n      expect(generate(root).code).toMatchSnapshot()\n    })\n\n    test('should NOT cache expressions that refer scope variables (v-slot)', () => {\n      const root = transformWithCache(\n        `<Comp v-slot=\"{ foo }\">{{ foo }}</Comp>`,\n        {\n          prefixIdentifiers: true,\n        },\n      )\n\n      expect(root.cached.length).toBe(0)\n      expect(generate(root).code).toMatchSnapshot()\n    })\n\n    test('should NOT cache elements with cached handlers', () => {\n      const root = transformWithCache(\n        `<div><div><div @click=\"foo\"/></div></div>`,\n        {\n          prefixIdentifiers: true,\n          cacheHandlers: true,\n        },\n      )\n\n      expect(root.cached.length).toBe(1)\n      expect(root.hoists.length).toBe(0)\n      expect(\n        generate(root, {\n          mode: 'module',\n          prefixIdentifiers: true,\n        }).code,\n      ).toMatchSnapshot()\n    })\n\n    test('should NOT cache elements with cached handlers + other bindings', () => {\n      const root = transformWithCache(\n        `<div><div><div :class=\"{}\" @click=\"foo\"/></div></div>`,\n        {\n          prefixIdentifiers: true,\n          cacheHandlers: true,\n        },\n      )\n\n      expect(root.cached.length).toBe(1)\n      expect(root.hoists.length).toBe(0)\n      expect(\n        generate(root, {\n          mode: 'module',\n          prefixIdentifiers: true,\n        }).code,\n      ).toMatchSnapshot()\n    })\n\n    test('should NOT cache keyed template v-for with plain element child', () => {\n      const root = transformWithCache(\n        `<div><template v-for=\"item in items\" :key=\"item\"><span/></template></div>`,\n      )\n      expect(root.hoists.length).toBe(0)\n      expect(generate(root).code).toMatchSnapshot()\n    })\n\n    test('should NOT cache SVG with directives', () => {\n      const root = transformWithCache(\n        `<div><svg v-foo><path d=\"M2,3H5.5L12\"/></svg></div>`,\n      )\n      expect(root.cached.length).toBe(1)\n      expect(root.codegenNode).toMatchObject({\n        children: [\n          {\n            tag: 'svg',\n            // only cache the children, not the svg tag itself\n            codegenNode: {\n              children: {\n                type: NodeTypes.JS_CACHE_EXPRESSION,\n              },\n            },\n          },\n        ],\n      })\n      expect(generate(root).code).toMatchSnapshot()\n    })\n\n    test('clone hoisted array children in v-for + HMR mode', () => {\n      const root = transformWithCache(\n        `<div><div v-for=\"i in 1\"><span class=\"hi\"></span></div></div>`,\n        {\n          hmr: true,\n        },\n      )\n      expect(root.cached.length).toBe(1)\n      const forBlockCodegen = (\n        (root.children[0] as ElementNode).children[0] as ForNode\n      ).codegenNode\n      expect(forBlockCodegen).toMatchObject({\n        type: NodeTypes.VNODE_CALL,\n        tag: FRAGMENT,\n        props: undefined,\n        children: {\n          type: NodeTypes.JS_CALL_EXPRESSION,\n          callee: RENDER_LIST,\n        },\n        patchFlag: PatchFlags.UNKEYED_FRAGMENT,\n      })\n      const innerBlockCodegen = forBlockCodegen!.children.arguments[1]\n      expect(innerBlockCodegen.returns).toMatchObject({\n        type: NodeTypes.VNODE_CALL,\n        tag: `\"div\"`,\n        children: cachedChildrenArrayMatcher(\n          ['span'],\n          true /* needArraySpread */,\n        ),\n      })\n      expect(generate(root).code).toMatchSnapshot()\n    })\n  })\n})\n"
  },
  {
    "path": "packages/compiler-core/__tests__/transforms/noopDirectiveTransform.spec.ts",
    "content": "import {\n  type ElementNode,\n  type VNodeCall,\n  noopDirectiveTransform,\n  baseParse as parse,\n  transform,\n} from '../../src'\nimport { transformElement } from '../../src/transforms/transformElement'\n\ndescribe('compiler: noop directive transform', () => {\n  test('should add no props to DOM', () => {\n    const ast = parse(`<div v-noop/>`)\n    transform(ast, {\n      nodeTransforms: [transformElement],\n      directiveTransforms: {\n        noop: noopDirectiveTransform,\n      },\n    })\n    const node = ast.children[0] as ElementNode\n    // As v-noop adds no properties the codegen should be identical to\n    // rendering a div with no props or reactive data (so just the tag as the arg)\n    expect((node.codegenNode as VNodeCall).props).toBeUndefined()\n  })\n})\n"
  },
  {
    "path": "packages/compiler-core/__tests__/transforms/transformElement.spec.ts",
    "content": "import {\n  BindingTypes,\n  type CompilerOptions,\n  ErrorCodes,\n  type NodeTransform,\n  baseCompile,\n  baseParse as parse,\n  transform,\n  transformExpression,\n} from '../../src'\nimport {\n  BASE_TRANSITION,\n  CREATE_VNODE,\n  GUARD_REACTIVE_PROPS,\n  KEEP_ALIVE,\n  MERGE_PROPS,\n  NORMALIZE_CLASS,\n  NORMALIZE_PROPS,\n  NORMALIZE_STYLE,\n  RESOLVE_COMPONENT,\n  RESOLVE_DIRECTIVE,\n  RESOLVE_DYNAMIC_COMPONENT,\n  SUSPENSE,\n  TELEPORT,\n  TO_HANDLERS,\n  helperNameMap,\n} from '../../src/runtimeHelpers'\nimport {\n  type DirectiveNode,\n  NodeTypes,\n  type RootNode,\n  type VNodeCall,\n  createObjectProperty,\n} from '../../src/ast'\nimport { transformElement } from '../../src/transforms/transformElement'\nimport { transformStyle } from '../../../compiler-dom/src/transforms/transformStyle'\nimport { transformOn } from '../../src/transforms/vOn'\nimport { transformBind } from '../../src/transforms/vBind'\nimport { PatchFlags } from '@vue/shared'\nimport { createObjectMatcher } from '../testUtils'\nimport { transformText } from '../../src/transforms/transformText'\nimport { parseWithForTransform } from './vFor.spec'\n\nfunction parseWithElementTransform(\n  template: string,\n  options: CompilerOptions = {},\n): {\n  root: RootNode\n  node: VNodeCall\n} {\n  // wrap raw template in an extra div so that it doesn't get turned into a\n  // block as root node\n  const ast = parse(`<div>${template}</div>`, options)\n  transform(ast, {\n    nodeTransforms: [transformElement, transformText],\n    ...options,\n  })\n  const codegenNode = (ast as any).children[0].children[0]\n    .codegenNode as VNodeCall\n  expect(codegenNode.type).toBe(NodeTypes.VNODE_CALL)\n  return {\n    root: ast,\n    node: codegenNode,\n  }\n}\n\nfunction parseWithBind(template: string, options?: CompilerOptions) {\n  return parseWithElementTransform(template, {\n    ...options,\n    directiveTransforms: {\n      ...options?.directiveTransforms,\n      bind: transformBind,\n    },\n  })\n}\n\ndescribe('compiler: element transform', () => {\n  test('import + resolve component', () => {\n    const { root } = parseWithElementTransform(`<Foo/>`)\n    expect(root.helpers).toContain(RESOLVE_COMPONENT)\n    expect(root.components).toContain(`Foo`)\n  })\n\n  test('resolve implicitly self-referencing component', () => {\n    const { root } = parseWithElementTransform(`<Example/>`, {\n      filename: `/foo/bar/Example.vue?vue&type=template`,\n    })\n    expect(root.helpers).toContain(RESOLVE_COMPONENT)\n    expect(root.components).toContain(`Example__self`)\n  })\n\n  test('resolve component from setup bindings', () => {\n    const { root, node } = parseWithElementTransform(`<Example/>`, {\n      bindingMetadata: {\n        Example: BindingTypes.SETUP_MAYBE_REF,\n      },\n    })\n    expect(root.helpers).not.toContain(RESOLVE_COMPONENT)\n    expect(node.tag).toBe(`$setup[\"Example\"]`)\n  })\n\n  test('resolve component from setup bindings (inline)', () => {\n    const { root, node } = parseWithElementTransform(`<Example/>`, {\n      inline: true,\n      bindingMetadata: {\n        Example: BindingTypes.SETUP_MAYBE_REF,\n      },\n    })\n    expect(root.helpers).not.toContain(RESOLVE_COMPONENT)\n    expect(node.tag).toBe(`_unref(Example)`)\n  })\n\n  test('resolve component from setup bindings (inline const)', () => {\n    const { root, node } = parseWithElementTransform(`<Example/>`, {\n      inline: true,\n      bindingMetadata: {\n        Example: BindingTypes.SETUP_CONST,\n      },\n    })\n    expect(root.helpers).not.toContain(RESOLVE_COMPONENT)\n    expect(node.tag).toBe(`Example`)\n  })\n\n  test('resolve namespaced component from setup bindings', () => {\n    const { root, node } = parseWithElementTransform(`<Foo.Example/>`, {\n      bindingMetadata: {\n        Foo: BindingTypes.SETUP_MAYBE_REF,\n      },\n    })\n    expect(root.helpers).not.toContain(RESOLVE_COMPONENT)\n    expect(node.tag).toBe(`$setup[\"Foo\"].Example`)\n  })\n\n  test('resolve namespaced component from setup bindings (inline)', () => {\n    const { root, node } = parseWithElementTransform(`<Foo.Example/>`, {\n      inline: true,\n      bindingMetadata: {\n        Foo: BindingTypes.SETUP_MAYBE_REF,\n      },\n    })\n    expect(root.helpers).not.toContain(RESOLVE_COMPONENT)\n    expect(node.tag).toBe(`_unref(Foo).Example`)\n  })\n\n  test('resolve namespaced component from setup bindings (inline const)', () => {\n    const { root, node } = parseWithElementTransform(`<Foo.Example/>`, {\n      inline: true,\n      bindingMetadata: {\n        Foo: BindingTypes.SETUP_CONST,\n      },\n    })\n    expect(root.helpers).not.toContain(RESOLVE_COMPONENT)\n    expect(node.tag).toBe(`Foo.Example`)\n  })\n\n  test('resolve namespaced component from props bindings (inline)', () => {\n    const { root, node } = parseWithElementTransform(`<Foo.Example/>`, {\n      inline: true,\n      bindingMetadata: {\n        Foo: BindingTypes.PROPS,\n      },\n    })\n    expect(root.helpers).not.toContain(RESOLVE_COMPONENT)\n    expect(node.tag).toBe(`_unref(__props[\"Foo\"]).Example`)\n  })\n\n  test('resolve namespaced component from props bindings (non-inline)', () => {\n    const { root, node } = parseWithElementTransform(`<Foo.Example/>`, {\n      inline: false,\n      bindingMetadata: {\n        Foo: BindingTypes.PROPS,\n      },\n    })\n    expect(root.helpers).not.toContain(RESOLVE_COMPONENT)\n    expect(node.tag).toBe('_unref($props[\"Foo\"]).Example')\n  })\n\n  test('do not resolve component from non-script-setup bindings', () => {\n    const bindingMetadata = {\n      Example: BindingTypes.SETUP_MAYBE_REF,\n    }\n    Object.defineProperty(bindingMetadata, '__isScriptSetup', { value: false })\n    const { root } = parseWithElementTransform(`<Example/>`, {\n      bindingMetadata,\n    })\n    expect(root.helpers).toContain(RESOLVE_COMPONENT)\n    expect(root.components).toContain(`Example`)\n  })\n\n  test('static props', () => {\n    const { node } = parseWithElementTransform(`<div id=\"foo\" class=\"bar\" />`)\n    expect(node).toMatchObject({\n      tag: `\"div\"`,\n      props: createObjectMatcher({\n        id: 'foo',\n        class: 'bar',\n      }),\n      children: undefined,\n    })\n  })\n\n  test('props + children', () => {\n    const { node } = parseWithElementTransform(`<div id=\"foo\"><span/></div>`)\n\n    expect(node).toMatchObject({\n      tag: `\"div\"`,\n      props: createObjectMatcher({\n        id: 'foo',\n      }),\n      children: [\n        {\n          type: NodeTypes.ELEMENT,\n          tag: 'span',\n          codegenNode: {\n            type: NodeTypes.VNODE_CALL,\n            tag: `\"span\"`,\n          },\n        },\n      ],\n    })\n  })\n\n  test('0 placeholder for children with no props', () => {\n    const { node } = parseWithElementTransform(`<div><span/></div>`)\n\n    expect(node).toMatchObject({\n      tag: `\"div\"`,\n      props: undefined,\n      children: [\n        {\n          type: NodeTypes.ELEMENT,\n          tag: 'span',\n          codegenNode: {\n            type: NodeTypes.VNODE_CALL,\n            tag: `\"span\"`,\n          },\n        },\n      ],\n    })\n  })\n\n  test('v-bind=\"obj\"', () => {\n    const { root, node } = parseWithElementTransform(`<div v-bind=\"obj\" />`)\n    // single v-bind doesn't need mergeProps\n    expect(root.helpers).not.toContain(MERGE_PROPS)\n    expect(root.helpers).toContain(NORMALIZE_PROPS)\n    expect(root.helpers).toContain(GUARD_REACTIVE_PROPS)\n\n    // should directly use `obj` in props position\n    expect(node.props).toMatchObject({\n      type: NodeTypes.JS_CALL_EXPRESSION,\n      callee: NORMALIZE_PROPS,\n      arguments: [\n        {\n          type: NodeTypes.JS_CALL_EXPRESSION,\n          callee: GUARD_REACTIVE_PROPS,\n          arguments: [\n            {\n              type: NodeTypes.SIMPLE_EXPRESSION,\n              content: `obj`,\n            },\n          ],\n        },\n      ],\n    })\n  })\n\n  test('v-bind=\"obj\" after static prop', () => {\n    const { root, node } = parseWithElementTransform(\n      `<div id=\"foo\" v-bind=\"obj\" />`,\n    )\n    expect(root.helpers).toContain(MERGE_PROPS)\n\n    expect(node.props).toMatchObject({\n      type: NodeTypes.JS_CALL_EXPRESSION,\n      callee: MERGE_PROPS,\n      arguments: [\n        createObjectMatcher({\n          id: 'foo',\n        }),\n        {\n          type: NodeTypes.SIMPLE_EXPRESSION,\n          content: `obj`,\n        },\n      ],\n    })\n  })\n\n  test('v-bind=\"obj\" before static prop', () => {\n    const { root, node } = parseWithElementTransform(\n      `<div v-bind=\"obj\" id=\"foo\" />`,\n    )\n    expect(root.helpers).toContain(MERGE_PROPS)\n\n    expect(node.props).toMatchObject({\n      type: NodeTypes.JS_CALL_EXPRESSION,\n      callee: MERGE_PROPS,\n      arguments: [\n        {\n          type: NodeTypes.SIMPLE_EXPRESSION,\n          content: `obj`,\n        },\n        createObjectMatcher({\n          id: 'foo',\n        }),\n      ],\n    })\n  })\n\n  test('v-bind=\"obj\" between static props', () => {\n    const { root, node } = parseWithElementTransform(\n      `<div id=\"foo\" v-bind=\"obj\" class=\"bar\" />`,\n    )\n    expect(root.helpers).toContain(MERGE_PROPS)\n\n    expect(node.props).toMatchObject({\n      type: NodeTypes.JS_CALL_EXPRESSION,\n      callee: MERGE_PROPS,\n      arguments: [\n        createObjectMatcher({\n          id: 'foo',\n        }),\n        {\n          type: NodeTypes.SIMPLE_EXPRESSION,\n          content: `obj`,\n        },\n        createObjectMatcher({\n          class: 'bar',\n        }),\n      ],\n    })\n  })\n\n  test('v-on=\"obj\"', () => {\n    const { root, node } = parseWithElementTransform(\n      `<div id=\"foo\" v-on=\"obj\" class=\"bar\" />`,\n    )\n    expect(root.helpers).toContain(MERGE_PROPS)\n\n    expect(node.props).toMatchObject({\n      type: NodeTypes.JS_CALL_EXPRESSION,\n      callee: MERGE_PROPS,\n      arguments: [\n        createObjectMatcher({\n          id: 'foo',\n        }),\n        {\n          type: NodeTypes.JS_CALL_EXPRESSION,\n          callee: TO_HANDLERS,\n          arguments: [\n            {\n              type: NodeTypes.SIMPLE_EXPRESSION,\n              content: `obj`,\n            },\n            `true`,\n          ],\n        },\n        createObjectMatcher({\n          class: 'bar',\n        }),\n      ],\n    })\n  })\n\n  test('v-on=\"obj\" on component', () => {\n    const { root, node } = parseWithElementTransform(\n      `<Foo id=\"foo\" v-on=\"obj\" class=\"bar\" />`,\n    )\n    expect(root.helpers).toContain(MERGE_PROPS)\n\n    expect(node.props).toMatchObject({\n      type: NodeTypes.JS_CALL_EXPRESSION,\n      callee: MERGE_PROPS,\n      arguments: [\n        createObjectMatcher({\n          id: 'foo',\n        }),\n        {\n          type: NodeTypes.JS_CALL_EXPRESSION,\n          callee: TO_HANDLERS,\n          arguments: [\n            {\n              type: NodeTypes.SIMPLE_EXPRESSION,\n              content: `obj`,\n            },\n          ],\n        },\n        createObjectMatcher({\n          class: 'bar',\n        }),\n      ],\n    })\n  })\n\n  test('v-on=\"obj\" + v-bind=\"obj\"', () => {\n    const { root, node } = parseWithElementTransform(\n      `<div id=\"foo\" v-on=\"handlers\" v-bind=\"obj\" />`,\n    )\n    expect(root.helpers).toContain(MERGE_PROPS)\n\n    expect(node.props).toMatchObject({\n      type: NodeTypes.JS_CALL_EXPRESSION,\n      callee: MERGE_PROPS,\n      arguments: [\n        createObjectMatcher({\n          id: 'foo',\n        }),\n        {\n          type: NodeTypes.JS_CALL_EXPRESSION,\n          callee: TO_HANDLERS,\n          arguments: [\n            {\n              type: NodeTypes.SIMPLE_EXPRESSION,\n              content: `handlers`,\n            },\n            `true`,\n          ],\n        },\n        {\n          type: NodeTypes.SIMPLE_EXPRESSION,\n          content: `obj`,\n        },\n      ],\n    })\n  })\n\n  test('should handle plain <template> as normal element', () => {\n    const { node } = parseWithElementTransform(`<template id=\"foo\" />`)\n\n    expect(node).toMatchObject({\n      tag: `\"template\"`,\n      props: createObjectMatcher({\n        id: 'foo',\n      }),\n    })\n  })\n\n  test('should handle <Teleport> with normal children', () => {\n    function assert(tag: string) {\n      const { root, node } = parseWithElementTransform(\n        `<${tag} target=\"#foo\"><span /></${tag}>`,\n      )\n      expect(root.components.length).toBe(0)\n      expect(root.helpers).toContain(TELEPORT)\n\n      expect(node).toMatchObject({\n        tag: TELEPORT,\n        props: createObjectMatcher({\n          target: '#foo',\n        }),\n        children: [\n          {\n            type: NodeTypes.ELEMENT,\n            tag: 'span',\n            codegenNode: {\n              type: NodeTypes.VNODE_CALL,\n              tag: `\"span\"`,\n            },\n          },\n        ],\n      })\n    }\n\n    assert(`teleport`)\n    assert(`Teleport`)\n  })\n\n  test('should handle <Suspense>', () => {\n    function assert(tag: string, content: string, hasFallback?: boolean) {\n      const { root, node } = parseWithElementTransform(\n        `<${tag}>${content}</${tag}>`,\n      )\n      expect(root.components.length).toBe(0)\n      expect(root.helpers).toContain(SUSPENSE)\n\n      expect(node).toMatchObject({\n        tag: SUSPENSE,\n        props: undefined,\n        children: hasFallback\n          ? createObjectMatcher({\n              default: {\n                type: NodeTypes.JS_FUNCTION_EXPRESSION,\n              },\n              fallback: {\n                type: NodeTypes.JS_FUNCTION_EXPRESSION,\n              },\n              _: `[1 /* STABLE */]`,\n            })\n          : createObjectMatcher({\n              default: {\n                type: NodeTypes.JS_FUNCTION_EXPRESSION,\n              },\n              _: `[1 /* STABLE */]`,\n            }),\n      })\n    }\n\n    assert(`suspense`, `foo`)\n    assert(`suspense`, `<template #default>foo</template>`)\n    assert(\n      `suspense`,\n      `<template #default>foo</template><template #fallback>fallback</template>`,\n      true,\n    )\n  })\n\n  test('should handle <KeepAlive>', () => {\n    function assert(tag: string) {\n      const root = parse(`<div><${tag}><span /></${tag}></div>`)\n      transform(root, {\n        nodeTransforms: [transformElement, transformText],\n      })\n      expect(root.components.length).toBe(0)\n      expect(root.helpers).toContain(KEEP_ALIVE)\n      const node = (root.children[0] as any).children[0].codegenNode\n      expect(node).toMatchObject({\n        type: NodeTypes.VNODE_CALL,\n        tag: KEEP_ALIVE,\n        isBlock: true, // should be forced into a block\n        props: undefined,\n        // keep-alive should not compile content to slots\n        children: [{ type: NodeTypes.ELEMENT, tag: 'span' }],\n        // should get a dynamic slots flag to force updates\n        patchFlag: PatchFlags.DYNAMIC_SLOTS,\n      })\n    }\n\n    assert(`keep-alive`)\n    assert(`KeepAlive`)\n  })\n\n  test('should handle <BaseTransition>', () => {\n    function assert(tag: string) {\n      const { root, node } = parseWithElementTransform(\n        `<${tag}><span /></${tag}>`,\n      )\n      expect(root.components.length).toBe(0)\n      expect(root.helpers).toContain(BASE_TRANSITION)\n\n      expect(node).toMatchObject({\n        tag: BASE_TRANSITION,\n        props: undefined,\n        children: createObjectMatcher({\n          default: {\n            type: NodeTypes.JS_FUNCTION_EXPRESSION,\n          },\n          _: `[1 /* STABLE */]`,\n        }),\n      })\n    }\n\n    assert(`base-transition`)\n    assert(`BaseTransition`)\n  })\n\n  test('error on v-bind with no argument', () => {\n    const onError = vi.fn()\n    parseWithElementTransform(`<div v-bind/>`, { onError })\n    expect(onError.mock.calls[0]).toMatchObject([\n      {\n        code: ErrorCodes.X_V_BIND_NO_EXPRESSION,\n      },\n    ])\n  })\n\n  test('directiveTransforms', () => {\n    let _dir: DirectiveNode\n    const { node } = parseWithElementTransform(`<div v-foo:bar=\"hello\" />`, {\n      directiveTransforms: {\n        foo(dir) {\n          _dir = dir\n          return {\n            props: [createObjectProperty(dir.arg!, dir.exp!)],\n          }\n        },\n      },\n    })\n\n    expect(node.props).toMatchObject({\n      type: NodeTypes.JS_OBJECT_EXPRESSION,\n      properties: [\n        {\n          type: NodeTypes.JS_PROPERTY,\n          key: _dir!.arg,\n          value: _dir!.exp,\n        },\n      ],\n    })\n    // should factor in props returned by custom directive transforms\n    // in patchFlag analysis\n    expect(node.patchFlag).toBe(PatchFlags.PROPS)\n    expect(node.dynamicProps).toMatch(`\"bar\"`)\n  })\n\n  test('directiveTransform with needRuntime: true', () => {\n    const { root, node } = parseWithElementTransform(\n      `<div v-foo:bar=\"hello\" />`,\n      {\n        directiveTransforms: {\n          foo() {\n            return {\n              props: [],\n              needRuntime: true,\n            }\n          },\n        },\n      },\n    )\n    expect(root.helpers).toContain(RESOLVE_DIRECTIVE)\n    expect(root.directives).toContain(`foo`)\n    expect(node).toMatchObject({\n      tag: `\"div\"`,\n      props: undefined,\n      children: undefined,\n      patchFlag: PatchFlags.NEED_PATCH, // should generate appropriate flag\n      directives: {\n        type: NodeTypes.JS_ARRAY_EXPRESSION,\n        elements: [\n          {\n            type: NodeTypes.JS_ARRAY_EXPRESSION,\n            elements: [\n              `_directive_foo`,\n              // exp\n              {\n                type: NodeTypes.SIMPLE_EXPRESSION,\n                content: `hello`,\n                isStatic: false,\n              },\n              // arg\n              {\n                type: NodeTypes.SIMPLE_EXPRESSION,\n                content: `bar`,\n                isStatic: true,\n              },\n            ],\n          },\n        ],\n      },\n    })\n  })\n\n  test('directiveTransform with needRuntime: Symbol', () => {\n    const { root, node } = parseWithElementTransform(\n      `<div v-foo:bar=\"hello\" />`,\n      {\n        directiveTransforms: {\n          foo() {\n            return {\n              props: [],\n              needRuntime: CREATE_VNODE,\n            }\n          },\n        },\n      },\n    )\n\n    expect(root.helpers).toContain(CREATE_VNODE)\n    expect(root.helpers).not.toContain(RESOLVE_DIRECTIVE)\n    expect(root.directives.length).toBe(0)\n    expect(node.directives!.elements[0].elements[0]).toBe(\n      `_${helperNameMap[CREATE_VNODE]}`,\n    )\n  })\n\n  test('runtime directives', () => {\n    const { root, node } = parseWithElementTransform(\n      `<div v-foo v-bar=\"x\" v-baz:[arg].mod.mad=\"y\" />`,\n    )\n    expect(root.helpers).toContain(RESOLVE_DIRECTIVE)\n    expect(root.directives).toContain(`foo`)\n    expect(root.directives).toContain(`bar`)\n    expect(root.directives).toContain(`baz`)\n\n    expect(node).toMatchObject({\n      directives: {\n        type: NodeTypes.JS_ARRAY_EXPRESSION,\n        elements: [\n          {\n            type: NodeTypes.JS_ARRAY_EXPRESSION,\n            elements: [`_directive_foo`],\n          },\n          {\n            type: NodeTypes.JS_ARRAY_EXPRESSION,\n            elements: [\n              `_directive_bar`,\n              // exp\n              {\n                type: NodeTypes.SIMPLE_EXPRESSION,\n                content: `x`,\n              },\n            ],\n          },\n          {\n            type: NodeTypes.JS_ARRAY_EXPRESSION,\n            elements: [\n              `_directive_baz`,\n              // exp\n              {\n                type: NodeTypes.SIMPLE_EXPRESSION,\n                content: `y`,\n                isStatic: false,\n              },\n              // arg\n              {\n                type: NodeTypes.SIMPLE_EXPRESSION,\n                content: `arg`,\n                isStatic: false,\n              },\n              // modifiers\n              {\n                type: NodeTypes.JS_OBJECT_EXPRESSION,\n                properties: [\n                  {\n                    type: NodeTypes.JS_PROPERTY,\n                    key: {\n                      type: NodeTypes.SIMPLE_EXPRESSION,\n                      content: `mod`,\n                      isStatic: true,\n                    },\n                    value: {\n                      type: NodeTypes.SIMPLE_EXPRESSION,\n                      content: `true`,\n                      isStatic: false,\n                    },\n                  },\n                  {\n                    type: NodeTypes.JS_PROPERTY,\n                    key: {\n                      type: NodeTypes.SIMPLE_EXPRESSION,\n                      content: `mad`,\n                      isStatic: true,\n                    },\n                    value: {\n                      type: NodeTypes.SIMPLE_EXPRESSION,\n                      content: `true`,\n                      isStatic: false,\n                    },\n                  },\n                ],\n              },\n            ],\n          },\n        ],\n      },\n    })\n  })\n\n  test(`props merging: event handlers`, () => {\n    const { node } = parseWithElementTransform(\n      `<div @click.foo=\"a\" @click.bar=\"b\" />`,\n      {\n        directiveTransforms: {\n          on: transformOn,\n        },\n      },\n    )\n    expect(node.props).toMatchObject({\n      type: NodeTypes.JS_OBJECT_EXPRESSION,\n      properties: [\n        {\n          type: NodeTypes.JS_PROPERTY,\n          key: {\n            type: NodeTypes.SIMPLE_EXPRESSION,\n            content: `onClick`,\n            isStatic: true,\n          },\n          value: {\n            type: NodeTypes.JS_ARRAY_EXPRESSION,\n            elements: [\n              {\n                type: NodeTypes.SIMPLE_EXPRESSION,\n                content: `a`,\n                isStatic: false,\n              },\n              {\n                type: NodeTypes.SIMPLE_EXPRESSION,\n                content: `b`,\n                isStatic: false,\n              },\n            ],\n          },\n        },\n      ],\n    })\n  })\n\n  test(`props merging: style`, () => {\n    const { node, root } = parseWithElementTransform(\n      `<div style=\"color: green\" :style=\"{ color: 'red' }\" />`,\n      {\n        nodeTransforms: [transformStyle, transformElement],\n        directiveTransforms: {\n          bind: transformBind,\n        },\n      },\n    )\n    expect(root.helpers).toContain(NORMALIZE_STYLE)\n    expect(node.props).toMatchObject({\n      type: NodeTypes.JS_OBJECT_EXPRESSION,\n      properties: [\n        {\n          type: NodeTypes.JS_PROPERTY,\n          key: {\n            type: NodeTypes.SIMPLE_EXPRESSION,\n            content: `style`,\n            isStatic: true,\n          },\n          value: {\n            type: NodeTypes.JS_CALL_EXPRESSION,\n            callee: NORMALIZE_STYLE,\n            arguments: [\n              {\n                type: NodeTypes.JS_ARRAY_EXPRESSION,\n                elements: [\n                  {\n                    type: NodeTypes.SIMPLE_EXPRESSION,\n                    content: `{\"color\":\"green\"}`,\n                    isStatic: false,\n                  },\n                  {\n                    type: NodeTypes.SIMPLE_EXPRESSION,\n                    content: `{ color: 'red' }`,\n                    isStatic: false,\n                  },\n                ],\n              },\n            ],\n          },\n        },\n      ],\n    })\n  })\n\n  test(`props merging: style w/ transformExpression`, () => {\n    const { node, root } = parseWithElementTransform(\n      `<div style=\"color: green\" :style=\"{ color: 'red' }\" />`,\n      {\n        nodeTransforms: [transformExpression, transformStyle, transformElement],\n        directiveTransforms: {\n          bind: transformBind,\n        },\n        prefixIdentifiers: true,\n      },\n    )\n    expect(root.helpers).toContain(NORMALIZE_STYLE)\n    expect(node.props).toMatchObject({\n      type: NodeTypes.JS_OBJECT_EXPRESSION,\n      properties: [\n        {\n          type: NodeTypes.JS_PROPERTY,\n          key: {\n            type: NodeTypes.SIMPLE_EXPRESSION,\n            content: `style`,\n            isStatic: true,\n          },\n          value: {\n            type: NodeTypes.JS_CALL_EXPRESSION,\n            callee: NORMALIZE_STYLE,\n          },\n        },\n      ],\n    })\n  })\n\n  test(':style with array literal', () => {\n    const { node, root } = parseWithElementTransform(\n      `<div :style=\"[{ color: 'red' }]\" />`,\n      {\n        nodeTransforms: [transformExpression, transformStyle, transformElement],\n        directiveTransforms: {\n          bind: transformBind,\n        },\n        prefixIdentifiers: true,\n      },\n    )\n    expect(root.helpers).toContain(NORMALIZE_STYLE)\n    expect(node.props).toMatchObject({\n      type: NodeTypes.JS_OBJECT_EXPRESSION,\n      properties: [\n        {\n          type: NodeTypes.JS_PROPERTY,\n          key: {\n            type: NodeTypes.SIMPLE_EXPRESSION,\n            content: `style`,\n            isStatic: true,\n          },\n          value: {\n            type: NodeTypes.JS_CALL_EXPRESSION,\n            callee: NORMALIZE_STYLE,\n          },\n        },\n      ],\n    })\n  })\n\n  test(`props merging: class`, () => {\n    const { node, root } = parseWithElementTransform(\n      `<div class=\"foo\" :class=\"{ bar: isBar }\" />`,\n      {\n        directiveTransforms: {\n          bind: transformBind,\n        },\n      },\n    )\n    expect(root.helpers).toContain(NORMALIZE_CLASS)\n    expect(node.props).toMatchObject({\n      type: NodeTypes.JS_OBJECT_EXPRESSION,\n      properties: [\n        {\n          type: NodeTypes.JS_PROPERTY,\n          key: {\n            type: NodeTypes.SIMPLE_EXPRESSION,\n            content: `class`,\n            isStatic: true,\n          },\n          value: {\n            type: NodeTypes.JS_CALL_EXPRESSION,\n            callee: NORMALIZE_CLASS,\n            arguments: [\n              {\n                type: NodeTypes.JS_ARRAY_EXPRESSION,\n                elements: [\n                  {\n                    type: NodeTypes.SIMPLE_EXPRESSION,\n                    content: `foo`,\n                    isStatic: true,\n                  },\n                  {\n                    type: NodeTypes.SIMPLE_EXPRESSION,\n                    content: `{ bar: isBar }`,\n                    isStatic: false,\n                  },\n                ],\n              },\n            ],\n          },\n        },\n      ],\n    })\n  })\n\n  describe('patchFlag analysis', () => {\n    test('TEXT', () => {\n      const { node } = parseWithBind(`<div>foo</div>`)\n      expect(node.patchFlag).toBeUndefined()\n\n      const { node: node2 } = parseWithBind(`<div>{{ foo }}</div>`)\n      expect(node2.patchFlag).toBe(PatchFlags.TEXT)\n\n      // multiple nodes, merged with optimize text\n      const { node: node3 } = parseWithBind(`<div>foo {{ bar }} baz</div>`)\n      expect(node3.patchFlag).toBe(PatchFlags.TEXT)\n    })\n\n    test('CLASS', () => {\n      const { node } = parseWithBind(`<div :class=\"foo\" />`)\n      expect(node.patchFlag).toBe(PatchFlags.CLASS)\n    })\n\n    test('STYLE', () => {\n      const { node } = parseWithBind(`<div :style=\"foo\" />`)\n      expect(node.patchFlag).toBe(PatchFlags.STYLE)\n    })\n\n    test('PROPS', () => {\n      const { node } = parseWithBind(`<div id=\"foo\" :foo=\"bar\" :baz=\"qux\" />`)\n      expect(node.patchFlag).toBe(PatchFlags.PROPS)\n      expect(node.dynamicProps).toBe(`[\"foo\", \"baz\"]`)\n    })\n\n    test('CLASS + STYLE + PROPS', () => {\n      const { node } = parseWithBind(\n        `<div id=\"foo\" :class=\"cls\" :style=\"styl\" :foo=\"bar\" :baz=\"qux\"/>`,\n      )\n      expect(node.patchFlag).toBe(\n        PatchFlags.CLASS | PatchFlags.STYLE | PatchFlags.PROPS,\n      )\n      expect(node.dynamicProps).toBe(`[\"foo\", \"baz\"]`)\n    })\n\n    // should treat `class` and `style` as PROPS\n    test('PROPS on component', () => {\n      const { node } = parseWithBind(\n        `<Foo :id=\"foo\" :class=\"cls\" :style=\"styl\" />`,\n      )\n      expect(node.patchFlag).toBe(PatchFlags.PROPS)\n      expect(node.dynamicProps).toBe(`[\"id\", \"class\", \"style\"]`)\n    })\n\n    test('FULL_PROPS (v-bind)', () => {\n      const { node } = parseWithBind(`<div v-bind=\"foo\" />`)\n      expect(node.patchFlag).toBe(PatchFlags.FULL_PROPS)\n    })\n\n    test('FULL_PROPS (dynamic key)', () => {\n      const { node } = parseWithBind(`<div :[foo]=\"bar\" />`)\n      expect(node.patchFlag).toBe(PatchFlags.FULL_PROPS)\n    })\n\n    test('FULL_PROPS (w/ others)', () => {\n      const { node } = parseWithBind(\n        `<div id=\"foo\" v-bind=\"bar\" :class=\"cls\" />`,\n      )\n      expect(node.patchFlag).toBe(PatchFlags.FULL_PROPS)\n    })\n\n    test('NEED_PATCH (static ref)', () => {\n      const { node } = parseWithBind(`<div ref=\"foo\" />`)\n      expect(node.patchFlag).toBe(PatchFlags.NEED_PATCH)\n    })\n\n    test('NEED_PATCH (dynamic ref)', () => {\n      const { node } = parseWithBind(`<div :ref=\"foo\" />`)\n      expect(node.patchFlag).toBe(PatchFlags.NEED_PATCH)\n    })\n\n    test('NEED_PATCH (custom directives)', () => {\n      const { node } = parseWithBind(`<div v-foo />`)\n      expect(node.patchFlag).toBe(PatchFlags.NEED_PATCH)\n    })\n\n    test('NEED_PATCH (vnode hooks)', () => {\n      const root = baseCompile(`<div @vue:updated=\"foo\" />`, {\n        prefixIdentifiers: true,\n        cacheHandlers: true,\n      }).ast\n      const node = (root as any).children[0].codegenNode\n      expect(node.patchFlag).toBe(PatchFlags.NEED_PATCH)\n    })\n\n    test('script setup inline mode template ref (binding exists)', () => {\n      const { node } = parseWithElementTransform(`<input ref=\"input\"/>`, {\n        inline: true,\n        bindingMetadata: {\n          input: BindingTypes.SETUP_REF,\n        },\n      })\n      expect(node.props).toMatchObject({\n        type: NodeTypes.JS_OBJECT_EXPRESSION,\n        properties: [\n          {\n            type: NodeTypes.JS_PROPERTY,\n            key: {\n              content: 'ref_key',\n              isStatic: true,\n            },\n            value: {\n              content: 'input',\n              isStatic: true,\n            },\n          },\n          {\n            type: NodeTypes.JS_PROPERTY,\n            key: {\n              content: 'ref',\n              isStatic: true,\n            },\n            value: {\n              content: 'input',\n              isStatic: false,\n            },\n          },\n        ],\n      })\n    })\n\n    test('script setup inline mode template ref (binding does not exist)', () => {\n      const { node } = parseWithElementTransform(`<input ref=\"input\"/>`, {\n        inline: true,\n      })\n      expect(node.props).toMatchObject({\n        type: NodeTypes.JS_OBJECT_EXPRESSION,\n        properties: [\n          {\n            type: NodeTypes.JS_PROPERTY,\n            key: {\n              content: 'ref',\n              isStatic: true,\n            },\n            value: {\n              content: 'input',\n              isStatic: true,\n            },\n          },\n        ],\n      })\n    })\n\n    test('script setup inline mode template ref (binding does not exist but props with the same name exist)', () => {\n      const { node } = parseWithElementTransform(`<input ref=\"msg\"/>`, {\n        inline: true,\n        bindingMetadata: {\n          msg: BindingTypes.PROPS,\n          ref: BindingTypes.SETUP_CONST,\n        },\n      })\n      expect(node.props).toMatchObject({\n        type: NodeTypes.JS_OBJECT_EXPRESSION,\n        properties: [\n          {\n            type: NodeTypes.JS_PROPERTY,\n            key: {\n              content: 'ref',\n              isStatic: true,\n            },\n            value: {\n              content: 'msg',\n              isStatic: true,\n            },\n          },\n        ],\n      })\n    })\n\n    test('NEED_HYDRATION for v-on', () => {\n      // ignore click events (has dedicated fast path)\n      const { node } = parseWithElementTransform(`<div @click=\"foo\" />`, {\n        directiveTransforms: {\n          on: transformOn,\n        },\n      })\n      // should only have props flag\n      expect(node.patchFlag).toBe(PatchFlags.PROPS)\n\n      const { node: node2 } = parseWithElementTransform(\n        `<div @keyup=\"foo\" />`,\n        {\n          directiveTransforms: {\n            on: transformOn,\n          },\n        },\n      )\n      expect(node2.patchFlag).toBe(PatchFlags.PROPS | PatchFlags.NEED_HYDRATION)\n    })\n\n    test('NEED_HYDRATION for v-bind.prop', () => {\n      const { node } = parseWithBind(`<div v-bind:id.prop=\"id\" />`)\n      expect(node.patchFlag).toBe(PatchFlags.PROPS | PatchFlags.NEED_HYDRATION)\n\n      const { node: node2 } = parseWithBind(`<div .id=\"id\" />`)\n      expect(node2.patchFlag).toBe(PatchFlags.PROPS | PatchFlags.NEED_HYDRATION)\n    })\n\n    // #5870\n    test('NEED_HYDRATION on dynamic component', () => {\n      const { node } = parseWithElementTransform(\n        `<component :is=\"foo\" @input=\"foo\" />`,\n        {\n          directiveTransforms: {\n            on: transformOn,\n          },\n        },\n      )\n      expect(node.patchFlag).toBe(PatchFlags.PROPS | PatchFlags.NEED_HYDRATION)\n    })\n\n    test('should not have PROPS patchflag for constant v-on handlers', () => {\n      const { node } = parseWithElementTransform(`<div @keydown=\"foo\" />`, {\n        prefixIdentifiers: true,\n        bindingMetadata: {\n          foo: BindingTypes.SETUP_CONST,\n        },\n        directiveTransforms: {\n          on: transformOn,\n        },\n      })\n      // should only have hydration flag\n      expect(node.patchFlag).toBe(PatchFlags.NEED_HYDRATION)\n    })\n  })\n\n  describe('dynamic component', () => {\n    test('static binding', () => {\n      const { node, root } = parseWithBind(`<component is=\"foo\" />`)\n      expect(root.helpers).toContain(RESOLVE_DYNAMIC_COMPONENT)\n      expect(node).toMatchObject({\n        isBlock: true,\n        tag: {\n          callee: RESOLVE_DYNAMIC_COMPONENT,\n          arguments: [\n            {\n              type: NodeTypes.SIMPLE_EXPRESSION,\n              content: 'foo',\n              isStatic: true,\n            },\n          ],\n        },\n      })\n    })\n\n    test('capitalized version w/ static binding', () => {\n      const { node, root } = parseWithBind(`<Component is=\"foo\" />`)\n      expect(root.helpers).toContain(RESOLVE_DYNAMIC_COMPONENT)\n      expect(node).toMatchObject({\n        isBlock: true,\n        tag: {\n          callee: RESOLVE_DYNAMIC_COMPONENT,\n          arguments: [\n            {\n              type: NodeTypes.SIMPLE_EXPRESSION,\n              content: 'foo',\n              isStatic: true,\n            },\n          ],\n        },\n      })\n    })\n\n    test('dynamic binding', () => {\n      const { node, root } = parseWithBind(`<component :is=\"foo\" />`)\n      expect(root.helpers).toContain(RESOLVE_DYNAMIC_COMPONENT)\n      expect(node).toMatchObject({\n        isBlock: true,\n        tag: {\n          callee: RESOLVE_DYNAMIC_COMPONENT,\n          arguments: [\n            {\n              type: NodeTypes.SIMPLE_EXPRESSION,\n              content: 'foo',\n              isStatic: false,\n            },\n          ],\n        },\n      })\n    })\n\n    test('dynamic binding shorthand', () => {\n      const { node, root } = parseWithBind(`<component :is />`)\n      expect(root.helpers).toContain(RESOLVE_DYNAMIC_COMPONENT)\n      expect(node).toMatchObject({\n        isBlock: true,\n        tag: {\n          callee: RESOLVE_DYNAMIC_COMPONENT,\n          arguments: [\n            {\n              type: NodeTypes.SIMPLE_EXPRESSION,\n              content: 'is',\n              isStatic: false,\n            },\n          ],\n        },\n      })\n    })\n\n    test('is casting', () => {\n      const { node, root } = parseWithBind(`<div is=\"vue:foo\" />`)\n      expect(root.helpers).toContain(RESOLVE_COMPONENT)\n      expect(node).toMatchObject({\n        type: NodeTypes.VNODE_CALL,\n        tag: '_component_foo',\n      })\n    })\n\n    // #3934\n    test('normal component with is prop', () => {\n      const { node, root } = parseWithBind(`<custom-input is=\"foo\" />`, {\n        isNativeTag: () => false,\n      })\n      expect(root.helpers).toContain(RESOLVE_COMPONENT)\n      expect(root.helpers).not.toContain(RESOLVE_DYNAMIC_COMPONENT)\n      expect(node).toMatchObject({\n        tag: '_component_custom_input',\n      })\n    })\n  })\n\n  test('<svg> should be forced into blocks', () => {\n    const ast = parse(`<div><svg/></div>`)\n    transform(ast, {\n      nodeTransforms: [transformElement],\n    })\n    expect((ast as any).children[0].children[0].codegenNode).toMatchObject({\n      type: NodeTypes.VNODE_CALL,\n      tag: `\"svg\"`,\n      isBlock: true,\n    })\n  })\n\n  test('<math> should be forced into blocks', () => {\n    const ast = parse(`<div><math/></div>`)\n    transform(ast, {\n      nodeTransforms: [transformElement],\n    })\n    expect((ast as any).children[0].children[0].codegenNode).toMatchObject({\n      type: NodeTypes.VNODE_CALL,\n      tag: `\"math\"`,\n      isBlock: true,\n    })\n  })\n\n  test('force block for runtime custom directive w/ children', () => {\n    const { node } = parseWithElementTransform(`<div v-foo>hello</div>`)\n    expect(node.isBlock).toBe(true)\n  })\n\n  test('force block for inline before-update handlers w/ children', () => {\n    expect(\n      parseWithElementTransform(`<div @vue:before-update>hello</div>`).node\n        .isBlock,\n    ).toBe(true)\n  })\n\n  // #938\n  test('element with dynamic keys should be forced into blocks', () => {\n    const ast = parse(`<div><div :key=\"foo\" /></div>`)\n    transform(ast, {\n      nodeTransforms: [transformElement],\n    })\n    expect((ast as any).children[0].children[0].codegenNode).toMatchObject({\n      type: NodeTypes.VNODE_CALL,\n      tag: `\"div\"`,\n      isBlock: true,\n    })\n  })\n\n  test('should process node when node has been replaced', () => {\n    // a NodeTransform that swaps out <div id=\"foo\" /> with <span id=\"foo\" />\n    const customNodeTransform: NodeTransform = (node, context) => {\n      if (\n        node.type === NodeTypes.ELEMENT &&\n        node.tag === 'div' &&\n        node.props.some(\n          prop =>\n            prop.type === NodeTypes.ATTRIBUTE &&\n            prop.name === 'id' &&\n            prop.value &&\n            prop.value.content === 'foo',\n        )\n      ) {\n        context.replaceNode({\n          ...node,\n          tag: 'span',\n        })\n      }\n    }\n    const ast = parse(`<div><div id=\"foo\" /></div>`)\n    transform(ast, {\n      nodeTransforms: [transformElement, transformText, customNodeTransform],\n    })\n    expect((ast as any).children[0].children[0].codegenNode).toMatchObject({\n      type: NodeTypes.VNODE_CALL,\n      tag: '\"span\"',\n      isBlock: false,\n    })\n  })\n\n  test('ref_for marker on static ref', () => {\n    const { node } = parseWithForTransform(`<div v-for=\"i in l\" ref=\"x\"/>`)\n    expect((node.children[0] as any).codegenNode.props).toMatchObject(\n      createObjectMatcher({\n        ref_for: `[true]`,\n        ref: 'x',\n      }),\n    )\n  })\n\n  test('ref_for marker on dynamic ref', () => {\n    const { node } = parseWithForTransform(`<div v-for=\"i in l\" :ref=\"x\"/>`)\n    expect((node.children[0] as any).codegenNode.props).toMatchObject(\n      createObjectMatcher({\n        ref_for: `[true]`,\n        ref: '[x]',\n      }),\n    )\n  })\n\n  test('ref_for marker on v-bind', () => {\n    const { node } = parseWithForTransform(`<div v-for=\"i in l\" v-bind=\"x\" />`)\n    expect((node.children[0] as any).codegenNode.props).toMatchObject({\n      type: NodeTypes.JS_CALL_EXPRESSION,\n      callee: MERGE_PROPS,\n      arguments: [\n        createObjectMatcher({\n          ref_for: `[true]`,\n        }),\n        {\n          type: NodeTypes.SIMPLE_EXPRESSION,\n          content: 'x',\n          isStatic: false,\n        },\n      ],\n    })\n  })\n})\n"
  },
  {
    "path": "packages/compiler-core/__tests__/transforms/transformExpressions.spec.ts",
    "content": "import {\n  BindingTypes,\n  type CompilerOptions,\n  ConstantTypes,\n  type DirectiveNode,\n  type ElementNode,\n  type InterpolationNode,\n  NodeTypes,\n  baseCompile,\n  baseParse as parse,\n  transform,\n} from '../../src'\nimport { transformIf } from '../../src/transforms/vIf'\nimport { transformExpression } from '../../src/transforms/transformExpression'\nimport { PatchFlagNames, PatchFlags } from '../../../shared/src'\n\nfunction parseWithExpressionTransform(\n  template: string,\n  options: CompilerOptions = {},\n) {\n  const ast = parse(template, options)\n  transform(ast, {\n    prefixIdentifiers: true,\n    nodeTransforms: [transformIf, transformExpression],\n    ...options,\n  })\n  return ast.children[0]\n}\n\nfunction compile(template: string) {\n  return baseCompile(template, { prefixIdentifiers: true })\n}\n\ndescribe('compiler: expression transform', () => {\n  test('interpolation (root)', () => {\n    const node = parseWithExpressionTransform(`{{ foo }}`) as InterpolationNode\n    expect(node.content).toMatchObject({\n      type: NodeTypes.SIMPLE_EXPRESSION,\n      content: `_ctx.foo`,\n    })\n  })\n\n  test('empty interpolation', () => {\n    const node = parseWithExpressionTransform(`{{}}`) as InterpolationNode\n    const node2 = parseWithExpressionTransform(`{{ }}`) as InterpolationNode\n    const node3 = parseWithExpressionTransform(\n      `<div>{{ }}</div>`,\n    ) as ElementNode\n\n    const objectToBeMatched = {\n      type: NodeTypes.SIMPLE_EXPRESSION,\n      content: ``,\n    }\n    expect(node.content).toMatchObject(objectToBeMatched)\n    expect(node2.content).toMatchObject(objectToBeMatched)\n    expect((node3.children[0] as InterpolationNode).content).toMatchObject(\n      objectToBeMatched,\n    )\n  })\n\n  test('interpolation (children)', () => {\n    const el = parseWithExpressionTransform(\n      `<div>{{ foo }}</div>`,\n    ) as ElementNode\n    const node = el.children[0] as InterpolationNode\n    expect(node.content).toMatchObject({\n      type: NodeTypes.SIMPLE_EXPRESSION,\n      content: `_ctx.foo`,\n    })\n  })\n\n  test('interpolation (complex)', () => {\n    const el = parseWithExpressionTransform(\n      `<div>{{ foo + bar(baz.qux) }}</div>`,\n    ) as ElementNode\n    const node = el.children[0] as InterpolationNode\n    expect(node.content).toMatchObject({\n      type: NodeTypes.COMPOUND_EXPRESSION,\n      children: [\n        { content: `_ctx.foo` },\n        ` + `,\n        { content: `_ctx.bar` },\n        `(`,\n        { content: `_ctx.baz` },\n        `.`,\n        { content: `qux` },\n        `)`,\n      ],\n    })\n  })\n\n  test('directive value', () => {\n    const node = parseWithExpressionTransform(\n      `<div v-foo:arg=\"baz\"/>`,\n    ) as ElementNode\n    const arg = (node.props[0] as DirectiveNode).arg!\n    expect(arg).toMatchObject({\n      type: NodeTypes.SIMPLE_EXPRESSION,\n      content: `arg`,\n    })\n    const exp = (node.props[0] as DirectiveNode).exp!\n    expect(exp).toMatchObject({\n      type: NodeTypes.SIMPLE_EXPRESSION,\n      content: `_ctx.baz`,\n    })\n  })\n\n  test('dynamic directive arg', () => {\n    const node = parseWithExpressionTransform(\n      `<div v-foo:[arg]=\"baz\"/>`,\n    ) as ElementNode\n    const arg = (node.props[0] as DirectiveNode).arg!\n    expect(arg).toMatchObject({\n      type: NodeTypes.SIMPLE_EXPRESSION,\n      content: `_ctx.arg`,\n    })\n    const exp = (node.props[0] as DirectiveNode).exp!\n    expect(exp).toMatchObject({\n      type: NodeTypes.SIMPLE_EXPRESSION,\n      content: `_ctx.baz`,\n    })\n  })\n\n  test('should prefix complex expressions', () => {\n    const node = parseWithExpressionTransform(\n      `{{ foo(baz + 1, { key: kuz }) }}`,\n    ) as InterpolationNode\n    // should parse into compound expression\n    expect(node.content).toMatchObject({\n      type: NodeTypes.COMPOUND_EXPRESSION,\n      children: [\n        {\n          content: `_ctx.foo`,\n          loc: {\n            start: { offset: 3, line: 1, column: 4 },\n            end: { offset: 6, line: 1, column: 7 },\n          },\n        },\n        `(`,\n        {\n          content: `_ctx.baz`,\n          loc: {\n            start: { offset: 7, line: 1, column: 8 },\n            end: { offset: 10, line: 1, column: 11 },\n          },\n        },\n        ` + 1, { key: `,\n        {\n          content: `_ctx.kuz`,\n          loc: {\n            start: { offset: 23, line: 1, column: 24 },\n            end: { offset: 26, line: 1, column: 27 },\n          },\n        },\n        ` })`,\n      ],\n    })\n  })\n\n  test('should not prefix whitelisted globals', () => {\n    const node = parseWithExpressionTransform(\n      `{{ Math.max(1, 2) }}`,\n    ) as InterpolationNode\n    expect(node.content).toMatchObject({\n      type: NodeTypes.COMPOUND_EXPRESSION,\n      children: [{ content: `Math` }, `.`, { content: `max` }, `(1, 2)`],\n    })\n\n    expect(\n      (parseWithExpressionTransform(`{{ new Error() }}`) as InterpolationNode)\n        .content,\n    ).toMatchObject({\n      type: NodeTypes.COMPOUND_EXPRESSION,\n      children: ['new ', { content: 'Error' }, '()'],\n    })\n  })\n\n  test('should not prefix reserved literals', () => {\n    function assert(exp: string) {\n      const node = parseWithExpressionTransform(\n        `{{ ${exp} }}`,\n      ) as InterpolationNode\n      expect(node.content).toMatchObject({\n        type: NodeTypes.SIMPLE_EXPRESSION,\n        content: exp,\n      })\n    }\n    assert(`true`)\n    assert(`false`)\n    assert(`null`)\n    assert(`this`)\n  })\n\n  test('should not prefix id of a function declaration', () => {\n    const node = parseWithExpressionTransform(\n      `{{ function foo() { return bar } }}`,\n    ) as InterpolationNode\n    expect(node.content).toMatchObject({\n      type: NodeTypes.COMPOUND_EXPRESSION,\n      children: [\n        `function `,\n        { content: `foo` },\n        `() { return `,\n        { content: `_ctx.bar` },\n        ` }`,\n      ],\n    })\n  })\n\n  test('should not prefix params of a function expression', () => {\n    const node = parseWithExpressionTransform(\n      `{{ foo => foo + bar }}`,\n    ) as InterpolationNode\n    expect(node.content).toMatchObject({\n      type: NodeTypes.COMPOUND_EXPRESSION,\n      children: [\n        { content: `foo` },\n        ` => `,\n        { content: `foo` },\n        ` + `,\n        { content: `_ctx.bar` },\n      ],\n    })\n  })\n\n  test('should prefix default value of a function expression param', () => {\n    const node = parseWithExpressionTransform(\n      `{{ (foo = baz) => foo + bar }}`,\n    ) as InterpolationNode\n    expect(node.content).toMatchObject({\n      type: NodeTypes.COMPOUND_EXPRESSION,\n      children: [\n        `(`,\n        { content: `foo` },\n        ` = `,\n        { content: `_ctx.baz` },\n        `) => `,\n        { content: `foo` },\n        ` + `,\n        { content: `_ctx.bar` },\n      ],\n    })\n  })\n\n  test('should not prefix function param destructuring', () => {\n    const node = parseWithExpressionTransform(\n      `{{ ({ foo }) => foo + bar }}`,\n    ) as InterpolationNode\n    expect(node.content).toMatchObject({\n      type: NodeTypes.COMPOUND_EXPRESSION,\n      children: [\n        `({ `,\n        { content: `foo` },\n        ` }) => `,\n        { content: `foo` },\n        ` + `,\n        { content: `_ctx.bar` },\n      ],\n    })\n  })\n\n  test('function params should not affect out of scope identifiers', () => {\n    const node = parseWithExpressionTransform(\n      `{{ { a: foo => foo, b: foo } }}`,\n    ) as InterpolationNode\n    expect(node.content).toMatchObject({\n      type: NodeTypes.COMPOUND_EXPRESSION,\n      children: [\n        `{ a: `,\n        { content: `foo` },\n        ` => `,\n        { content: `foo` },\n        `, b: `,\n        { content: `_ctx.foo` },\n        ` }`,\n      ],\n    })\n  })\n\n  test('should prefix default value of function param destructuring', () => {\n    const node = parseWithExpressionTransform(\n      `{{ ({ foo = bar }) => foo + bar }}`,\n    ) as InterpolationNode\n    expect(node.content).toMatchObject({\n      type: NodeTypes.COMPOUND_EXPRESSION,\n      children: [\n        `({ `,\n        { content: `foo` },\n        ` = `,\n        { content: `_ctx.bar` },\n        ` }) => `,\n        { content: `foo` },\n        ` + `,\n        { content: `_ctx.bar` },\n      ],\n    })\n  })\n\n  test('should not prefix an object property key', () => {\n    const node = parseWithExpressionTransform(\n      `{{ { foo() { baz() }, value: bar } }}`,\n    ) as InterpolationNode\n    expect(node.content).toMatchObject({\n      type: NodeTypes.COMPOUND_EXPRESSION,\n      children: [\n        `{ foo() { `,\n        { content: `_ctx.baz` },\n        `() }, value: `,\n        { content: `_ctx.bar` },\n        ` }`,\n      ],\n    })\n  })\n\n  test('should not duplicate object key with same name as value', () => {\n    const node = parseWithExpressionTransform(\n      `{{ { foo: foo } }}`,\n    ) as InterpolationNode\n    expect(node.content).toMatchObject({\n      type: NodeTypes.COMPOUND_EXPRESSION,\n      children: [`{ foo: `, { content: `_ctx.foo` }, ` }`],\n    })\n  })\n\n  test('should prefix a computed object property key', () => {\n    const node = parseWithExpressionTransform(\n      `{{ { [foo]: bar } }}`,\n    ) as InterpolationNode\n    expect(node.content).toMatchObject({\n      type: NodeTypes.COMPOUND_EXPRESSION,\n      children: [\n        `{ [`,\n        { content: `_ctx.foo` },\n        `]: `,\n        { content: `_ctx.bar` },\n        ` }`,\n      ],\n    })\n  })\n\n  test('should prefix object property shorthand value', () => {\n    const node = parseWithExpressionTransform(\n      `{{ { foo } }}`,\n    ) as InterpolationNode\n    expect(node.content).toMatchObject({\n      type: NodeTypes.COMPOUND_EXPRESSION,\n      children: [`{ foo: `, { content: `_ctx.foo` }, ` }`],\n    })\n  })\n\n  test('should not prefix id in a member expression', () => {\n    const node = parseWithExpressionTransform(\n      `{{ foo.bar.baz }}`,\n    ) as InterpolationNode\n    expect(node.content).toMatchObject({\n      type: NodeTypes.COMPOUND_EXPRESSION,\n      children: [\n        { content: `_ctx.foo` },\n        `.`,\n        { content: `bar` },\n        `.`,\n        { content: `baz` },\n      ],\n    })\n  })\n\n  test('should prefix computed id in a member expression', () => {\n    const node = parseWithExpressionTransform(\n      `{{ foo[bar][baz] }}`,\n    ) as InterpolationNode\n    expect(node.content).toMatchObject({\n      type: NodeTypes.COMPOUND_EXPRESSION,\n      children: [\n        { content: `_ctx.foo` },\n        `[`,\n        { content: `_ctx.bar` },\n        `][`,\n        { content: '_ctx.baz' },\n        `]`,\n      ],\n    })\n  })\n\n  test('should handle parse error', () => {\n    const onError = vi.fn()\n    parseWithExpressionTransform(`{{ a( }}`, { onError })\n    expect(onError.mock.calls[0][0].message).toMatch(\n      `Error parsing JavaScript expression: Unexpected token`,\n    )\n  })\n\n  test('should not error', () => {\n    const onError = vi.fn()\n    parseWithExpressionTransform(\n      `<p :id=\"undefined /* force override the id */\"/>`,\n      {\n        onError,\n      },\n    )\n    expect(onError).not.toHaveBeenCalled()\n  })\n\n  test('should prefix in assignment', () => {\n    const node = parseWithExpressionTransform(\n      `{{ x = 1 }}`,\n    ) as InterpolationNode\n    expect(node.content).toMatchObject({\n      type: NodeTypes.COMPOUND_EXPRESSION,\n      children: [{ content: `_ctx.x` }, ` = 1`],\n    })\n  })\n\n  test('should prefix in assignment pattern', () => {\n    const node = parseWithExpressionTransform(\n      `{{ { x, y: [z] } = obj }}`,\n    ) as InterpolationNode\n    expect(node.content).toMatchObject({\n      type: NodeTypes.COMPOUND_EXPRESSION,\n      children: [\n        `{ x: `,\n        { content: `_ctx.x` },\n        `, y: [`,\n        { content: `_ctx.z` },\n        `] } = `,\n        { content: `_ctx.obj` },\n      ],\n    })\n  })\n\n  // #8295\n  test('should treat floating point number literals as constant', () => {\n    const node = parseWithExpressionTransform(\n      `{{ [1, 2.1] }}`,\n    ) as InterpolationNode\n    expect(node.content).toMatchObject({\n      constType: ConstantTypes.CAN_STRINGIFY,\n    })\n  })\n\n  // #10807\n  test('should not bail constant on strings w/ ()', () => {\n    const node = parseWithExpressionTransform(\n      `{{ { foo: 'ok()' } }}`,\n    ) as InterpolationNode\n    expect(node.content).toMatchObject({\n      constType: ConstantTypes.CAN_STRINGIFY,\n    })\n  })\n\n  test('should bail constant for global identifiers w/ new or call expressions', () => {\n    const node = parseWithExpressionTransform(\n      `{{ new Date().getFullYear() }}`,\n    ) as InterpolationNode\n    expect(node.content).toMatchObject({\n      children: [\n        'new ',\n        { constType: ConstantTypes.NOT_CONSTANT },\n        '().',\n        { constType: ConstantTypes.NOT_CONSTANT },\n        '()',\n      ],\n    })\n  })\n\n  test('should not prefix temp variable of for...in', () => {\n    const { code } = compile(\n      `<div @click=\"() => {\n        for (const x in list) {\n          log(x)\n        }\n        error(x)\n      }\"/>`,\n    )\n    expect(code).not.toMatch(`log(_ctx.x)`)\n    expect(code).toMatch(`error(_ctx.x)`)\n    expect(code).toMatchSnapshot()\n  })\n\n  test('should not prefix temp variable of for...of', () => {\n    const { code } = compile(\n      `<div @click=\"() => {\n        for (const x of list) {\n          log(x)\n        }\n        error(x)\n      }\"/>`,\n    )\n    expect(code).not.toMatch(`log(_ctx.x)`)\n    expect(code).toMatch(`error(_ctx.x)`)\n    expect(code).toMatchSnapshot()\n  })\n\n  test('should not prefix temp variable of for loop', () => {\n    const { code } = compile(\n      `<div @click=\"() => {\n        for (let i = 0; i < list.length; i++) {\n          log(i)\n        }\n        error(i)\n      }\"/>`,\n    )\n    expect(code).not.toMatch(`log(_ctx.i)`)\n    expect(code).toMatch(`error(_ctx.i)`)\n    expect(code).toMatchSnapshot()\n  })\n\n  test('should allow leak of var declarations in for loop', () => {\n    const { code } = compile(\n      `<div @click=\"() => {\n        for (var i = 0; i < list.length; i++) {\n          log(i)\n        }\n        error(i)\n      }\"/>`,\n    )\n    expect(code).not.toMatch(`log(_ctx.i)`)\n    expect(code).not.toMatch(`error(_ctx.i)`)\n    expect(code).toMatchSnapshot()\n  })\n\n  test('should not prefix catch block param', () => {\n    const { code } = compile(\n      `<div @click=\"() => {\n         try {} catch (err) { console.error(err) }\n        console.log(err)\n      }\"/>`,\n    )\n    expect(code).not.toMatch(`console.error(_ctx.err)`)\n    expect(code).toMatch(`console.log(_ctx.err)`)\n    expect(code).toMatchSnapshot()\n  })\n\n  test('should not prefix destructured catch block param', () => {\n    const { code } = compile(\n      `<div @click=\"() => {\n        try {\n          throw new Error('sup?')\n        } catch ({ message: { length } }) {\n          console.error(length)\n        }\n        console.log(length)\n      }\"/>`,\n    )\n    expect(code).not.toMatch(`console.error(_ctx.length)`)\n    expect(code).toMatch(`console.log(_ctx.length)`)\n    expect(code).toMatchSnapshot()\n  })\n\n  describe('ES Proposals support', () => {\n    test('bigInt', () => {\n      const node = parseWithExpressionTransform(\n        `{{ 13000n }}`,\n      ) as InterpolationNode\n      expect(node.content).toMatchObject({\n        type: NodeTypes.SIMPLE_EXPRESSION,\n        content: `13000n`,\n        isStatic: false,\n        constType: ConstantTypes.CAN_STRINGIFY,\n      })\n    })\n\n    test('nullish coalescing', () => {\n      const node = parseWithExpressionTransform(\n        `{{ a ?? b }}`,\n      ) as InterpolationNode\n      expect(node.content).toMatchObject({\n        type: NodeTypes.COMPOUND_EXPRESSION,\n        children: [{ content: `_ctx.a` }, ` ?? `, { content: `_ctx.b` }],\n      })\n    })\n\n    test('optional chaining', () => {\n      const node = parseWithExpressionTransform(\n        `{{ a?.b?.c }}`,\n      ) as InterpolationNode\n      expect(node.content).toMatchObject({\n        type: NodeTypes.COMPOUND_EXPRESSION,\n        children: [\n          { content: `_ctx.a` },\n          `?.`,\n          { content: `b` },\n          `?.`,\n          { content: `c` },\n        ],\n      })\n    })\n\n    test('Enabling additional plugins', () => {\n      // enabling pipeline operator to replace filters:\n      const node = parseWithExpressionTransform(`{{ a |> uppercase }}`, {\n        expressionPlugins: [\n          [\n            'pipelineOperator',\n            {\n              proposal: 'minimal',\n            },\n          ],\n        ],\n      }) as InterpolationNode\n      expect(node.content).toMatchObject({\n        type: NodeTypes.COMPOUND_EXPRESSION,\n        children: [\n          { content: `_ctx.a` },\n          ` |> `,\n          { content: `_ctx.uppercase` },\n        ],\n      })\n    })\n  })\n\n  describe('bindingMetadata', () => {\n    const bindingMetadata = {\n      props: BindingTypes.PROPS,\n      setup: BindingTypes.SETUP_MAYBE_REF,\n      setupConst: BindingTypes.SETUP_CONST,\n      data: BindingTypes.DATA,\n      options: BindingTypes.OPTIONS,\n      reactive: BindingTypes.SETUP_REACTIVE_CONST,\n      literal: BindingTypes.LITERAL_CONST,\n      isNaN: BindingTypes.SETUP_REF,\n    }\n\n    function compileWithBindingMetadata(\n      template: string,\n      options?: CompilerOptions,\n    ) {\n      return baseCompile(template, {\n        prefixIdentifiers: true,\n        bindingMetadata,\n        ...options,\n      })\n    }\n\n    test('non-inline mode', () => {\n      const { code } = compileWithBindingMetadata(\n        `<div>{{ props }} {{ setup }} {{ data }} {{ options }} {{ isNaN }}</div>`,\n      )\n      expect(code).toMatch(`$props.props`)\n      expect(code).toMatch(`$setup.setup`)\n      expect(code).toMatch(`$setup.isNaN`)\n      expect(code).toMatch(`$data.data`)\n      expect(code).toMatch(`$options.options`)\n      expect(code).toMatch(`_ctx, _cache, $props, $setup, $data, $options`)\n      expect(code).toMatchSnapshot()\n    })\n\n    test('inline mode', () => {\n      const { code } = compileWithBindingMetadata(\n        `<div>{{ props }} {{ setup }} {{ setupConst }} {{ data }} {{ options }} {{ isNaN }}</div>`,\n        { inline: true },\n      )\n      expect(code).toMatch(`__props.props`)\n      expect(code).toMatch(`_unref(setup)`)\n      expect(code).toMatch(`_toDisplayString(setupConst)`)\n      expect(code).toMatch(`_ctx.data`)\n      expect(code).toMatch(`_ctx.options`)\n      expect(code).toMatch(`isNaN.value`)\n      expect(code).toMatchSnapshot()\n    })\n\n    test('literal const handling', () => {\n      const { code } = compileWithBindingMetadata(`<div>{{ literal }}</div>`, {\n        inline: true,\n      })\n      expect(code).toMatch(`toDisplayString(literal)`)\n      // #7973 should skip patch for literal const\n      expect(code).not.toMatch(\n        `${PatchFlags.TEXT} /* ${PatchFlagNames[PatchFlags.TEXT]} */`,\n      )\n    })\n\n    test('literal const handling， non-inline mode', () => {\n      const { code } = compileWithBindingMetadata(`<div>{{ literal }}</div>`)\n      expect(code).toMatch(`toDisplayString($setup.literal)`)\n      // #7973 should skip patch for literal const\n      expect(code).not.toMatch(\n        `${PatchFlags.TEXT} /* ${PatchFlagNames[PatchFlags.TEXT]} */`,\n      )\n    })\n\n    test('reactive const handling', () => {\n      const { code } = compileWithBindingMetadata(`<div>{{ reactive }}</div>`, {\n        inline: true,\n      })\n      // #7973 should not skip patch for reactive const\n      expect(code).toMatch(\n        `${PatchFlags.TEXT} /* ${PatchFlagNames[PatchFlags.TEXT]} */`,\n      )\n    })\n\n    // #10754\n    test('await expression in right hand of assignment, inline mode', () => {\n      const node = parseWithExpressionTransform(\n        `{{ (async () => { x = await bar })() }}`,\n        {\n          inline: true,\n          bindingMetadata: {\n            x: BindingTypes.SETUP_LET,\n            bar: BindingTypes.SETUP_CONST,\n          },\n        },\n      ) as InterpolationNode\n      expect(node.content).toMatchObject({\n        type: NodeTypes.COMPOUND_EXPRESSION,\n        children: [\n          `(async () => { `,\n          {\n            content: `_isRef(x) ? x.value = await bar : x`,\n          },\n          ` = await `,\n          {\n            content: `bar`,\n          },\n          ` })()`,\n        ],\n      })\n    })\n  })\n\n  describe('switch case variable declarations', () => {\n    test('should handle const declarations in switch case without braces', () => {\n      const { code } = compile(\n        `{{ (() => { switch (1) { case 1: const foo = \"bar\"; return \\`\\${foo}\\`; } })() }}`,\n      )\n\n      expect(code).toMatch(`const foo = \"bar\";`)\n      expect(code).toMatch(`return \\`\\${foo}\\`;`)\n      expect(code).not.toMatch(`_ctx.foo`)\n    })\n\n    test('should handle const declarations in switch case with braces (existing behavior)', () => {\n      const { code } = compile(\n        `{{ (() => {\n          switch (true) {\n            case true: {\n              const foo = \"bar\";\n              return \\`\\${foo}\\`;\n            }\n          }\n        })() }}`,\n      )\n\n      expect(code).toMatch(`const foo = \"bar\";`)\n      expect(code).toMatch(`return \\`\\${foo}\\`;`)\n      expect(code).not.toMatch(`_ctx.foo`)\n    })\n\n    test('should parse switch case test as local scoped variables', () => {\n      const { code } = compile(\n        `{{ (() => { switch (foo) { case bar: return \\`\\${bar}\\`; } })() }}`,\n      )\n\n      expect(code).toMatch('_ctx.foo')\n      expect(code).toMatch(`_ctx.bar`)\n    })\n  })\n})\n"
  },
  {
    "path": "packages/compiler-core/__tests__/transforms/transformSlotOutlet.spec.ts",
    "content": "import {\n  type CompilerOptions,\n  type ElementNode,\n  ErrorCodes,\n  NodeTypes,\n  baseParse as parse,\n  transform,\n} from '../../src'\nimport { transformElement } from '../../src/transforms/transformElement'\nimport { transformOn } from '../../src/transforms/vOn'\nimport { transformBind } from '../../src/transforms/vBind'\nimport { transformExpression } from '../../src/transforms/transformExpression'\nimport { RENDER_SLOT } from '../../src/runtimeHelpers'\nimport { transformSlotOutlet } from '../../src/transforms/transformSlotOutlet'\n\nfunction parseWithSlots(template: string, options: CompilerOptions = {}) {\n  const ast = parse(template)\n  transform(ast, {\n    nodeTransforms: [\n      ...(options.prefixIdentifiers ? [transformExpression] : []),\n      transformSlotOutlet,\n      transformElement,\n    ],\n    directiveTransforms: {\n      on: transformOn,\n      bind: transformBind,\n    },\n    ...options,\n  })\n  return ast\n}\n\ndescribe('compiler: transform <slot> outlets', () => {\n  test('default slot outlet', () => {\n    const ast = parseWithSlots(`<slot/>`)\n    expect((ast.children[0] as ElementNode).codegenNode).toMatchObject({\n      type: NodeTypes.JS_CALL_EXPRESSION,\n      callee: RENDER_SLOT,\n      arguments: [`$slots`, `\"default\"`],\n    })\n  })\n\n  test('statically named slot outlet', () => {\n    const ast = parseWithSlots(`<slot name=\"foo\" />`)\n    expect((ast.children[0] as ElementNode).codegenNode).toMatchObject({\n      type: NodeTypes.JS_CALL_EXPRESSION,\n      callee: RENDER_SLOT,\n      arguments: [`$slots`, `\"foo\"`],\n    })\n  })\n\n  test('dynamically named slot outlet', () => {\n    const ast = parseWithSlots(`<slot :name=\"foo\" />`)\n    expect((ast.children[0] as ElementNode).codegenNode).toMatchObject({\n      type: NodeTypes.JS_CALL_EXPRESSION,\n      callee: RENDER_SLOT,\n      arguments: [\n        `$slots`,\n        {\n          type: NodeTypes.SIMPLE_EXPRESSION,\n          content: `foo`,\n          isStatic: false,\n        },\n      ],\n    })\n  })\n\n  test('dynamically named slot outlet w/ prefixIdentifiers: true', () => {\n    const ast = parseWithSlots(`<slot :name=\"foo + bar\" />`, {\n      prefixIdentifiers: true,\n    })\n    expect((ast.children[0] as ElementNode).codegenNode).toMatchObject({\n      type: NodeTypes.JS_CALL_EXPRESSION,\n      callee: RENDER_SLOT,\n      arguments: [\n        `_ctx.$slots`,\n        {\n          type: NodeTypes.COMPOUND_EXPRESSION,\n          children: [\n            {\n              type: NodeTypes.SIMPLE_EXPRESSION,\n              content: `_ctx.foo`,\n              isStatic: false,\n            },\n            ` + `,\n            {\n              type: NodeTypes.SIMPLE_EXPRESSION,\n              content: `_ctx.bar`,\n              isStatic: false,\n            },\n          ],\n        },\n      ],\n    })\n  })\n\n  test('default slot outlet with props', () => {\n    const ast = parseWithSlots(\n      `<slot foo=\"bar\" :baz=\"qux\" :foo-bar=\"foo-bar\" />`,\n    )\n    expect((ast.children[0] as ElementNode).codegenNode).toMatchObject({\n      type: NodeTypes.JS_CALL_EXPRESSION,\n      callee: RENDER_SLOT,\n      arguments: [\n        `$slots`,\n        `\"default\"`,\n        {\n          type: NodeTypes.JS_OBJECT_EXPRESSION,\n          properties: [\n            {\n              key: {\n                content: `foo`,\n                isStatic: true,\n              },\n              value: {\n                content: `bar`,\n                isStatic: true,\n              },\n            },\n            {\n              key: {\n                content: `baz`,\n                isStatic: true,\n              },\n              value: {\n                content: `qux`,\n                isStatic: false,\n              },\n            },\n            {\n              key: {\n                content: `fooBar`,\n                isStatic: true,\n              },\n              value: {\n                content: `foo-bar`,\n                isStatic: false,\n              },\n            },\n          ],\n        },\n      ],\n    })\n  })\n\n  test('statically named slot outlet with props', () => {\n    const ast = parseWithSlots(`<slot name=\"foo\" foo=\"bar\" :baz=\"qux\" />`)\n    expect((ast.children[0] as ElementNode).codegenNode).toMatchObject({\n      type: NodeTypes.JS_CALL_EXPRESSION,\n      callee: RENDER_SLOT,\n      arguments: [\n        `$slots`,\n        `\"foo\"`,\n        {\n          type: NodeTypes.JS_OBJECT_EXPRESSION,\n          // props should not include name\n          properties: [\n            {\n              key: {\n                content: `foo`,\n                isStatic: true,\n              },\n              value: {\n                content: `bar`,\n                isStatic: true,\n              },\n            },\n            {\n              key: {\n                content: `baz`,\n                isStatic: true,\n              },\n              value: {\n                content: `qux`,\n                isStatic: false,\n              },\n            },\n          ],\n        },\n      ],\n    })\n  })\n\n  test('dynamically named slot outlet with props', () => {\n    const ast = parseWithSlots(`<slot :name=\"foo\" foo=\"bar\" :baz=\"qux\" />`)\n    expect((ast.children[0] as ElementNode).codegenNode).toMatchObject({\n      type: NodeTypes.JS_CALL_EXPRESSION,\n      callee: RENDER_SLOT,\n      arguments: [\n        `$slots`,\n        { content: `foo`, isStatic: false },\n        {\n          type: NodeTypes.JS_OBJECT_EXPRESSION,\n          // props should not include name\n          properties: [\n            {\n              key: {\n                content: `foo`,\n                isStatic: true,\n              },\n              value: {\n                content: `bar`,\n                isStatic: true,\n              },\n            },\n            {\n              key: {\n                content: `baz`,\n                isStatic: true,\n              },\n              value: {\n                content: `qux`,\n                isStatic: false,\n              },\n            },\n          ],\n        },\n      ],\n    })\n  })\n\n  test('default slot outlet with fallback', () => {\n    const ast = parseWithSlots(`<slot><div/></slot>`)\n    expect((ast.children[0] as ElementNode).codegenNode).toMatchObject({\n      type: NodeTypes.JS_CALL_EXPRESSION,\n      callee: RENDER_SLOT,\n      arguments: [\n        `$slots`,\n        `\"default\"`,\n        `{}`,\n        {\n          type: NodeTypes.JS_FUNCTION_EXPRESSION,\n          params: [],\n          returns: [\n            {\n              type: NodeTypes.ELEMENT,\n              tag: `div`,\n            },\n          ],\n        },\n      ],\n    })\n  })\n\n  test('named slot outlet with fallback', () => {\n    const ast = parseWithSlots(`<slot name=\"foo\"><div/></slot>`)\n    expect((ast.children[0] as ElementNode).codegenNode).toMatchObject({\n      type: NodeTypes.JS_CALL_EXPRESSION,\n      callee: RENDER_SLOT,\n      arguments: [\n        `$slots`,\n        `\"foo\"`,\n        `{}`,\n        {\n          type: NodeTypes.JS_FUNCTION_EXPRESSION,\n          params: [],\n          returns: [\n            {\n              type: NodeTypes.ELEMENT,\n              tag: `div`,\n            },\n          ],\n        },\n      ],\n    })\n  })\n\n  test('default slot outlet with props & fallback', () => {\n    const ast = parseWithSlots(`<slot :foo=\"bar\"><div/></slot>`)\n    expect((ast.children[0] as ElementNode).codegenNode).toMatchObject({\n      type: NodeTypes.JS_CALL_EXPRESSION,\n      callee: RENDER_SLOT,\n      arguments: [\n        `$slots`,\n        `\"default\"`,\n        {\n          type: NodeTypes.JS_OBJECT_EXPRESSION,\n          properties: [\n            {\n              key: {\n                content: `foo`,\n                isStatic: true,\n              },\n              value: {\n                content: `bar`,\n                isStatic: false,\n              },\n            },\n          ],\n        },\n        {\n          type: NodeTypes.JS_FUNCTION_EXPRESSION,\n          params: [],\n          returns: [\n            {\n              type: NodeTypes.ELEMENT,\n              tag: `div`,\n            },\n          ],\n        },\n      ],\n    })\n  })\n\n  test('named slot outlet with props & fallback', () => {\n    const ast = parseWithSlots(`<slot name=\"foo\" :foo=\"bar\"><div/></slot>`)\n    expect((ast.children[0] as ElementNode).codegenNode).toMatchObject({\n      type: NodeTypes.JS_CALL_EXPRESSION,\n      callee: RENDER_SLOT,\n      arguments: [\n        `$slots`,\n        `\"foo\"`,\n        {\n          type: NodeTypes.JS_OBJECT_EXPRESSION,\n          properties: [\n            {\n              key: {\n                content: `foo`,\n                isStatic: true,\n              },\n              value: {\n                content: `bar`,\n                isStatic: false,\n              },\n            },\n          ],\n        },\n        {\n          type: NodeTypes.JS_FUNCTION_EXPRESSION,\n          params: [],\n          returns: [\n            {\n              type: NodeTypes.ELEMENT,\n              tag: `div`,\n            },\n          ],\n        },\n      ],\n    })\n  })\n\n  test('slot with slotted: false', async () => {\n    const ast = parseWithSlots(`<slot/>`, { slotted: false, scopeId: 'foo' })\n    expect((ast.children[0] as ElementNode).codegenNode).toMatchObject({\n      type: NodeTypes.JS_CALL_EXPRESSION,\n      callee: RENDER_SLOT,\n      arguments: [`$slots`, `\"default\"`, `{}`, `undefined`, `true`],\n    })\n    const fallback = parseWithSlots(`<slot>fallback</slot>`, {\n      slotted: false,\n      scopeId: 'foo',\n    })\n\n    const child = {\n      type: NodeTypes.JS_FUNCTION_EXPRESSION,\n      params: [],\n      returns: [\n        {\n          type: NodeTypes.TEXT,\n          content: `fallback`,\n        },\n      ],\n    }\n    expect((fallback.children[0] as ElementNode).codegenNode).toMatchObject({\n      type: NodeTypes.JS_CALL_EXPRESSION,\n      callee: RENDER_SLOT,\n      arguments: [`$slots`, `\"default\"`, `{}`, child, `true`],\n    })\n  })\n\n  test(`error on unexpected custom directive on <slot>`, () => {\n    const onError = vi.fn()\n    const source = `<slot v-foo />`\n    parseWithSlots(source, { onError })\n    const index = source.indexOf('v-foo')\n    expect(onError.mock.calls[0][0]).toMatchObject({\n      code: ErrorCodes.X_V_SLOT_UNEXPECTED_DIRECTIVE_ON_SLOT_OUTLET,\n      loc: {\n        start: {\n          offset: index,\n          line: 1,\n          column: index + 1,\n        },\n        end: {\n          offset: index + 5,\n          line: 1,\n          column: index + 6,\n        },\n      },\n    })\n  })\n\n  test('dynamically named slot outlet with v-bind shorthand', () => {\n    const ast = parseWithSlots(`<slot :name />`)\n    expect((ast.children[0] as ElementNode).codegenNode).toMatchObject({\n      type: NodeTypes.JS_CALL_EXPRESSION,\n      callee: RENDER_SLOT,\n      arguments: [\n        `$slots`,\n        {\n          type: NodeTypes.SIMPLE_EXPRESSION,\n          content: `name`,\n          isStatic: false,\n        },\n      ],\n    })\n  })\n})\n"
  },
  {
    "path": "packages/compiler-core/__tests__/transforms/transformText.spec.ts",
    "content": "import {\n  type CompilerOptions,\n  type ElementNode,\n  type ForNode,\n  NodeTypes,\n  generate,\n  isWhitespaceText,\n  baseParse as parse,\n  transform,\n} from '../../src'\nimport { transformFor } from '../../src/transforms/vFor'\nimport { transformText } from '../../src/transforms/transformText'\nimport { transformExpression } from '../../src/transforms/transformExpression'\nimport { transformElement } from '../../src/transforms/transformElement'\nimport { CREATE_TEXT } from '../../src/runtimeHelpers'\nimport { genFlagText } from '../testUtils'\nimport { PatchFlags } from '@vue/shared'\n\nfunction transformWithTextOpt(template: string, options: CompilerOptions = {}) {\n  const ast = parse(template)\n  transform(ast, {\n    nodeTransforms: [\n      transformFor,\n      ...(options.prefixIdentifiers ? [transformExpression] : []),\n      transformElement,\n      transformText,\n    ],\n    ...options,\n  })\n  return ast\n}\n\ndescribe('compiler: transform text', () => {\n  test('no consecutive text', () => {\n    const root = transformWithTextOpt(`{{ foo }}`)\n    expect(root.children[0]).toMatchObject({\n      type: NodeTypes.INTERPOLATION,\n      content: {\n        content: `foo`,\n      },\n    })\n    expect(generate(root).code).toMatchSnapshot()\n  })\n\n  test('consecutive text', () => {\n    const root = transformWithTextOpt(`{{ foo }} bar {{ baz }}`)\n    expect(root.children.length).toBe(1)\n    expect(root.children[0]).toMatchObject({\n      type: NodeTypes.COMPOUND_EXPRESSION,\n      children: [\n        { type: NodeTypes.INTERPOLATION, content: { content: `foo` } },\n        ` + `,\n        { type: NodeTypes.TEXT, content: ` bar ` },\n        ` + `,\n        { type: NodeTypes.INTERPOLATION, content: { content: `baz` } },\n      ],\n    })\n    expect(generate(root).code).toMatchSnapshot()\n  })\n\n  test('consecutive text between elements', () => {\n    const root = transformWithTextOpt(`<div/>{{ foo }} bar {{ baz }}<div/>`)\n    expect(root.children.length).toBe(3)\n    expect(root.children[0].type).toBe(NodeTypes.ELEMENT)\n    expect(root.children[1]).toMatchObject({\n      // when mixed with elements, should convert it into a text node call\n      type: NodeTypes.TEXT_CALL,\n      codegenNode: {\n        type: NodeTypes.JS_CALL_EXPRESSION,\n        callee: CREATE_TEXT,\n        arguments: [\n          {\n            type: NodeTypes.COMPOUND_EXPRESSION,\n            children: [\n              { type: NodeTypes.INTERPOLATION, content: { content: `foo` } },\n              ` + `,\n              { type: NodeTypes.TEXT, content: ` bar ` },\n              ` + `,\n              { type: NodeTypes.INTERPOLATION, content: { content: `baz` } },\n            ],\n          },\n          genFlagText(PatchFlags.TEXT),\n        ],\n      },\n    })\n    expect(root.children[2].type).toBe(NodeTypes.ELEMENT)\n    expect(generate(root).code).toMatchSnapshot()\n  })\n\n  test('text between elements (static)', () => {\n    const root = transformWithTextOpt(`<div/>hello<div/>`)\n    expect(root.children.length).toBe(3)\n    expect(root.children[0].type).toBe(NodeTypes.ELEMENT)\n    expect(root.children[1]).toMatchObject({\n      // when mixed with elements, should convert it into a text node call\n      type: NodeTypes.TEXT_CALL,\n      codegenNode: {\n        type: NodeTypes.JS_CALL_EXPRESSION,\n        callee: CREATE_TEXT,\n        arguments: [\n          {\n            type: NodeTypes.TEXT,\n            content: `hello`,\n          },\n          // should have no flag\n        ],\n      },\n    })\n    expect(root.children[2].type).toBe(NodeTypes.ELEMENT)\n    expect(generate(root).code).toMatchSnapshot()\n  })\n\n  test('whitespace text', () => {\n    const root = transformWithTextOpt(`<div/>hello<div/>  <div/>`)\n    expect(root.children.length).toBe(5)\n    expect(root.children[0].type).toBe(NodeTypes.ELEMENT)\n    expect(root.children[1].type).toBe(NodeTypes.TEXT_CALL)\n    expect(root.children[2].type).toBe(NodeTypes.ELEMENT)\n    expect(root.children[3].type).toBe(NodeTypes.TEXT_CALL)\n    expect(root.children[4].type).toBe(NodeTypes.ELEMENT)\n\n    expect(root.children.map(isWhitespaceText)).toEqual([\n      false,\n      false,\n      false,\n      true,\n      false,\n    ])\n  })\n\n  test('consecutive text mixed with elements', () => {\n    const root = transformWithTextOpt(\n      `<div/>{{ foo }} bar {{ baz }}<div/>hello<div/>`,\n    )\n    expect(root.children.length).toBe(5)\n    expect(root.children[0].type).toBe(NodeTypes.ELEMENT)\n    expect(root.children[1]).toMatchObject({\n      type: NodeTypes.TEXT_CALL,\n      codegenNode: {\n        type: NodeTypes.JS_CALL_EXPRESSION,\n        callee: CREATE_TEXT,\n        arguments: [\n          {\n            type: NodeTypes.COMPOUND_EXPRESSION,\n            children: [\n              { type: NodeTypes.INTERPOLATION, content: { content: `foo` } },\n              ` + `,\n              { type: NodeTypes.TEXT, content: ` bar ` },\n              ` + `,\n              { type: NodeTypes.INTERPOLATION, content: { content: `baz` } },\n            ],\n          },\n          genFlagText(PatchFlags.TEXT),\n        ],\n      },\n    })\n    expect(root.children[2].type).toBe(NodeTypes.ELEMENT)\n    expect(root.children[3]).toMatchObject({\n      type: NodeTypes.TEXT_CALL,\n      codegenNode: {\n        type: NodeTypes.JS_CALL_EXPRESSION,\n        callee: CREATE_TEXT,\n        arguments: [\n          {\n            type: NodeTypes.TEXT,\n            content: `hello`,\n          },\n        ],\n      },\n    })\n    expect(root.children[4].type).toBe(NodeTypes.ELEMENT)\n    expect(generate(root).code).toMatchSnapshot()\n  })\n\n  test('<template v-for>', () => {\n    const root = transformWithTextOpt(\n      `<template v-for=\"i in list\">foo</template>`,\n    )\n    expect(root.children[0].type).toBe(NodeTypes.FOR)\n    const forNode = root.children[0] as ForNode\n    // should convert template v-for text children because they are inside\n    // fragments\n    expect(forNode.children[0]).toMatchObject({\n      type: NodeTypes.TEXT_CALL,\n    })\n    expect(generate(root).code).toMatchSnapshot()\n  })\n\n  test('with prefixIdentifiers: true', () => {\n    const root = transformWithTextOpt(`{{ foo }} bar {{ baz + qux }}`, {\n      prefixIdentifiers: true,\n    })\n    expect(root.children.length).toBe(1)\n    expect(root.children[0]).toMatchObject({\n      type: NodeTypes.COMPOUND_EXPRESSION,\n      children: [\n        { type: NodeTypes.INTERPOLATION, content: { content: `_ctx.foo` } },\n        ` + `,\n        { type: NodeTypes.TEXT, content: ` bar ` },\n        ` + `,\n        {\n          type: NodeTypes.INTERPOLATION,\n          content: {\n            type: NodeTypes.COMPOUND_EXPRESSION,\n            children: [{ content: `_ctx.baz` }, ` + `, { content: `_ctx.qux` }],\n          },\n        },\n      ],\n    })\n    expect(\n      generate(root, {\n        prefixIdentifiers: true,\n      }).code,\n    ).toMatchSnapshot()\n  })\n\n  // #3756\n  test('element with custom directives and only one text child node', () => {\n    const root = transformWithTextOpt(`<p v-foo>{{ foo }}</p>`)\n    expect(root.children.length).toBe(1)\n    expect(root.children[0].type).toBe(NodeTypes.ELEMENT)\n    expect((root.children[0] as ElementNode).children[0]).toMatchObject({\n      type: NodeTypes.TEXT_CALL,\n      codegenNode: {\n        type: NodeTypes.JS_CALL_EXPRESSION,\n        callee: CREATE_TEXT,\n        arguments: [\n          {\n            type: NodeTypes.INTERPOLATION,\n            content: {\n              type: NodeTypes.SIMPLE_EXPRESSION,\n              content: 'foo',\n            },\n          },\n          genFlagText(PatchFlags.TEXT),\n        ],\n      },\n    })\n    expect(generate(root).code).toMatchSnapshot()\n  })\n})\n"
  },
  {
    "path": "packages/compiler-core/__tests__/transforms/vBind.spec.ts",
    "content": "import {\n  type CallExpression,\n  type CompilerOptions,\n  type ElementNode,\n  ErrorCodes,\n  NodeTypes,\n  type ObjectExpression,\n  type VNodeCall,\n  baseParse as parse,\n  transform,\n} from '../../src'\nimport { transformBind } from '../../src/transforms/vBind'\nimport { transformElement } from '../../src/transforms/transformElement'\nimport {\n  CAMELIZE,\n  NORMALIZE_PROPS,\n  helperNameMap,\n} from '../../src/runtimeHelpers'\nimport { transformExpression } from '../../src/transforms/transformExpression'\nimport { transformVBindShorthand } from '../../src/transforms/transformVBindShorthand'\n\nfunction parseWithVBind(\n  template: string,\n  options: CompilerOptions = {},\n): ElementNode {\n  const ast = parse(template)\n  transform(ast, {\n    nodeTransforms: [\n      transformVBindShorthand,\n      ...(options.prefixIdentifiers ? [transformExpression] : []),\n      transformElement,\n    ],\n    directiveTransforms: {\n      bind: transformBind,\n    },\n    ...options,\n  })\n  return ast.children[0] as ElementNode\n}\n\ndescribe('compiler: transform v-bind', () => {\n  test('basic', () => {\n    const node = parseWithVBind(`<div v-bind:id=\"id\"/>`)\n    const props = (node.codegenNode as VNodeCall).props as ObjectExpression\n    expect(props.properties[0]).toMatchObject({\n      key: {\n        content: `id`,\n        isStatic: true,\n        loc: {\n          start: {\n            line: 1,\n            column: 13,\n          },\n          end: {\n            line: 1,\n            column: 15,\n          },\n        },\n      },\n      value: {\n        content: `id`,\n        isStatic: false,\n        loc: {\n          start: {\n            line: 1,\n            column: 17,\n          },\n          end: {\n            line: 1,\n            column: 19,\n          },\n        },\n      },\n    })\n  })\n\n  test('no expression', () => {\n    const node = parseWithVBind(`<div v-bind:id />`)\n    const props = (node.codegenNode as VNodeCall).props as ObjectExpression\n    expect(props.properties[0]).toMatchObject({\n      key: {\n        content: `id`,\n        isStatic: true,\n        loc: {\n          start: { line: 1, column: 13, offset: 12 },\n          end: { line: 1, column: 15, offset: 14 },\n        },\n      },\n      value: {\n        content: `id`,\n        isStatic: false,\n        loc: {\n          start: { line: 1, column: 13, offset: 12 },\n          end: { line: 1, column: 15, offset: 14 },\n        },\n      },\n    })\n  })\n\n  test('no expression (shorthand)', () => {\n    const node = parseWithVBind(`<div :id />`)\n    const props = (node.codegenNode as VNodeCall).props as ObjectExpression\n    expect(props.properties[0]).toMatchObject({\n      key: {\n        content: `id`,\n        isStatic: true,\n      },\n      value: {\n        content: `id`,\n        isStatic: false,\n      },\n    })\n  })\n\n  test('no expression (shorthand) in-DOM templates', () => {\n    try {\n      __BROWSER__ = true\n      // :id in in-DOM templates will be parsed into :id=\"\" by browser\n      const node = parseWithVBind(`<div :id=\"\" />`)\n      const props = (node.codegenNode as VNodeCall).props as ObjectExpression\n      expect(props.properties[0]).toMatchObject({\n        key: {\n          content: `id`,\n          isStatic: true,\n        },\n        value: {\n          content: `id`,\n          isStatic: false,\n        },\n      })\n    } finally {\n      __BROWSER__ = false\n    }\n  })\n\n  test('dynamic arg', () => {\n    const node = parseWithVBind(`<div v-bind:[id]=\"id\"/>`)\n    const props = (node.codegenNode as VNodeCall).props as CallExpression\n    expect(props).toMatchObject({\n      type: NodeTypes.JS_CALL_EXPRESSION,\n      callee: NORMALIZE_PROPS,\n      arguments: [\n        {\n          type: NodeTypes.JS_OBJECT_EXPRESSION,\n          properties: [\n            {\n              key: {\n                content: `id || \"\"`,\n                isStatic: false,\n              },\n              value: {\n                content: `id`,\n                isStatic: false,\n              },\n            },\n          ],\n        },\n      ],\n    })\n  })\n\n  test('should error if empty expression', () => {\n    const onError = vi.fn()\n    const node = parseWithVBind(`<div v-bind:arg=\"\" />`, { onError })\n    const props = (node.codegenNode as VNodeCall).props as ObjectExpression\n    expect(onError.mock.calls[0][0]).toMatchObject({\n      code: ErrorCodes.X_V_BIND_NO_EXPRESSION,\n      loc: {\n        start: {\n          line: 1,\n          column: 6,\n        },\n        end: {\n          line: 1,\n          column: 19,\n        },\n      },\n    })\n    expect(props.properties[0]).toMatchObject({\n      key: {\n        content: `arg`,\n        isStatic: true,\n      },\n      value: {\n        content: ``,\n        isStatic: true,\n      },\n    })\n  })\n\n  test('.camel modifier', () => {\n    const node = parseWithVBind(`<div v-bind:foo-bar.camel=\"id\"/>`)\n    const props = (node.codegenNode as VNodeCall).props as ObjectExpression\n    expect(props.properties[0]).toMatchObject({\n      key: {\n        content: `fooBar`,\n        isStatic: true,\n      },\n      value: {\n        content: `id`,\n        isStatic: false,\n      },\n    })\n  })\n\n  test('.camel modifier w/ no expression', () => {\n    const node = parseWithVBind(`<div v-bind:foo-bar.camel />`)\n    const props = (node.codegenNode as VNodeCall).props as ObjectExpression\n    expect(props.properties[0]).toMatchObject({\n      key: {\n        content: `fooBar`,\n        isStatic: true,\n      },\n      value: {\n        content: `fooBar`,\n        isStatic: false,\n      },\n    })\n  })\n\n  test('.camel modifier w/ dynamic arg', () => {\n    const node = parseWithVBind(`<div v-bind:[foo].camel=\"id\"/>`)\n    const props = (node.codegenNode as VNodeCall).props as CallExpression\n    expect(props).toMatchObject({\n      type: NodeTypes.JS_CALL_EXPRESSION,\n      callee: NORMALIZE_PROPS,\n      arguments: [\n        {\n          type: NodeTypes.JS_OBJECT_EXPRESSION,\n          properties: [\n            {\n              key: {\n                content: `_${helperNameMap[CAMELIZE]}(foo || \"\")`,\n                isStatic: false,\n              },\n              value: {\n                content: `id`,\n                isStatic: false,\n              },\n            },\n          ],\n        },\n      ],\n    })\n  })\n\n  test('.camel modifier w/ dynamic arg + prefixIdentifiers', () => {\n    const node = parseWithVBind(`<div v-bind:[foo(bar)].camel=\"id\"/>`, {\n      prefixIdentifiers: true,\n    })\n    const props = (node.codegenNode as VNodeCall).props as CallExpression\n    expect(props).toMatchObject({\n      type: NodeTypes.JS_CALL_EXPRESSION,\n      callee: NORMALIZE_PROPS,\n      arguments: [\n        {\n          type: NodeTypes.JS_OBJECT_EXPRESSION,\n          properties: [\n            {\n              key: {\n                children: [\n                  `_${helperNameMap[CAMELIZE]}(`,\n                  `(`,\n                  { content: `_ctx.foo` },\n                  `(`,\n                  { content: `_ctx.bar` },\n                  `)`,\n                  `) || \"\"`,\n                  `)`,\n                ],\n              },\n              value: {\n                content: `_ctx.id`,\n                isStatic: false,\n              },\n            },\n          ],\n        },\n      ],\n    })\n  })\n\n  test('.prop modifier', () => {\n    const node = parseWithVBind(`<div v-bind:fooBar.prop=\"id\"/>`)\n    const props = (node.codegenNode as VNodeCall).props as ObjectExpression\n    expect(props.properties[0]).toMatchObject({\n      key: {\n        content: `.fooBar`,\n        isStatic: true,\n      },\n      value: {\n        content: `id`,\n        isStatic: false,\n      },\n    })\n  })\n\n  test('.prop modifier w/ no expression', () => {\n    const node = parseWithVBind(`<div v-bind:fooBar.prop />`)\n    const props = (node.codegenNode as VNodeCall).props as ObjectExpression\n    expect(props.properties[0]).toMatchObject({\n      key: {\n        content: `.fooBar`,\n        isStatic: true,\n      },\n      value: {\n        content: `fooBar`,\n        isStatic: false,\n      },\n    })\n  })\n\n  test('.prop modifier w/ dynamic arg', () => {\n    const node = parseWithVBind(`<div v-bind:[fooBar].prop=\"id\"/>`)\n    const props = (node.codegenNode as VNodeCall).props as CallExpression\n    expect(props).toMatchObject({\n      type: NodeTypes.JS_CALL_EXPRESSION,\n      callee: NORMALIZE_PROPS,\n      arguments: [\n        {\n          type: NodeTypes.JS_OBJECT_EXPRESSION,\n          properties: [\n            {\n              key: {\n                content: '`.${fooBar || \"\"}`',\n                isStatic: false,\n              },\n              value: {\n                content: `id`,\n                isStatic: false,\n              },\n            },\n          ],\n        },\n      ],\n    })\n  })\n\n  test('.prop modifier w/ dynamic arg + prefixIdentifiers', () => {\n    const node = parseWithVBind(`<div v-bind:[foo(bar)].prop=\"id\"/>`, {\n      prefixIdentifiers: true,\n    })\n    const props = (node.codegenNode as VNodeCall).props as CallExpression\n    expect(props).toMatchObject({\n      type: NodeTypes.JS_CALL_EXPRESSION,\n      callee: NORMALIZE_PROPS,\n      arguments: [\n        {\n          type: NodeTypes.JS_OBJECT_EXPRESSION,\n          properties: [\n            {\n              key: {\n                children: [\n                  `'.' + (`,\n                  `(`,\n                  { content: `_ctx.foo` },\n                  `(`,\n                  { content: `_ctx.bar` },\n                  `)`,\n                  `) || \"\"`,\n                  `)`,\n                ],\n              },\n              value: {\n                content: `_ctx.id`,\n                isStatic: false,\n              },\n            },\n          ],\n        },\n      ],\n    })\n  })\n\n  test('.prop modifier (shorthand)', () => {\n    const node = parseWithVBind(`<div .fooBar=\"id\"/>`)\n    const props = (node.codegenNode as VNodeCall).props as ObjectExpression\n    expect(props.properties[0]).toMatchObject({\n      key: {\n        content: `.fooBar`,\n        isStatic: true,\n      },\n      value: {\n        content: `id`,\n        isStatic: false,\n      },\n    })\n  })\n\n  test('.prop modifier (shortband) w/ no expression', () => {\n    const node = parseWithVBind(`<div .fooBar />`)\n    const props = (node.codegenNode as VNodeCall).props as ObjectExpression\n    expect(props.properties[0]).toMatchObject({\n      key: {\n        content: `.fooBar`,\n        isStatic: true,\n      },\n      value: {\n        content: `fooBar`,\n        isStatic: false,\n      },\n    })\n  })\n\n  test('.attr modifier', () => {\n    const node = parseWithVBind(`<div v-bind:foo-bar.attr=\"id\"/>`)\n    const props = (node.codegenNode as VNodeCall).props as ObjectExpression\n    expect(props.properties[0]).toMatchObject({\n      key: {\n        content: `^foo-bar`,\n        isStatic: true,\n      },\n      value: {\n        content: `id`,\n        isStatic: false,\n      },\n    })\n  })\n\n  test('.attr modifier w/ no expression', () => {\n    const node = parseWithVBind(`<div v-bind:foo-bar.attr />`)\n    const props = (node.codegenNode as VNodeCall).props as ObjectExpression\n    expect(props.properties[0]).toMatchObject({\n      key: {\n        content: `^foo-bar`,\n        isStatic: true,\n      },\n      value: {\n        content: `fooBar`,\n        isStatic: false,\n      },\n    })\n  })\n\n  test('error on invalid argument for same-name shorthand', () => {\n    const onError = vi.fn()\n    parseWithVBind(`<div v-bind:[arg] />`, { onError })\n    expect(onError.mock.calls[0][0]).toMatchObject({\n      code: ErrorCodes.X_V_BIND_INVALID_SAME_NAME_ARGUMENT,\n      loc: {\n        start: {\n          line: 1,\n          column: 13,\n        },\n        end: {\n          line: 1,\n          column: 18,\n        },\n      },\n    })\n  })\n})\n"
  },
  {
    "path": "packages/compiler-core/__tests__/transforms/vFor.spec.ts",
    "content": "import { baseParse as parse } from '../../src/parser'\nimport { transform } from '../../src/transform'\nimport { transformIf } from '../../src/transforms/vIf'\nimport { transformFor } from '../../src/transforms/vFor'\nimport { transformBind } from '../../src/transforms/vBind'\nimport { transformElement } from '../../src/transforms/transformElement'\nimport { transformSlotOutlet } from '../../src/transforms/transformSlotOutlet'\nimport { transformExpression } from '../../src/transforms/transformExpression'\nimport {\n  ConstantTypes,\n  type ElementNode,\n  type ForCodegenNode,\n  type ForNode,\n  type InterpolationNode,\n  NodeTypes,\n  type RootNode,\n  type SimpleExpressionNode,\n} from '../../src/ast'\nimport { ErrorCodes } from '../../src/errors'\nimport { type CompilerOptions, generate } from '../../src'\nimport { FRAGMENT, RENDER_LIST, RENDER_SLOT } from '../../src/runtimeHelpers'\nimport { PatchFlags } from '@vue/shared'\nimport { createObjectMatcher } from '../testUtils'\nimport { transformVBindShorthand } from '../../src/transforms/transformVBindShorthand'\n\nexport function parseWithForTransform(\n  template: string,\n  options: CompilerOptions = {},\n): {\n  root: RootNode\n  node: ForNode & { codegenNode: ForCodegenNode }\n} {\n  const ast = parse(template, options)\n  transform(ast, {\n    nodeTransforms: [\n      transformVBindShorthand,\n      transformIf,\n      transformFor,\n      ...(options.prefixIdentifiers ? [transformExpression] : []),\n      transformSlotOutlet,\n      transformElement,\n    ],\n    directiveTransforms: {\n      bind: transformBind,\n    },\n    ...options,\n  })\n  return {\n    root: ast,\n    node: ast.children[0] as ForNode & { codegenNode: ForCodegenNode },\n  }\n}\n\ndescribe('compiler: v-for', () => {\n  describe('transform', () => {\n    test('number expression', () => {\n      const { node: forNode } = parseWithForTransform(\n        '<span v-for=\"index in 5\" />',\n      )\n      expect(forNode.keyAlias).toBeUndefined()\n      expect(forNode.objectIndexAlias).toBeUndefined()\n      expect((forNode.valueAlias as SimpleExpressionNode).content).toBe('index')\n      expect((forNode.source as SimpleExpressionNode).content).toBe('5')\n    })\n\n    test('value', () => {\n      const { node: forNode } = parseWithForTransform(\n        '<span v-for=\"(item) in items\" />',\n      )\n      expect(forNode.keyAlias).toBeUndefined()\n      expect(forNode.objectIndexAlias).toBeUndefined()\n      expect((forNode.valueAlias as SimpleExpressionNode).content).toBe('item')\n      expect((forNode.source as SimpleExpressionNode).content).toBe('items')\n    })\n\n    test('object de-structured value', () => {\n      const { node: forNode } = parseWithForTransform(\n        '<span v-for=\"({ id, value }) in items\" />',\n      )\n      expect(forNode.keyAlias).toBeUndefined()\n      expect(forNode.objectIndexAlias).toBeUndefined()\n      expect((forNode.valueAlias as SimpleExpressionNode).content).toBe(\n        '{ id, value }',\n      )\n      expect((forNode.source as SimpleExpressionNode).content).toBe('items')\n    })\n\n    test('array de-structured value', () => {\n      const { node: forNode } = parseWithForTransform(\n        '<span v-for=\"([ id, value ]) in items\" />',\n      )\n      expect(forNode.keyAlias).toBeUndefined()\n      expect(forNode.objectIndexAlias).toBeUndefined()\n      expect((forNode.valueAlias as SimpleExpressionNode).content).toBe(\n        '[ id, value ]',\n      )\n      expect((forNode.source as SimpleExpressionNode).content).toBe('items')\n    })\n\n    test('value and key', () => {\n      const { node: forNode } = parseWithForTransform(\n        '<span v-for=\"(item, key) in items\" />',\n      )\n      expect(forNode.keyAlias).not.toBeUndefined()\n      expect((forNode.keyAlias as SimpleExpressionNode).content).toBe('key')\n      expect(forNode.objectIndexAlias).toBeUndefined()\n      expect((forNode.valueAlias as SimpleExpressionNode).content).toBe('item')\n      expect((forNode.source as SimpleExpressionNode).content).toBe('items')\n    })\n\n    test('value, key and index', () => {\n      const { node: forNode } = parseWithForTransform(\n        '<span v-for=\"(value, key, index) in items\" />',\n      )\n      expect(forNode.keyAlias).not.toBeUndefined()\n      expect((forNode.keyAlias as SimpleExpressionNode).content).toBe('key')\n      expect(forNode.objectIndexAlias).not.toBeUndefined()\n      expect((forNode.objectIndexAlias as SimpleExpressionNode).content).toBe(\n        'index',\n      )\n      expect((forNode.valueAlias as SimpleExpressionNode).content).toBe('value')\n      expect((forNode.source as SimpleExpressionNode).content).toBe('items')\n    })\n\n    test('skipped key', () => {\n      const { node: forNode } = parseWithForTransform(\n        '<span v-for=\"(value,,index) in items\" />',\n      )\n      expect(forNode.keyAlias).toBeUndefined()\n      expect(forNode.objectIndexAlias).not.toBeUndefined()\n      expect((forNode.objectIndexAlias as SimpleExpressionNode).content).toBe(\n        'index',\n      )\n      expect((forNode.valueAlias as SimpleExpressionNode).content).toBe('value')\n      expect((forNode.source as SimpleExpressionNode).content).toBe('items')\n    })\n\n    test('skipped value and key', () => {\n      const { node: forNode } = parseWithForTransform(\n        '<span v-for=\"(,,index) in items\" />',\n      )\n      expect(forNode.keyAlias).toBeUndefined()\n      expect(forNode.objectIndexAlias).not.toBeUndefined()\n      expect((forNode.objectIndexAlias as SimpleExpressionNode).content).toBe(\n        'index',\n      )\n      expect(forNode.valueAlias).toBeUndefined()\n      expect((forNode.source as SimpleExpressionNode).content).toBe('items')\n    })\n\n    test('unbracketed value', () => {\n      const { node: forNode } = parseWithForTransform(\n        '<span v-for=\"item in items\" />',\n      )\n      expect(forNode.keyAlias).toBeUndefined()\n      expect(forNode.objectIndexAlias).toBeUndefined()\n      expect((forNode.valueAlias as SimpleExpressionNode).content).toBe('item')\n      expect((forNode.source as SimpleExpressionNode).content).toBe('items')\n    })\n\n    test('unbracketed value and key', () => {\n      const { node: forNode } = parseWithForTransform(\n        '<span v-for=\"item, key in items\" />',\n      )\n      expect(forNode.keyAlias).not.toBeUndefined()\n      expect((forNode.keyAlias as SimpleExpressionNode).content).toBe('key')\n      expect(forNode.objectIndexAlias).toBeUndefined()\n      expect((forNode.valueAlias as SimpleExpressionNode).content).toBe('item')\n      expect((forNode.source as SimpleExpressionNode).content).toBe('items')\n    })\n\n    test('unbracketed value, key and index', () => {\n      const { node: forNode } = parseWithForTransform(\n        '<span v-for=\"value, key, index in items\" />',\n      )\n      expect(forNode.keyAlias).not.toBeUndefined()\n      expect((forNode.keyAlias as SimpleExpressionNode).content).toBe('key')\n      expect(forNode.objectIndexAlias).not.toBeUndefined()\n      expect((forNode.objectIndexAlias as SimpleExpressionNode).content).toBe(\n        'index',\n      )\n      expect((forNode.valueAlias as SimpleExpressionNode).content).toBe('value')\n      expect((forNode.source as SimpleExpressionNode).content).toBe('items')\n    })\n\n    test('unbracketed skipped key', () => {\n      const { node: forNode } = parseWithForTransform(\n        '<span v-for=\"value, , index in items\" />',\n      )\n      expect(forNode.keyAlias).toBeUndefined()\n      expect(forNode.objectIndexAlias).not.toBeUndefined()\n      expect((forNode.objectIndexAlias as SimpleExpressionNode).content).toBe(\n        'index',\n      )\n      expect((forNode.valueAlias as SimpleExpressionNode).content).toBe('value')\n      expect((forNode.source as SimpleExpressionNode).content).toBe('items')\n    })\n\n    test('unbracketed skipped value and key', () => {\n      const { node: forNode } = parseWithForTransform(\n        '<span v-for=\", , index in items\" />',\n      )\n      expect(forNode.keyAlias).toBeUndefined()\n      expect(forNode.objectIndexAlias).not.toBeUndefined()\n      expect((forNode.objectIndexAlias as SimpleExpressionNode).content).toBe(\n        'index',\n      )\n      expect(forNode.valueAlias).toBeUndefined()\n      expect((forNode.source as SimpleExpressionNode).content).toBe('items')\n    })\n\n    test('source containing string expression with spaces', () => {\n      const { node: forNode } = parseWithForTransform(\n        `<span v-for=\"item in state ['my items']\" />`,\n      )\n      expect(forNode.keyAlias).toBeUndefined()\n      expect(forNode.objectIndexAlias).toBeUndefined()\n      expect((forNode.valueAlias as SimpleExpressionNode).content).toBe('item')\n      expect((forNode.source as SimpleExpressionNode).content).toBe(\n        \"state ['my items']\",\n      )\n    })\n  })\n\n  describe('errors', () => {\n    test('missing expression', () => {\n      const onError = vi.fn()\n      parseWithForTransform('<span v-for />', { onError })\n\n      expect(onError).toHaveBeenCalledTimes(1)\n      expect(onError).toHaveBeenCalledWith(\n        expect.objectContaining({\n          code: ErrorCodes.X_V_FOR_NO_EXPRESSION,\n        }),\n      )\n    })\n\n    test('empty expression', () => {\n      const onError = vi.fn()\n      parseWithForTransform('<span v-for=\"\" />', { onError })\n\n      expect(onError).toHaveBeenCalledTimes(1)\n      expect(onError).toHaveBeenCalledWith(\n        expect.objectContaining({\n          code: ErrorCodes.X_V_FOR_MALFORMED_EXPRESSION,\n        }),\n      )\n    })\n\n    test('invalid expression', () => {\n      const onError = vi.fn()\n      parseWithForTransform('<span v-for=\"items\" />', { onError })\n\n      expect(onError).toHaveBeenCalledTimes(1)\n      expect(onError).toHaveBeenCalledWith(\n        expect.objectContaining({\n          code: ErrorCodes.X_V_FOR_MALFORMED_EXPRESSION,\n        }),\n      )\n    })\n\n    test('missing source', () => {\n      const onError = vi.fn()\n      parseWithForTransform('<span v-for=\"item in\" />', { onError })\n\n      expect(onError).toHaveBeenCalledTimes(1)\n      expect(onError).toHaveBeenCalledWith(\n        expect.objectContaining({\n          code: ErrorCodes.X_V_FOR_MALFORMED_EXPRESSION,\n        }),\n      )\n    })\n\n    test('missing source and have multiple spaces with', () => {\n      const onError = vi.fn()\n      parseWithForTransform('<span v-for=\"item in  \" />', { onError })\n\n      expect(onError).toHaveBeenCalledTimes(1)\n      expect(onError).toHaveBeenCalledWith(\n        expect.objectContaining({\n          code: ErrorCodes.X_V_FOR_MALFORMED_EXPRESSION,\n        }),\n      )\n    })\n\n    test('missing value', () => {\n      const onError = vi.fn()\n      parseWithForTransform('<span v-for=\"in items\" />', { onError })\n\n      expect(onError).toHaveBeenCalledTimes(1)\n      expect(onError).toHaveBeenCalledWith(\n        expect.objectContaining({\n          code: ErrorCodes.X_V_FOR_MALFORMED_EXPRESSION,\n        }),\n      )\n    })\n\n    test('<template v-for> key placement', () => {\n      const onError = vi.fn()\n      parseWithForTransform(\n        `\n      <template v-for=\"item in items\">\n        <div :key=\"item.id\"/>\n      </template>`,\n        { onError },\n      )\n\n      expect(onError).toHaveBeenCalledTimes(1)\n      expect(onError).toHaveBeenCalledWith(\n        expect.objectContaining({\n          code: ErrorCodes.X_V_FOR_TEMPLATE_KEY_PLACEMENT,\n        }),\n      )\n\n      // should not warn on nested v-for keys\n      parseWithForTransform(\n        `\n      <template v-for=\"item in items\">\n        <div v-for=\"c in item.children\" :key=\"c.id\"/>\n      </template>`,\n        { onError },\n      )\n      expect(onError).toHaveBeenCalledTimes(1)\n    })\n  })\n\n  describe('source location', () => {\n    test('value & source', () => {\n      const source = '<span v-for=\"item in items\" />'\n      const { node: forNode } = parseWithForTransform(source)\n\n      const itemOffset = source.indexOf('item')\n      const value = forNode.valueAlias as SimpleExpressionNode\n      expect((forNode.valueAlias as SimpleExpressionNode).content).toBe('item')\n      expect(value.loc.start.offset).toBe(itemOffset)\n      expect(value.loc.start.line).toBe(1)\n      expect(value.loc.start.column).toBe(itemOffset + 1)\n      expect(value.loc.end.line).toBe(1)\n      expect(value.loc.end.column).toBe(itemOffset + 1 + `item`.length)\n\n      const itemsOffset = source.indexOf('items')\n      expect((forNode.source as SimpleExpressionNode).content).toBe('items')\n      expect(forNode.source.loc.start.offset).toBe(itemsOffset)\n      expect(forNode.source.loc.start.line).toBe(1)\n      expect(forNode.source.loc.start.column).toBe(itemsOffset + 1)\n      expect(forNode.source.loc.end.line).toBe(1)\n      expect(forNode.source.loc.end.column).toBe(\n        itemsOffset + 1 + `items`.length,\n      )\n    })\n\n    test('bracketed value', () => {\n      const source = '<span v-for=\"( item ) in items\" />'\n      const { node: forNode } = parseWithForTransform(source)\n\n      const itemOffset = source.indexOf('item')\n      const value = forNode.valueAlias as SimpleExpressionNode\n      expect(value.content).toBe('item')\n      expect(value.loc.start.offset).toBe(itemOffset)\n      expect(value.loc.start.line).toBe(1)\n      expect(value.loc.start.column).toBe(itemOffset + 1)\n      expect(value.loc.end.line).toBe(1)\n      expect(value.loc.end.column).toBe(itemOffset + 1 + `item`.length)\n\n      const itemsOffset = source.indexOf('items')\n      expect((forNode.source as SimpleExpressionNode).content).toBe('items')\n      expect(forNode.source.loc.start.offset).toBe(itemsOffset)\n      expect(forNode.source.loc.start.line).toBe(1)\n      expect(forNode.source.loc.start.column).toBe(itemsOffset + 1)\n      expect(forNode.source.loc.end.line).toBe(1)\n      expect(forNode.source.loc.end.column).toBe(\n        itemsOffset + 1 + `items`.length,\n      )\n    })\n\n    test('de-structured value', () => {\n      const source = '<span v-for=\"(  { id, key }) in items\" />'\n      const { node: forNode } = parseWithForTransform(source)\n\n      const value = forNode.valueAlias as SimpleExpressionNode\n      const valueIndex = source.indexOf('{ id, key }')\n      expect(value.content).toBe('{ id, key }')\n      expect(value.loc.start.offset).toBe(valueIndex)\n      expect(value.loc.start.line).toBe(1)\n      expect(value.loc.start.column).toBe(valueIndex + 1)\n      expect(value.loc.end.line).toBe(1)\n      expect(value.loc.end.column).toBe(valueIndex + 1 + '{ id, key }'.length)\n\n      const itemsOffset = source.indexOf('items')\n      expect((forNode.source as SimpleExpressionNode).content).toBe('items')\n      expect(forNode.source.loc.start.offset).toBe(itemsOffset)\n      expect(forNode.source.loc.start.line).toBe(1)\n      expect(forNode.source.loc.start.column).toBe(itemsOffset + 1)\n      expect(forNode.source.loc.end.line).toBe(1)\n      expect(forNode.source.loc.end.column).toBe(\n        itemsOffset + 1 + `items`.length,\n      )\n    })\n\n    test('bracketed value, key, index', () => {\n      const source = '<span v-for=\"( item, key, index ) in items\" />'\n      const { node: forNode } = parseWithForTransform(source)\n\n      const itemOffset = source.indexOf('item')\n      const value = forNode.valueAlias as SimpleExpressionNode\n      expect(value.content).toBe('item')\n      expect(value.loc.start.offset).toBe(itemOffset)\n      expect(value.loc.start.line).toBe(1)\n      expect(value.loc.start.column).toBe(itemOffset + 1)\n      expect(value.loc.end.line).toBe(1)\n      expect(value.loc.end.column).toBe(itemOffset + 1 + `item`.length)\n\n      const keyOffset = source.indexOf('key')\n      const key = forNode.keyAlias as SimpleExpressionNode\n      expect(key.content).toBe('key')\n      expect(key.loc.start.offset).toBe(keyOffset)\n      expect(key.loc.start.line).toBe(1)\n      expect(key.loc.start.column).toBe(keyOffset + 1)\n      expect(key.loc.end.line).toBe(1)\n      expect(key.loc.end.column).toBe(keyOffset + 1 + `key`.length)\n\n      const indexOffset = source.indexOf('index')\n      const index = forNode.objectIndexAlias as SimpleExpressionNode\n      expect(index.content).toBe('index')\n      expect(index.loc.start.offset).toBe(indexOffset)\n      expect(index.loc.start.line).toBe(1)\n      expect(index.loc.start.column).toBe(indexOffset + 1)\n      expect(index.loc.end.line).toBe(1)\n      expect(index.loc.end.column).toBe(indexOffset + 1 + `index`.length)\n\n      const itemsOffset = source.indexOf('items')\n      expect((forNode.source as SimpleExpressionNode).content).toBe('items')\n      expect(forNode.source.loc.start.offset).toBe(itemsOffset)\n      expect(forNode.source.loc.start.line).toBe(1)\n      expect(forNode.source.loc.start.column).toBe(itemsOffset + 1)\n      expect(forNode.source.loc.end.line).toBe(1)\n      expect(forNode.source.loc.end.column).toBe(\n        itemsOffset + 1 + `items`.length,\n      )\n    })\n\n    test('skipped key', () => {\n      const source = '<span v-for=\"( item,, index ) in items\" />'\n      const { node: forNode } = parseWithForTransform(source)\n\n      const itemOffset = source.indexOf('item')\n      const value = forNode.valueAlias as SimpleExpressionNode\n      expect(value.content).toBe('item')\n      expect(value.loc.start.offset).toBe(itemOffset)\n      expect(value.loc.start.line).toBe(1)\n      expect(value.loc.start.column).toBe(itemOffset + 1)\n      expect(value.loc.end.line).toBe(1)\n      expect(value.loc.end.column).toBe(itemOffset + 1 + `item`.length)\n\n      const indexOffset = source.indexOf('index')\n      const index = forNode.objectIndexAlias as SimpleExpressionNode\n      expect(index.content).toBe('index')\n      expect(index.loc.start.offset).toBe(indexOffset)\n      expect(index.loc.start.line).toBe(1)\n      expect(index.loc.start.column).toBe(indexOffset + 1)\n      expect(index.loc.end.line).toBe(1)\n      expect(index.loc.end.column).toBe(indexOffset + 1 + `index`.length)\n\n      const itemsOffset = source.indexOf('items')\n      expect((forNode.source as SimpleExpressionNode).content).toBe('items')\n      expect(forNode.source.loc.start.offset).toBe(itemsOffset)\n      expect(forNode.source.loc.start.line).toBe(1)\n      expect(forNode.source.loc.start.column).toBe(itemsOffset + 1)\n      expect(forNode.source.loc.end.line).toBe(1)\n      expect(forNode.source.loc.end.column).toBe(\n        itemsOffset + 1 + `items`.length,\n      )\n    })\n  })\n\n  describe('prefixIdentifiers: true', () => {\n    test('should prefix v-for source', () => {\n      const { node } = parseWithForTransform(`<div v-for=\"i in list\"/>`, {\n        prefixIdentifiers: true,\n      })\n      expect(node.source).toMatchObject({\n        type: NodeTypes.SIMPLE_EXPRESSION,\n        content: `_ctx.list`,\n      })\n    })\n\n    test('should prefix v-for source w/ complex expression', () => {\n      const { node } = parseWithForTransform(\n        `<div v-for=\"i in list.concat([foo])\"/>`,\n        { prefixIdentifiers: true },\n      )\n      expect(node.source).toMatchObject({\n        type: NodeTypes.COMPOUND_EXPRESSION,\n        children: [\n          { content: `_ctx.list` },\n          `.`,\n          { content: `concat` },\n          `([`,\n          { content: `_ctx.foo` },\n          `])`,\n        ],\n      })\n    })\n\n    test('should not prefix v-for alias', () => {\n      const { node } = parseWithForTransform(\n        `<div v-for=\"i in list\">{{ i }}{{ j }}</div>`,\n        { prefixIdentifiers: true },\n      )\n      const div = node.children[0] as ElementNode\n      expect((div.children[0] as InterpolationNode).content).toMatchObject({\n        type: NodeTypes.SIMPLE_EXPRESSION,\n        content: `i`,\n      })\n      expect((div.children[1] as InterpolationNode).content).toMatchObject({\n        type: NodeTypes.SIMPLE_EXPRESSION,\n        content: `_ctx.j`,\n      })\n    })\n\n    test('should not prefix v-for aliases (multiple)', () => {\n      const { node } = parseWithForTransform(\n        `<div v-for=\"(i, j, k) in list\">{{ i + j + k }}{{ l }}</div>`,\n        { prefixIdentifiers: true },\n      )\n      const div = node.children[0] as ElementNode\n      expect((div.children[0] as InterpolationNode).content).toMatchObject({\n        type: NodeTypes.COMPOUND_EXPRESSION,\n        children: [\n          { content: `i` },\n          ` + `,\n          { content: `j` },\n          ` + `,\n          { content: `k` },\n        ],\n      })\n      expect((div.children[1] as InterpolationNode).content).toMatchObject({\n        type: NodeTypes.SIMPLE_EXPRESSION,\n        content: `_ctx.l`,\n      })\n    })\n\n    test('should prefix id outside of v-for', () => {\n      const { node } = parseWithForTransform(\n        `<div><div v-for=\"i in list\" />{{ i }}</div>`,\n        { prefixIdentifiers: true },\n      )\n      expect((node.children[1] as InterpolationNode).content).toMatchObject({\n        type: NodeTypes.SIMPLE_EXPRESSION,\n        content: `_ctx.i`,\n      })\n    })\n\n    test('nested v-for', () => {\n      const { node } = parseWithForTransform(\n        `<div v-for=\"i in list\">\n          <div v-for=\"i in list\">{{ i + j }}</div>{{ i }}\n        </div>`,\n        { prefixIdentifiers: true },\n      )\n      const outerDiv = node.children[0] as ElementNode\n      const innerFor = outerDiv.children[0] as ForNode\n      const innerExp = (innerFor.children[0] as ElementNode)\n        .children[0] as InterpolationNode\n      expect(innerExp.content).toMatchObject({\n        type: NodeTypes.COMPOUND_EXPRESSION,\n        children: [{ content: 'i' }, ` + `, { content: `_ctx.j` }],\n      })\n\n      // when an inner v-for shadows a variable of an outer v-for and exit,\n      // it should not cause the outer v-for's alias to be removed from known ids\n      const outerExp = outerDiv.children[1] as InterpolationNode\n      expect(outerExp.content).toMatchObject({\n        type: NodeTypes.SIMPLE_EXPRESSION,\n        content: `i`,\n      })\n    })\n\n    test('v-for aliases w/ complex expressions', () => {\n      const { node } = parseWithForTransform(\n        `<div v-for=\"({ foo = bar, baz: [qux = quux] }) in list\">\n          {{ foo + bar + baz + qux + quux }}\n        </div>`,\n        { prefixIdentifiers: true },\n      )\n      expect(node.valueAlias!).toMatchObject({\n        type: NodeTypes.COMPOUND_EXPRESSION,\n        children: [\n          `{ `,\n          { content: `foo` },\n          ` = `,\n          { content: `_ctx.bar` },\n          `, baz: [`,\n          { content: `qux` },\n          ` = `,\n          { content: `_ctx.quux` },\n          `] }`,\n        ],\n      })\n      const div = node.children[0] as ElementNode\n      expect((div.children[0] as InterpolationNode).content).toMatchObject({\n        type: NodeTypes.COMPOUND_EXPRESSION,\n        children: [\n          { content: `foo` },\n          ` + `,\n          { content: `_ctx.bar` },\n          ` + `,\n          { content: `_ctx.baz` },\n          ` + `,\n          { content: `qux` },\n          ` + `,\n          { content: `_ctx.quux` },\n        ],\n      })\n    })\n\n    test('element v-for key expression prefixing', () => {\n      const {\n        node: { codegenNode },\n      } = parseWithForTransform(\n        '<div v-for=\"item in items\" :key=\"itemKey(item)\">test</div>',\n        { prefixIdentifiers: true },\n      )\n      const innerBlock = codegenNode.children.arguments[1].returns\n      expect(innerBlock).toMatchObject({\n        type: NodeTypes.VNODE_CALL,\n        tag: `\"div\"`,\n        props: createObjectMatcher({\n          key: {\n            type: NodeTypes.COMPOUND_EXPRESSION,\n            children: [\n              // should prefix outer scope references\n              { content: `_ctx.itemKey` },\n              `(`,\n              // should NOT prefix in scope variables\n              { content: `item` },\n              `)`,\n            ],\n          },\n        }),\n      })\n    })\n\n    // #2085\n    test('template v-for key expression prefixing', () => {\n      const {\n        node: { codegenNode },\n      } = parseWithForTransform(\n        '<template v-for=\"item in items\" :key=\"itemKey(item)\">test</template>',\n        { prefixIdentifiers: true },\n      )\n      const innerBlock = codegenNode.children.arguments[1].returns\n      expect(innerBlock).toMatchObject({\n        type: NodeTypes.VNODE_CALL,\n        tag: FRAGMENT,\n        props: createObjectMatcher({\n          key: {\n            type: NodeTypes.COMPOUND_EXPRESSION,\n            children: [\n              // should prefix outer scope references\n              { content: `_ctx.itemKey` },\n              `(`,\n              // should NOT prefix in scope variables\n              { content: `item` },\n              `)`,\n            ],\n          },\n        }),\n      })\n    })\n\n    test('template v-for key no prefixing on attribute key', () => {\n      const {\n        node: { codegenNode },\n      } = parseWithForTransform(\n        '<template v-for=\"item in items\" key=\"key\">test</template>',\n        { prefixIdentifiers: true },\n      )\n      const innerBlock = codegenNode.children.arguments[1].returns\n      expect(innerBlock).toMatchObject({\n        type: NodeTypes.VNODE_CALL,\n        tag: FRAGMENT,\n        props: createObjectMatcher({\n          key: {\n            type: NodeTypes.SIMPLE_EXPRESSION,\n            content: 'key',\n          },\n        }),\n      })\n    })\n  })\n\n  describe('codegen', () => {\n    function assertSharedCodegen(\n      node: ForCodegenNode,\n      keyed: boolean = false,\n      customReturn: boolean = false,\n      disableTracking: boolean = true,\n    ) {\n      expect(node).toMatchObject({\n        type: NodeTypes.VNODE_CALL,\n        tag: FRAGMENT,\n        disableTracking,\n        patchFlag: !disableTracking\n          ? PatchFlags.STABLE_FRAGMENT\n          : keyed\n            ? PatchFlags.KEYED_FRAGMENT\n            : PatchFlags.UNKEYED_FRAGMENT,\n        children: {\n          type: NodeTypes.JS_CALL_EXPRESSION,\n          callee: RENDER_LIST,\n          arguments: [\n            {}, // to be asserted by each test\n            {\n              type: NodeTypes.JS_FUNCTION_EXPRESSION,\n              returns: customReturn\n                ? {}\n                : {\n                    type: NodeTypes.VNODE_CALL,\n                    isBlock: disableTracking,\n                  },\n            },\n          ],\n        },\n      })\n      const renderListArgs = node.children.arguments\n      return {\n        source: renderListArgs[0] as SimpleExpressionNode,\n        params: (renderListArgs[1] as any).params,\n        returns: (renderListArgs[1] as any).returns,\n        innerVNodeCall: customReturn\n          ? null\n          : (renderListArgs[1] as any).returns,\n      }\n    }\n\n    test('basic v-for', () => {\n      const {\n        root,\n        node: { codegenNode },\n      } = parseWithForTransform('<span v-for=\"(item) in items\" />')\n      expect(assertSharedCodegen(codegenNode)).toMatchObject({\n        source: { content: `items` },\n        params: [{ content: `item` }],\n        innerVNodeCall: {\n          tag: `\"span\"`,\n        },\n      })\n      expect(generate(root).code).toMatchSnapshot()\n    })\n\n    test('value + key + index', () => {\n      const {\n        root,\n        node: { codegenNode },\n      } = parseWithForTransform('<span v-for=\"(item, key, index) in items\" />')\n      expect(assertSharedCodegen(codegenNode)).toMatchObject({\n        source: { content: `items` },\n        params: [{ content: `item` }, { content: `key` }, { content: `index` }],\n      })\n      expect(generate(root).code).toMatchSnapshot()\n    })\n\n    test('skipped value', () => {\n      const {\n        root,\n        node: { codegenNode },\n      } = parseWithForTransform('<span v-for=\"(, key, index) in items\" />')\n      expect(assertSharedCodegen(codegenNode)).toMatchObject({\n        source: { content: `items` },\n        params: [{ content: `_` }, { content: `key` }, { content: `index` }],\n      })\n      expect(generate(root).code).toMatchSnapshot()\n    })\n\n    test('skipped key', () => {\n      const {\n        root,\n        node: { codegenNode },\n      } = parseWithForTransform('<span v-for=\"(item,,index) in items\" />')\n      expect(assertSharedCodegen(codegenNode)).toMatchObject({\n        source: { content: `items` },\n        params: [{ content: `item` }, { content: `__` }, { content: `index` }],\n      })\n      expect(generate(root).code).toMatchSnapshot()\n    })\n\n    test('skipped value & key', () => {\n      const {\n        root,\n        node: { codegenNode },\n      } = parseWithForTransform('<span v-for=\"(,,index) in items\" />')\n      expect(assertSharedCodegen(codegenNode)).toMatchObject({\n        source: { content: `items` },\n        params: [{ content: `_` }, { content: `__` }, { content: `index` }],\n      })\n      expect(generate(root).code).toMatchSnapshot()\n    })\n\n    test('v-for with constant expression', () => {\n      const {\n        root,\n        node: { codegenNode },\n      } = parseWithForTransform('<p v-for=\"item in 10\">{{item}}</p>', {\n        prefixIdentifiers: true,\n      })\n\n      expect(\n        assertSharedCodegen(\n          codegenNode,\n          false /* keyed */,\n          false /* customReturn */,\n          false /* disableTracking */,\n        ),\n      ).toMatchObject({\n        source: { content: `10`, constType: ConstantTypes.CAN_STRINGIFY },\n        params: [{ content: `item` }],\n        innerVNodeCall: {\n          tag: `\"p\"`,\n          props: undefined,\n          isBlock: false,\n          children: {\n            type: NodeTypes.INTERPOLATION,\n            content: {\n              type: NodeTypes.SIMPLE_EXPRESSION,\n              content: 'item',\n              isStatic: false,\n              constType: ConstantTypes.NOT_CONSTANT,\n            },\n          },\n          patchFlag: PatchFlags.TEXT,\n        },\n      })\n      expect(generate(root).code).toMatchSnapshot()\n    })\n\n    test('template v-for', () => {\n      const {\n        root,\n        node: { codegenNode },\n      } = parseWithForTransform(\n        '<template v-for=\"item in items\">hello<span/></template>',\n      )\n      expect(assertSharedCodegen(codegenNode)).toMatchObject({\n        source: { content: `items` },\n        params: [{ content: `item` }],\n        innerVNodeCall: {\n          tag: FRAGMENT,\n          props: undefined,\n          isBlock: true,\n          children: [\n            { type: NodeTypes.TEXT, content: `hello` },\n            { type: NodeTypes.ELEMENT, tag: `span` },\n          ],\n          patchFlag: PatchFlags.STABLE_FRAGMENT,\n        },\n      })\n      expect(generate(root).code).toMatchSnapshot()\n    })\n\n    test('template v-for w/ <slot/>', () => {\n      const {\n        root,\n        node: { codegenNode },\n      } = parseWithForTransform(\n        '<template v-for=\"item in items\"><slot/></template>',\n      )\n      expect(\n        assertSharedCodegen(codegenNode, false, true /* custom return */),\n      ).toMatchObject({\n        source: { content: `items` },\n        params: [{ content: `item` }],\n        returns: {\n          type: NodeTypes.JS_CALL_EXPRESSION,\n          callee: RENDER_SLOT,\n        },\n      })\n      expect(generate(root).code).toMatchSnapshot()\n    })\n\n    // #1907\n    test('template v-for key injection with single child', () => {\n      const {\n        root,\n        node: { codegenNode },\n      } = parseWithForTransform(\n        '<template v-for=\"item in items\" :key=\"item.id\"><span :id=\"item.id\" /></template>',\n      )\n      expect(assertSharedCodegen(codegenNode, true)).toMatchObject({\n        source: { content: `items` },\n        params: [{ content: `item` }],\n        innerVNodeCall: {\n          type: NodeTypes.VNODE_CALL,\n          tag: `\"span\"`,\n          props: createObjectMatcher({\n            key: '[item.id]',\n            id: '[item.id]',\n          }),\n        },\n      })\n      expect(generate(root).code).toMatchSnapshot()\n    })\n\n    test('v-for on <slot/>', () => {\n      const {\n        root,\n        node: { codegenNode },\n      } = parseWithForTransform('<slot v-for=\"item in items\"></slot>')\n      expect(\n        assertSharedCodegen(codegenNode, false, true /* custom return */),\n      ).toMatchObject({\n        source: { content: `items` },\n        params: [{ content: `item` }],\n        returns: {\n          type: NodeTypes.JS_CALL_EXPRESSION,\n          callee: RENDER_SLOT,\n        },\n      })\n      expect(generate(root).code).toMatchSnapshot()\n    })\n\n    test('keyed v-for', () => {\n      const {\n        root,\n        node: { codegenNode },\n      } = parseWithForTransform('<span v-for=\"(item) in items\" :key=\"item\" />')\n      expect(assertSharedCodegen(codegenNode, true)).toMatchObject({\n        source: { content: `items` },\n        params: [{ content: `item` }],\n        innerVNodeCall: {\n          tag: `\"span\"`,\n          props: createObjectMatcher({\n            key: `[item]`,\n          }),\n        },\n      })\n      expect(generate(root).code).toMatchSnapshot()\n    })\n\n    test('keyed template v-for', () => {\n      const {\n        root,\n        node: { codegenNode },\n      } = parseWithForTransform(\n        '<template v-for=\"item in items\" :key=\"item\">hello<span/></template>',\n      )\n      expect(assertSharedCodegen(codegenNode, true)).toMatchObject({\n        source: { content: `items` },\n        params: [{ content: `item` }],\n        innerVNodeCall: {\n          tag: FRAGMENT,\n          props: createObjectMatcher({\n            key: `[item]`,\n          }),\n          children: [\n            { type: NodeTypes.TEXT, content: `hello` },\n            { type: NodeTypes.ELEMENT, tag: `span` },\n          ],\n          patchFlag: PatchFlags.STABLE_FRAGMENT,\n        },\n      })\n      expect(generate(root).code).toMatchSnapshot()\n    })\n\n    test('v-if + v-for', () => {\n      const {\n        root,\n        node: { codegenNode },\n      } = parseWithForTransform(`<div v-if=\"ok\" v-for=\"i in list\"/>`)\n      expect(codegenNode).toMatchObject({\n        type: NodeTypes.JS_CONDITIONAL_EXPRESSION,\n        test: { content: `ok` },\n        consequent: {\n          type: NodeTypes.VNODE_CALL,\n          props: createObjectMatcher({\n            key: `[0]`,\n          }),\n          isBlock: true,\n          disableTracking: true,\n          patchFlag: PatchFlags.UNKEYED_FRAGMENT,\n          children: {\n            type: NodeTypes.JS_CALL_EXPRESSION,\n            callee: RENDER_LIST,\n            arguments: [\n              { content: `list` },\n              {\n                type: NodeTypes.JS_FUNCTION_EXPRESSION,\n                params: [{ content: `i` }],\n                returns: {\n                  type: NodeTypes.VNODE_CALL,\n                  tag: `\"div\"`,\n                  isBlock: true,\n                },\n              },\n            ],\n          },\n        },\n      })\n      expect(generate(root).code).toMatchSnapshot()\n    })\n\n    // 1637\n    test('v-if + v-for on <template>', () => {\n      const {\n        root,\n        node: { codegenNode },\n      } = parseWithForTransform(`<template v-if=\"ok\" v-for=\"i in list\"/>`)\n      expect(codegenNode).toMatchObject({\n        type: NodeTypes.JS_CONDITIONAL_EXPRESSION,\n        test: { content: `ok` },\n        consequent: {\n          type: NodeTypes.VNODE_CALL,\n          props: createObjectMatcher({\n            key: `[0]`,\n          }),\n          isBlock: true,\n          disableTracking: true,\n          patchFlag: PatchFlags.UNKEYED_FRAGMENT,\n          children: {\n            type: NodeTypes.JS_CALL_EXPRESSION,\n            callee: RENDER_LIST,\n            arguments: [\n              { content: `list` },\n              {\n                type: NodeTypes.JS_FUNCTION_EXPRESSION,\n                params: [{ content: `i` }],\n                returns: {\n                  type: NodeTypes.VNODE_CALL,\n                  tag: FRAGMENT,\n                  isBlock: true,\n                },\n              },\n            ],\n          },\n        },\n      })\n      expect(generate(root).code).toMatchSnapshot()\n    })\n\n    test('v-for on element with custom directive', () => {\n      const {\n        root,\n        node: { codegenNode },\n      } = parseWithForTransform('<div v-for=\"i in list\" v-foo/>')\n      const { returns } = assertSharedCodegen(codegenNode, false, true)\n      expect(returns).toMatchObject({\n        type: NodeTypes.VNODE_CALL,\n        directives: { type: NodeTypes.JS_ARRAY_EXPRESSION },\n      })\n      expect(generate(root).code).toMatchSnapshot()\n    })\n\n    test('template v-for key w/ :key shorthand on div', () => {\n      const {\n        node: { codegenNode },\n      } = parseWithForTransform('<div v-for=\"key in keys\" :key>test</div>')\n      expect(codegenNode.patchFlag).toBe(PatchFlags.KEYED_FRAGMENT)\n    })\n\n    test('template v-for key w/ :key shorthand on template injected to the child', () => {\n      const {\n        node: { codegenNode },\n      } = parseWithForTransform(\n        '<template v-for=\"key in keys\" :key><div>test</div></template>',\n      )\n      expect(assertSharedCodegen(codegenNode, true)).toMatchObject({\n        source: { content: `keys` },\n        params: [{ content: `key` }],\n        innerVNodeCall: {\n          type: NodeTypes.VNODE_CALL,\n          tag: `\"div\"`,\n          props: createObjectMatcher({\n            key: '[key]',\n          }),\n        },\n      })\n    })\n  })\n})\n"
  },
  {
    "path": "packages/compiler-core/__tests__/transforms/vIf.spec.ts",
    "content": "import { baseParse as parse } from '../../src/parser'\nimport { transform } from '../../src/transform'\nimport { transformIf } from '../../src/transforms/vIf'\nimport { transformElement } from '../../src/transforms/transformElement'\nimport { transformSlotOutlet } from '../../src/transforms/transformSlotOutlet'\nimport {\n  type CommentNode,\n  type ConditionalExpression,\n  type ElementNode,\n  ElementTypes,\n  type IfBranchNode,\n  type IfConditionalExpression,\n  type IfNode,\n  NodeTypes,\n  type SimpleExpressionNode,\n  type TextNode,\n  type VNodeCall,\n} from '../../src/ast'\nimport { ErrorCodes } from '../../src/errors'\nimport {\n  type CompilerOptions,\n  TO_HANDLERS,\n  generate,\n  transformVBindShorthand,\n} from '../../src'\nimport {\n  CREATE_COMMENT,\n  FRAGMENT,\n  MERGE_PROPS,\n  NORMALIZE_PROPS,\n  RENDER_SLOT,\n} from '../../src/runtimeHelpers'\nimport { createObjectMatcher } from '../testUtils'\n\nfunction parseWithIfTransform(\n  template: string,\n  options: CompilerOptions = {},\n  returnIndex: number = 0,\n  childrenLen: number = 1,\n) {\n  const ast = parse(template, options)\n  transform(ast, {\n    nodeTransforms: [\n      transformVBindShorthand,\n      transformIf,\n      transformSlotOutlet,\n      transformElement,\n    ],\n    ...options,\n  })\n  if (!options.onError) {\n    expect(ast.children.length).toBe(childrenLen)\n    for (let i = 0; i < childrenLen; i++) {\n      expect(ast.children[i].type).toBe(NodeTypes.IF)\n    }\n  }\n  return {\n    root: ast,\n    node: ast.children[returnIndex] as IfNode & {\n      codegenNode: IfConditionalExpression\n    },\n  }\n}\n\ndescribe('compiler: v-if', () => {\n  describe('transform', () => {\n    test('basic v-if', () => {\n      const { node } = parseWithIfTransform(`<div v-if=\"ok\"/>`)\n      expect(node.type).toBe(NodeTypes.IF)\n      expect(node.branches.length).toBe(1)\n      expect((node.branches[0].condition as SimpleExpressionNode).content).toBe(\n        `ok`,\n      )\n      expect(node.branches[0].children.length).toBe(1)\n      expect(node.branches[0].children[0].type).toBe(NodeTypes.ELEMENT)\n      expect((node.branches[0].children[0] as ElementNode).tag).toBe(`div`)\n    })\n\n    test('template v-if', () => {\n      const { node } = parseWithIfTransform(\n        `<template v-if=\"ok\"><div/>hello<p/></template>`,\n      )\n      expect(node.type).toBe(NodeTypes.IF)\n      expect(node.branches.length).toBe(1)\n      expect((node.branches[0].condition as SimpleExpressionNode).content).toBe(\n        `ok`,\n      )\n      expect(node.branches[0].children.length).toBe(3)\n      expect(node.branches[0].children[0].type).toBe(NodeTypes.ELEMENT)\n      expect((node.branches[0].children[0] as ElementNode).tag).toBe(`div`)\n      expect(node.branches[0].children[1].type).toBe(NodeTypes.TEXT)\n      expect((node.branches[0].children[1] as TextNode).content).toBe(`hello`)\n      expect(node.branches[0].children[2].type).toBe(NodeTypes.ELEMENT)\n      expect((node.branches[0].children[2] as ElementNode).tag).toBe(`p`)\n    })\n\n    test('component v-if', () => {\n      const { node } = parseWithIfTransform(`<Component v-if=\"ok\"></Component>`)\n      expect(node.type).toBe(NodeTypes.IF)\n      expect(node.branches.length).toBe(1)\n      expect((node.branches[0].children[0] as ElementNode).tag).toBe(\n        `Component`,\n      )\n      expect((node.branches[0].children[0] as ElementNode).tagType).toBe(\n        ElementTypes.COMPONENT,\n      )\n      // #2058 since a component may fail to resolve and fallback to a plain\n      // element, it still needs to be made a block\n      expect(\n        ((node.branches[0].children[0] as ElementNode)!\n          .codegenNode as VNodeCall)!.isBlock,\n      ).toBe(true)\n    })\n\n    test('v-if + v-else', () => {\n      const { node } = parseWithIfTransform(`<div v-if=\"ok\"/><p v-else/>`)\n      expect(node.type).toBe(NodeTypes.IF)\n      expect(node.branches.length).toBe(2)\n\n      const b1 = node.branches[0]\n      expect((b1.condition as SimpleExpressionNode).content).toBe(`ok`)\n      expect(b1.children.length).toBe(1)\n      expect(b1.children[0].type).toBe(NodeTypes.ELEMENT)\n      expect((b1.children[0] as ElementNode).tag).toBe(`div`)\n\n      const b2 = node.branches[1]\n      expect(b2.condition).toBeUndefined()\n      expect(b2.children.length).toBe(1)\n      expect(b2.children[0].type).toBe(NodeTypes.ELEMENT)\n      expect((b2.children[0] as ElementNode).tag).toBe(`p`)\n    })\n\n    test('v-if + v-else-if', () => {\n      const { node } = parseWithIfTransform(\n        `<div v-if=\"ok\"/><p v-else-if=\"orNot\"/>`,\n      )\n      expect(node.type).toBe(NodeTypes.IF)\n      expect(node.branches.length).toBe(2)\n\n      const b1 = node.branches[0]\n      expect((b1.condition as SimpleExpressionNode).content).toBe(`ok`)\n      expect(b1.children.length).toBe(1)\n      expect(b1.children[0].type).toBe(NodeTypes.ELEMENT)\n      expect((b1.children[0] as ElementNode).tag).toBe(`div`)\n\n      const b2 = node.branches[1]\n      expect((b2.condition as SimpleExpressionNode).content).toBe(`orNot`)\n      expect(b2.children.length).toBe(1)\n      expect(b2.children[0].type).toBe(NodeTypes.ELEMENT)\n      expect((b2.children[0] as ElementNode).tag).toBe(`p`)\n    })\n\n    test('v-if + v-else-if + v-else', () => {\n      const { node } = parseWithIfTransform(\n        `<div v-if=\"ok\"/><p v-else-if=\"orNot\"/><template v-else>fine</template>`,\n      )\n      expect(node.type).toBe(NodeTypes.IF)\n      expect(node.branches.length).toBe(3)\n\n      const b1 = node.branches[0]\n      expect((b1.condition as SimpleExpressionNode).content).toBe(`ok`)\n      expect(b1.children.length).toBe(1)\n      expect(b1.children[0].type).toBe(NodeTypes.ELEMENT)\n      expect((b1.children[0] as ElementNode).tag).toBe(`div`)\n\n      const b2 = node.branches[1]\n      expect((b2.condition as SimpleExpressionNode).content).toBe(`orNot`)\n      expect(b2.children.length).toBe(1)\n      expect(b2.children[0].type).toBe(NodeTypes.ELEMENT)\n      expect((b2.children[0] as ElementNode).tag).toBe(`p`)\n\n      const b3 = node.branches[2]\n      expect(b3.condition).toBeUndefined()\n      expect(b3.children.length).toBe(1)\n      expect(b3.children[0].type).toBe(NodeTypes.TEXT)\n      expect((b3.children[0] as TextNode).content).toBe(`fine`)\n    })\n\n    test('comment between branches', () => {\n      const { node } = parseWithIfTransform(`\n        <div v-if=\"ok\"/>\n        <!--foo-->\n        <p v-else-if=\"orNot\"/>\n        <!--bar-->\n        <template v-else>fine</template>\n      `)\n      expect(node.type).toBe(NodeTypes.IF)\n      expect(node.branches.length).toBe(3)\n\n      const b1 = node.branches[0]\n      expect((b1.condition as SimpleExpressionNode).content).toBe(`ok`)\n      expect(b1.children.length).toBe(1)\n      expect(b1.children[0].type).toBe(NodeTypes.ELEMENT)\n      expect((b1.children[0] as ElementNode).tag).toBe(`div`)\n\n      const b2 = node.branches[1]\n      expect((b2.condition as SimpleExpressionNode).content).toBe(`orNot`)\n      expect(b2.children.length).toBe(2)\n      expect(b2.children[0].type).toBe(NodeTypes.COMMENT)\n      expect((b2.children[0] as CommentNode).content).toBe(`foo`)\n      expect(b2.children[1].type).toBe(NodeTypes.ELEMENT)\n      expect((b2.children[1] as ElementNode).tag).toBe(`p`)\n\n      const b3 = node.branches[2]\n      expect(b3.condition).toBeUndefined()\n      expect(b3.children.length).toBe(2)\n      expect(b3.children[0].type).toBe(NodeTypes.COMMENT)\n      expect((b3.children[0] as CommentNode).content).toBe(`bar`)\n      expect(b3.children[1].type).toBe(NodeTypes.TEXT)\n      expect((b3.children[1] as TextNode).content).toBe(`fine`)\n    })\n\n    test('should prefix v-if condition', () => {\n      const { node } = parseWithIfTransform(`<div v-if=\"ok\"/>`, {\n        prefixIdentifiers: true,\n      })\n      expect(node.branches[0].condition).toMatchObject({\n        type: NodeTypes.SIMPLE_EXPRESSION,\n        content: `_ctx.ok`,\n      })\n    })\n\n    //#11321\n    test('v-if + :key shorthand', () => {\n      const { node } = parseWithIfTransform(`<div v-if=\"ok\" :key></div>`)\n      expect(node.type).toBe(NodeTypes.IF)\n      expect(node.branches[0].userKey).toMatchObject({\n        arg: { content: 'key' },\n        exp: { content: 'key' },\n      })\n    })\n  })\n\n  describe('errors', () => {\n    test('error on v-else missing adjacent v-if', () => {\n      const onError = vi.fn()\n\n      const { node: node1 } = parseWithIfTransform(`<div v-else/>`, { onError })\n      expect(onError.mock.calls[0]).toMatchObject([\n        {\n          code: ErrorCodes.X_V_ELSE_NO_ADJACENT_IF,\n          loc: node1.loc,\n        },\n      ])\n\n      const { node: node2 } = parseWithIfTransform(\n        `<div/><div v-else/>`,\n        { onError },\n        1,\n      )\n      expect(onError.mock.calls[1]).toMatchObject([\n        {\n          code: ErrorCodes.X_V_ELSE_NO_ADJACENT_IF,\n          loc: node2.loc,\n        },\n      ])\n\n      const { node: node3 } = parseWithIfTransform(\n        `<div/>foo<div v-else/>`,\n        { onError },\n        2,\n      )\n      expect(onError.mock.calls[2]).toMatchObject([\n        {\n          code: ErrorCodes.X_V_ELSE_NO_ADJACENT_IF,\n          loc: node3.loc,\n        },\n      ])\n\n      const { node: node4 } = parseWithIfTransform(\n        `<div v-if=\"bar\"/>foo<div v-else/>`,\n        { onError },\n        2,\n      )\n      expect(onError.mock.calls[3]).toMatchObject([\n        {\n          code: ErrorCodes.X_V_ELSE_NO_ADJACENT_IF,\n          loc: node4.loc,\n        },\n      ])\n\n      // Non-breaking space\n      const { node: node5 } = parseWithIfTransform(\n        `<div v-if=\"bar\"/>\\u00a0<div v-else/>`,\n        { onError },\n        2,\n      )\n      expect(onError.mock.calls[4]).toMatchObject([\n        {\n          code: ErrorCodes.X_V_ELSE_NO_ADJACENT_IF,\n          loc: node5.loc,\n        },\n      ])\n    })\n\n    test('error on v-else-if missing adjacent v-if or v-else-if', () => {\n      const onError = vi.fn()\n\n      const { node: node1 } = parseWithIfTransform(`<div v-else-if=\"foo\"/>`, {\n        onError,\n      })\n      expect(onError.mock.calls[0]).toMatchObject([\n        {\n          code: ErrorCodes.X_V_ELSE_NO_ADJACENT_IF,\n          loc: node1.loc,\n        },\n      ])\n\n      const { node: node2 } = parseWithIfTransform(\n        `<div/><div v-else-if=\"foo\"/>`,\n        { onError },\n        1,\n      )\n      expect(onError.mock.calls[1]).toMatchObject([\n        {\n          code: ErrorCodes.X_V_ELSE_NO_ADJACENT_IF,\n          loc: node2.loc,\n        },\n      ])\n\n      const { node: node3 } = parseWithIfTransform(\n        `<div/>foo<div v-else-if=\"foo\"/>`,\n        { onError },\n        2,\n      )\n      expect(onError.mock.calls[2]).toMatchObject([\n        {\n          code: ErrorCodes.X_V_ELSE_NO_ADJACENT_IF,\n          loc: node3.loc,\n        },\n      ])\n\n      const { node: node4 } = parseWithIfTransform(\n        `<div v-if=\"bar\"/>foo<div v-else-if=\"foo\"/>`,\n        { onError },\n        2,\n      )\n      expect(onError.mock.calls[3]).toMatchObject([\n        {\n          code: ErrorCodes.X_V_ELSE_NO_ADJACENT_IF,\n          loc: node4.loc,\n        },\n      ])\n\n      // Non-breaking space\n      const { node: node5 } = parseWithIfTransform(\n        `<div v-if=\"bar\"/>\\u00a0<div v-else-if=\"foo\"/>`,\n        { onError },\n        2,\n      )\n      expect(onError.mock.calls[4]).toMatchObject([\n        {\n          code: ErrorCodes.X_V_ELSE_NO_ADJACENT_IF,\n          loc: node5.loc,\n        },\n      ])\n\n      const {\n        node: { branches },\n      } = parseWithIfTransform(\n        `<div v-if=\"notOk\"/><div v-else/><div v-else-if=\"ok\"/>`,\n        { onError },\n        0,\n      )\n\n      expect(onError.mock.calls[5]).toMatchObject([\n        {\n          code: ErrorCodes.X_V_ELSE_NO_ADJACENT_IF,\n          loc: branches[branches.length - 1].loc,\n        },\n      ])\n    })\n\n    test('error on adjacent v-else', () => {\n      const onError = vi.fn()\n\n      const {\n        node: { branches },\n      } = parseWithIfTransform(\n        `<div v-if=\"false\"/><div v-else/><div v-else/>`,\n        { onError },\n        0,\n      )\n\n      expect(onError.mock.calls[0]).toMatchObject([\n        {\n          code: ErrorCodes.X_V_ELSE_NO_ADJACENT_IF,\n          loc: branches[branches.length - 1].loc,\n        },\n      ])\n    })\n\n    test('error on user key', () => {\n      const onError = vi.fn()\n      // dynamic\n      parseWithIfTransform(\n        `<div v-if=\"ok\" :key=\"a + 1\" /><div v-else :key=\"a + 1\" />`,\n        { onError },\n      )\n      expect(onError.mock.calls[0]).toMatchObject([\n        {\n          code: ErrorCodes.X_V_IF_SAME_KEY,\n        },\n      ])\n      // static\n      parseWithIfTransform(`<div v-if=\"ok\" key=\"1\" /><div v-else key=\"1\" />`, {\n        onError,\n      })\n      expect(onError.mock.calls[1]).toMatchObject([\n        {\n          code: ErrorCodes.X_V_IF_SAME_KEY,\n        },\n      ])\n    })\n  })\n\n  describe('codegen', () => {\n    function assertSharedCodegen(\n      node: IfConditionalExpression,\n      depth: number = 0,\n      hasElse: boolean = false,\n    ) {\n      expect(node).toMatchObject({\n        type: NodeTypes.JS_CONDITIONAL_EXPRESSION,\n        test: {\n          content: `ok`,\n        },\n        consequent: {\n          type: NodeTypes.VNODE_CALL,\n          isBlock: true,\n        },\n        alternate:\n          depth < 1\n            ? hasElse\n              ? {\n                  type: NodeTypes.VNODE_CALL,\n                  isBlock: true,\n                }\n              : {\n                  type: NodeTypes.JS_CALL_EXPRESSION,\n                  callee: CREATE_COMMENT,\n                }\n            : {\n                type: NodeTypes.JS_CONDITIONAL_EXPRESSION,\n                test: {\n                  content: `orNot`,\n                },\n                consequent: {\n                  type: NodeTypes.VNODE_CALL,\n                  isBlock: true,\n                },\n                alternate: hasElse\n                  ? {\n                      type: NodeTypes.VNODE_CALL,\n                      isBlock: true,\n                    }\n                  : {\n                      type: NodeTypes.JS_CALL_EXPRESSION,\n                      callee: CREATE_COMMENT,\n                    },\n              },\n      })\n    }\n\n    test('basic v-if', () => {\n      const {\n        root,\n        node: { codegenNode },\n      } = parseWithIfTransform(`<div v-if=\"ok\"/>`)\n      assertSharedCodegen(codegenNode)\n      expect(codegenNode.consequent).toMatchObject({\n        tag: `\"div\"`,\n        props: createObjectMatcher({ key: `[0]` }),\n      })\n      expect(codegenNode.alternate).toMatchObject({\n        type: NodeTypes.JS_CALL_EXPRESSION,\n        callee: CREATE_COMMENT,\n      })\n      expect(generate(root).code).toMatchSnapshot()\n    })\n\n    test('template v-if', () => {\n      const {\n        root,\n        node: { codegenNode },\n      } = parseWithIfTransform(`<template v-if=\"ok\"><div/>hello<p/></template>`)\n      assertSharedCodegen(codegenNode)\n      expect(codegenNode.consequent).toMatchObject({\n        tag: FRAGMENT,\n        props: createObjectMatcher({ key: `[0]` }),\n        children: [\n          { type: NodeTypes.ELEMENT, tag: 'div' },\n          { type: NodeTypes.TEXT, content: `hello` },\n          { type: NodeTypes.ELEMENT, tag: 'p' },\n        ],\n      })\n      expect(codegenNode.alternate).toMatchObject({\n        type: NodeTypes.JS_CALL_EXPRESSION,\n        callee: CREATE_COMMENT,\n      })\n      expect(generate(root).code).toMatchSnapshot()\n    })\n\n    test('template v-if w/ single <slot/> child', () => {\n      const {\n        root,\n        node: { codegenNode },\n      } = parseWithIfTransform(`<template v-if=\"ok\"><slot/></template>`)\n      expect(codegenNode.consequent).toMatchObject({\n        type: NodeTypes.JS_CALL_EXPRESSION,\n        callee: RENDER_SLOT,\n        arguments: ['$slots', '\"default\"', createObjectMatcher({ key: `[0]` })],\n      })\n      expect(generate(root).code).toMatchSnapshot()\n    })\n\n    test('v-if on <slot/>', () => {\n      const {\n        root,\n        node: { codegenNode },\n      } = parseWithIfTransform(`<slot v-if=\"ok\"></slot>`)\n      expect(codegenNode.consequent).toMatchObject({\n        type: NodeTypes.JS_CALL_EXPRESSION,\n        callee: RENDER_SLOT,\n        arguments: ['$slots', '\"default\"', createObjectMatcher({ key: `[0]` })],\n      })\n      expect(generate(root).code).toMatchSnapshot()\n    })\n\n    test('v-if + v-else', () => {\n      const {\n        root,\n        node: { codegenNode },\n      } = parseWithIfTransform(`<div v-if=\"ok\"/><p v-else/>`)\n      assertSharedCodegen(codegenNode, 0, true)\n      expect(codegenNode.consequent).toMatchObject({\n        tag: `\"div\"`,\n        props: createObjectMatcher({ key: `[0]` }),\n      })\n      expect(codegenNode.alternate).toMatchObject({\n        tag: `\"p\"`,\n        props: createObjectMatcher({ key: `[1]` }),\n      })\n      expect(generate(root).code).toMatchSnapshot()\n    })\n\n    test('v-if + v-else-if', () => {\n      const {\n        root,\n        node: { codegenNode },\n      } = parseWithIfTransform(`<div v-if=\"ok\"/><p v-else-if=\"orNot\" />`)\n      assertSharedCodegen(codegenNode, 1)\n      expect(codegenNode.consequent).toMatchObject({\n        tag: `\"div\"`,\n        props: createObjectMatcher({ key: `[0]` }),\n      })\n      const branch2 = codegenNode.alternate as ConditionalExpression\n      expect(branch2.consequent).toMatchObject({\n        tag: `\"p\"`,\n        props: createObjectMatcher({ key: `[1]` }),\n      })\n      expect(generate(root).code).toMatchSnapshot()\n    })\n\n    test('v-if + v-else-if + v-else', () => {\n      const {\n        root,\n        node: { codegenNode },\n      } = parseWithIfTransform(\n        `<div v-if=\"ok\"/><p v-else-if=\"orNot\"/><template v-else>fine</template>`,\n      )\n      assertSharedCodegen(codegenNode, 1, true)\n      expect(codegenNode.consequent).toMatchObject({\n        tag: `\"div\"`,\n        props: createObjectMatcher({ key: `[0]` }),\n      })\n      const branch2 = codegenNode.alternate as ConditionalExpression\n      expect(branch2.consequent).toMatchObject({\n        tag: `\"p\"`,\n        props: createObjectMatcher({ key: `[1]` }),\n      })\n      expect(branch2.alternate).toMatchObject({\n        tag: FRAGMENT,\n        props: createObjectMatcher({ key: `[2]` }),\n        children: [\n          {\n            type: NodeTypes.TEXT,\n            content: `fine`,\n          },\n        ],\n      })\n      expect(generate(root).code).toMatchSnapshot()\n    })\n\n    test('multiple v-if that are sibling nodes should have different keys', () => {\n      const { root } = parseWithIfTransform(\n        `<div v-if=\"ok\"/><p v-if=\"orNot\"/>`,\n        {},\n        0 /* returnIndex, just give the default value */,\n        2 /* childrenLen */,\n      )\n\n      const ifNode = root.children[0] as IfNode & {\n        codegenNode: IfConditionalExpression\n      }\n      expect(ifNode.codegenNode.consequent).toMatchObject({\n        tag: `\"div\"`,\n        props: createObjectMatcher({ key: `[0]` }),\n      })\n      const ifNode2 = root.children[1] as IfNode & {\n        codegenNode: IfConditionalExpression\n      }\n      expect(ifNode2.codegenNode.consequent).toMatchObject({\n        tag: `\"p\"`,\n        props: createObjectMatcher({ key: `[1]` }),\n      })\n      expect(generate(root).code).toMatchSnapshot()\n    })\n\n    test('increasing key: v-if + v-else-if + v-else', () => {\n      const { root } = parseWithIfTransform(\n        `<div v-if=\"ok\"/><p v-else/><div v-if=\"another\"/><p v-else-if=\"orNot\"/><p v-else/>`,\n        {},\n        0 /* returnIndex, just give the default value */,\n        2 /* childrenLen */,\n      )\n      const ifNode = root.children[0] as IfNode & {\n        codegenNode: IfConditionalExpression\n      }\n      expect(ifNode.codegenNode.consequent).toMatchObject({\n        tag: `\"div\"`,\n        props: createObjectMatcher({ key: `[0]` }),\n      })\n      expect(ifNode.codegenNode.alternate).toMatchObject({\n        tag: `\"p\"`,\n        props: createObjectMatcher({ key: `[1]` }),\n      })\n      const ifNode2 = root.children[1] as IfNode & {\n        codegenNode: IfConditionalExpression\n      }\n      expect(ifNode2.codegenNode.consequent).toMatchObject({\n        tag: `\"div\"`,\n        props: createObjectMatcher({ key: `[2]` }),\n      })\n      const branch = ifNode2.codegenNode.alternate as IfConditionalExpression\n      expect(branch.consequent).toMatchObject({\n        tag: `\"p\"`,\n        props: createObjectMatcher({ key: `[3]` }),\n      })\n      expect(branch.alternate).toMatchObject({\n        tag: `\"p\"`,\n        props: createObjectMatcher({ key: `[4]` }),\n      })\n      expect(generate(root).code).toMatchSnapshot()\n    })\n\n    test('key injection (only v-bind)', () => {\n      const {\n        node: { codegenNode },\n      } = parseWithIfTransform(`<div v-if=\"ok\" v-bind=\"obj\"/>`)\n      const branch1 = codegenNode.consequent as VNodeCall\n      expect(branch1.props).toMatchObject({\n        type: NodeTypes.JS_CALL_EXPRESSION,\n        callee: NORMALIZE_PROPS,\n        arguments: [\n          {\n            type: NodeTypes.JS_CALL_EXPRESSION,\n            callee: MERGE_PROPS,\n            arguments: [\n              createObjectMatcher({ key: `[0]` }),\n              { content: `obj` },\n            ],\n          },\n        ],\n      })\n    })\n\n    test('key injection (before v-bind)', () => {\n      const {\n        node: { codegenNode },\n      } = parseWithIfTransform(`<div v-if=\"ok\" id=\"foo\" v-bind=\"obj\"/>`)\n      const branch1 = codegenNode.consequent as VNodeCall\n      expect(branch1.props).toMatchObject({\n        type: NodeTypes.JS_CALL_EXPRESSION,\n        callee: MERGE_PROPS,\n        arguments: [\n          createObjectMatcher({\n            key: '[0]',\n            id: 'foo',\n          }),\n          { content: `obj` },\n        ],\n      })\n    })\n\n    test('key injection (after v-bind)', () => {\n      const {\n        node: { codegenNode },\n      } = parseWithIfTransform(`<div v-if=\"ok\" v-bind=\"obj\" id=\"foo\"/>`)\n      const branch1 = codegenNode.consequent as VNodeCall\n      expect(branch1.props).toMatchObject({\n        type: NodeTypes.JS_CALL_EXPRESSION,\n        callee: MERGE_PROPS,\n        arguments: [\n          createObjectMatcher({ key: `[0]` }),\n          { content: `obj` },\n          createObjectMatcher({\n            id: 'foo',\n          }),\n        ],\n      })\n    })\n\n    test('key injection (w/ custom directive)', () => {\n      const {\n        node: { codegenNode },\n      } = parseWithIfTransform(`<div v-if=\"ok\" v-foo />`)\n      const branch1 = codegenNode.consequent as VNodeCall\n      expect(branch1.directives).not.toBeUndefined()\n      expect(branch1.props).toMatchObject(createObjectMatcher({ key: `[0]` }))\n    })\n\n    // #6631\n    test('avoid duplicate keys', () => {\n      const {\n        node: { codegenNode },\n      } = parseWithIfTransform(`<div v-if=\"ok\" key=\"custom_key\" v-bind=\"obj\"/>`)\n      const branch1 = codegenNode.consequent as VNodeCall\n      expect(branch1.props).toMatchObject({\n        type: NodeTypes.JS_CALL_EXPRESSION,\n        callee: MERGE_PROPS,\n        arguments: [\n          createObjectMatcher({\n            key: 'custom_key',\n          }),\n          { content: `obj` },\n        ],\n      })\n    })\n\n    test('with spaces between branches', () => {\n      const {\n        node: { codegenNode },\n      } = parseWithIfTransform(\n        `<div v-if=\"ok\"/> <div v-else-if=\"no\"/> <div v-else/>`,\n      )\n      expect(codegenNode.consequent).toMatchObject({\n        tag: `\"div\"`,\n        props: createObjectMatcher({ key: `[0]` }),\n      })\n      const branch = codegenNode.alternate as ConditionalExpression\n      expect(branch.consequent).toMatchObject({\n        tag: `\"div\"`,\n        props: createObjectMatcher({ key: `[1]` }),\n      })\n      expect(branch.alternate).toMatchObject({\n        tag: `\"div\"`,\n        props: createObjectMatcher({ key: `[2]` }),\n      })\n    })\n\n    test('with comments', () => {\n      const { node } = parseWithIfTransform(`\n          <template v-if=\"ok\">\n            <!--comment1-->\n            <div v-if=\"ok2\">\n              <!--comment2-->\n            </div>\n            <!--comment3-->\n            <b v-else/>\n            <!--comment4-->\n            <p/>\n          </template>\n        `)\n      expect(node.type).toBe(NodeTypes.IF)\n      expect(node.branches.length).toBe(1)\n\n      const b1 = node.branches[0]\n      expect((b1.condition as SimpleExpressionNode).content).toBe(`ok`)\n      expect(b1.children.length).toBe(4)\n\n      expect(b1.children[0].type).toBe(NodeTypes.COMMENT)\n      expect((b1.children[0] as CommentNode).content).toBe(`comment1`)\n\n      expect(b1.children[1].type).toBe(NodeTypes.IF)\n      expect((b1.children[1] as IfNode).branches.length).toBe(2)\n      const b1b1: ElementNode = (b1.children[1] as IfNode).branches[0]\n        .children[0] as ElementNode\n      expect(b1b1.type).toBe(NodeTypes.ELEMENT)\n      expect(b1b1.tag).toBe('div')\n      expect(b1b1.children[0].type).toBe(NodeTypes.COMMENT)\n      expect((b1b1.children[0] as CommentNode).content).toBe('comment2')\n\n      const b1b2: IfBranchNode = (b1.children[1] as IfNode)\n        .branches[1] as IfBranchNode\n      expect(b1b2.children[0].type).toBe(NodeTypes.COMMENT)\n      expect((b1b2.children[0] as CommentNode).content).toBe(`comment3`)\n      expect(b1b2.children[1].type).toBe(NodeTypes.ELEMENT)\n      expect((b1b2.children[1] as ElementNode).tag).toBe(`b`)\n\n      expect(b1.children[2].type).toBe(NodeTypes.COMMENT)\n      expect((b1.children[2] as CommentNode).content).toBe(`comment4`)\n\n      expect(b1.children[3].type).toBe(NodeTypes.ELEMENT)\n      expect((b1.children[3] as ElementNode).tag).toBe(`p`)\n    })\n\n    // #6843\n    test('should parse correctly with comments: true in prod', () => {\n      __DEV__ = false\n      parseWithIfTransform(\n        `\n          <template v-if=\"ok\">\n            <!--comment1-->\n            <div v-if=\"ok2\">\n              <!--comment2-->\n            </div>\n            <!--comment3-->\n            <b v-else/>\n            <!--comment4-->\n            <p/>\n          </template>\n        `,\n        { comments: true },\n      )\n      __DEV__ = true\n    })\n  })\n\n  test('v-on with v-if', () => {\n    const {\n      node: { codegenNode },\n    } = parseWithIfTransform(\n      `<button v-on=\"{ click: clickEvent }\" v-if=\"true\">w/ v-if</button>`,\n    )\n\n    expect((codegenNode.consequent as any).props.type).toBe(\n      NodeTypes.JS_CALL_EXPRESSION,\n    )\n    expect((codegenNode.consequent as any).props.callee).toBe(MERGE_PROPS)\n    expect(\n      (codegenNode.consequent as any).props.arguments[0].properties[0].value\n        .content,\n    ).toBe('0')\n    expect((codegenNode.consequent as any).props.arguments[1].callee).toBe(\n      TO_HANDLERS,\n    )\n  })\n})\n"
  },
  {
    "path": "packages/compiler-core/__tests__/transforms/vMemo.spec.ts",
    "content": "import { baseCompile } from '../../src'\n\ndescribe('compiler: v-memo transform', () => {\n  function compile(content: string) {\n    return baseCompile(`<div>${content}</div>`, {\n      mode: 'module',\n      prefixIdentifiers: true,\n    }).code\n  }\n\n  test('on root element', () => {\n    expect(\n      baseCompile(`<div v-memo=\"[x]\"></div>`, {\n        mode: 'module',\n        prefixIdentifiers: true,\n      }).code,\n    ).toMatchSnapshot()\n  })\n\n  test('on normal element', () => {\n    expect(compile(`<div v-memo=\"[x]\"></div>`)).toMatchSnapshot()\n  })\n\n  test('on component', () => {\n    expect(compile(`<Comp v-memo=\"[x]\"></Comp>`)).toMatchSnapshot()\n  })\n\n  test('on v-if', () => {\n    expect(\n      compile(\n        `<div v-if=\"ok\" v-memo=\"[x]\"><span>foo</span>bar</div>\n        <Comp v-else v-memo=\"[x]\"></Comp>`,\n      ),\n    ).toMatchSnapshot()\n  })\n\n  test('on v-for', () => {\n    expect(\n      compile(\n        `<div v-for=\"{ x, y } in list\" :key=\"x\" v-memo=\"[x, y === z]\">\n          <span>foobar</span>\n        </div>`,\n      ),\n    ).toMatchSnapshot()\n  })\n\n  test('on template v-for', () => {\n    expect(\n      compile(\n        `<template v-for=\"{ x, y } in list\" :key=\"x\" v-memo=\"[x, y === z]\">\n          <span>foobar</span>\n        </template>`,\n      ),\n    ).toMatchSnapshot()\n  })\n\n  test('element v-for key expression prefixing + v-memo', () => {\n    expect(\n      compile(\n        `<span v-for=\"data of tableData\" :key=\"getId(data)\" v-memo=\"getLetter(data)\"></span>`,\n      ),\n    ).toMatchSnapshot()\n  })\n})\n"
  },
  {
    "path": "packages/compiler-core/__tests__/transforms/vModel.spec.ts",
    "content": "import {\n  BindingTypes,\n  type CompilerOptions,\n  type ComponentNode,\n  type ElementNode,\n  type ForNode,\n  NORMALIZE_PROPS,\n  NodeTypes,\n  type ObjectExpression,\n  type PlainElementNode,\n  type VNodeCall,\n  generate,\n  baseParse as parse,\n  transform,\n} from '../../src'\nimport { ErrorCodes } from '../../src/errors'\nimport { transformModel } from '../../src/transforms/vModel'\nimport { transformElement } from '../../src/transforms/transformElement'\nimport { transformExpression } from '../../src/transforms/transformExpression'\nimport { transformFor } from '../../src/transforms/vFor'\nimport { trackSlotScopes } from '../../src/transforms/vSlot'\nimport type { CallExpression } from '@babel/types'\n\nfunction parseWithVModel(template: string, options: CompilerOptions = {}) {\n  const ast = parse(template)\n\n  transform(ast, {\n    nodeTransforms: [\n      transformFor,\n      transformExpression,\n      transformElement,\n      trackSlotScopes,\n    ],\n    directiveTransforms: {\n      ...options.directiveTransforms,\n      model: transformModel,\n    },\n    ...options,\n  })\n\n  return ast\n}\n\ndescribe('compiler: transform v-model', () => {\n  test('simple expression', () => {\n    const root = parseWithVModel('<input v-model=\"model\" />')\n    const node = root.children[0] as ElementNode\n    const props = ((node.codegenNode as VNodeCall).props as ObjectExpression)\n      .properties\n\n    expect(props[0]).toMatchObject({\n      key: {\n        content: 'modelValue',\n        isStatic: true,\n      },\n      value: {\n        content: 'model',\n        isStatic: false,\n      },\n    })\n\n    expect(props[1]).toMatchObject({\n      key: {\n        content: 'onUpdate:modelValue',\n        isStatic: true,\n      },\n      value: {\n        children: [\n          '$event => ((',\n          {\n            content: 'model',\n            isStatic: false,\n          },\n          ') = $event)',\n        ],\n      },\n    })\n\n    expect(generate(root).code).toMatchSnapshot()\n  })\n\n  test('simple expression (with prefixIdentifiers)', () => {\n    const root = parseWithVModel('<input v-model=\"model\" />', {\n      prefixIdentifiers: true,\n    })\n    const node = root.children[0] as ElementNode\n    const props = ((node.codegenNode as VNodeCall).props as ObjectExpression)\n      .properties\n\n    expect(props[0]).toMatchObject({\n      key: {\n        content: 'modelValue',\n        isStatic: true,\n      },\n      value: {\n        content: '_ctx.model',\n        isStatic: false,\n      },\n    })\n\n    expect(props[1]).toMatchObject({\n      key: {\n        content: 'onUpdate:modelValue',\n        isStatic: true,\n      },\n      value: {\n        children: [\n          '$event => ((',\n          {\n            content: '_ctx.model',\n            isStatic: false,\n          },\n          ') = $event)',\n        ],\n      },\n    })\n\n    expect(generate(root, { mode: 'module' }).code).toMatchSnapshot()\n  })\n\n  // #2426\n  test('simple expression (with multilines)', () => {\n    const root = parseWithVModel('<input v-model=\"\\n model\\n.\\nfoo \\n\" />')\n    const node = root.children[0] as ElementNode\n    const props = ((node.codegenNode as VNodeCall).props as ObjectExpression)\n      .properties\n\n    expect(props[0]).toMatchObject({\n      key: {\n        content: 'modelValue',\n        isStatic: true,\n      },\n      value: {\n        content: '\\n model\\n.\\nfoo \\n',\n        isStatic: false,\n      },\n    })\n\n    expect(props[1]).toMatchObject({\n      key: {\n        content: 'onUpdate:modelValue',\n        isStatic: true,\n      },\n      value: {\n        children: [\n          '$event => ((',\n          {\n            content: '\\n model\\n.\\nfoo \\n',\n            isStatic: false,\n          },\n          ') = $event)',\n        ],\n      },\n    })\n\n    expect(generate(root).code).toMatchSnapshot()\n  })\n\n  test('compound expression', () => {\n    const root = parseWithVModel('<input v-model=\"model[index]\" />')\n    const node = root.children[0] as ElementNode\n    const props = ((node.codegenNode as VNodeCall).props as ObjectExpression)\n      .properties\n\n    expect(props[0]).toMatchObject({\n      key: {\n        content: 'modelValue',\n        isStatic: true,\n      },\n      value: {\n        content: 'model[index]',\n        isStatic: false,\n      },\n    })\n\n    expect(props[1]).toMatchObject({\n      key: {\n        content: 'onUpdate:modelValue',\n        isStatic: true,\n      },\n      value: {\n        children: [\n          '$event => ((',\n          {\n            content: 'model[index]',\n            isStatic: false,\n          },\n          ') = $event)',\n        ],\n      },\n    })\n\n    expect(generate(root).code).toMatchSnapshot()\n  })\n\n  test('compound expression (with prefixIdentifiers)', () => {\n    const root = parseWithVModel('<input v-model=\"model[index]\" />', {\n      prefixIdentifiers: true,\n    })\n    const node = root.children[0] as ElementNode\n    const props = ((node.codegenNode as VNodeCall).props as ObjectExpression)\n      .properties\n\n    expect(props[0]).toMatchObject({\n      key: {\n        content: 'modelValue',\n        isStatic: true,\n      },\n      value: {\n        children: [\n          {\n            content: '_ctx.model',\n            isStatic: false,\n          },\n          '[',\n          {\n            content: '_ctx.index',\n            isStatic: false,\n          },\n          ']',\n        ],\n      },\n    })\n\n    expect(props[1]).toMatchObject({\n      key: {\n        content: 'onUpdate:modelValue',\n        isStatic: true,\n      },\n      value: {\n        children: [\n          '$event => ((',\n          {\n            children: [\n              {\n                content: '_ctx.model',\n                isStatic: false,\n              },\n              '[',\n              {\n                content: '_ctx.index',\n                isStatic: false,\n              },\n              ']',\n            ],\n          },\n          ') = $event)',\n        ],\n      },\n    })\n\n    expect(generate(root, { mode: 'module' }).code).toMatchSnapshot()\n  })\n\n  test('with argument', () => {\n    const root = parseWithVModel('<input v-model:foo-value=\"model\" />')\n    const node = root.children[0] as ElementNode\n    const props = ((node.codegenNode as VNodeCall).props as ObjectExpression)\n      .properties\n    expect(props[0]).toMatchObject({\n      key: {\n        content: 'foo-value',\n        isStatic: true,\n      },\n      value: {\n        content: 'model',\n        isStatic: false,\n      },\n    })\n\n    expect(props[1]).toMatchObject({\n      key: {\n        content: 'onUpdate:fooValue',\n        isStatic: true,\n      },\n      value: {\n        children: [\n          '$event => ((',\n          {\n            content: 'model',\n            isStatic: false,\n          },\n          ') = $event)',\n        ],\n      },\n    })\n\n    expect(generate(root).code).toMatchSnapshot()\n  })\n\n  test('with dynamic argument', () => {\n    const root = parseWithVModel('<input v-model:[value]=\"model\" />')\n    const node = root.children[0] as ElementNode\n    const props = (node.codegenNode as VNodeCall)\n      .props as unknown as CallExpression\n\n    expect(props).toMatchObject({\n      type: NodeTypes.JS_CALL_EXPRESSION,\n      callee: NORMALIZE_PROPS,\n      arguments: [\n        {\n          type: NodeTypes.JS_OBJECT_EXPRESSION,\n          properties: [\n            {\n              key: {\n                content: 'value',\n                isStatic: false,\n              },\n              value: {\n                content: 'model',\n                isStatic: false,\n              },\n            },\n            {\n              key: {\n                children: [\n                  '\"onUpdate:\" + ',\n                  {\n                    content: 'value',\n                    isStatic: false,\n                  },\n                ],\n              },\n              value: {\n                children: [\n                  '$event => ((',\n                  {\n                    content: 'model',\n                    isStatic: false,\n                  },\n                  ') = $event)',\n                ],\n              },\n            },\n          ],\n        },\n      ],\n    })\n\n    expect(generate(root).code).toMatchSnapshot()\n  })\n\n  test('with dynamic argument (with prefixIdentifiers)', () => {\n    const root = parseWithVModel('<input v-model:[value]=\"model\" />', {\n      prefixIdentifiers: true,\n    })\n    const node = root.children[0] as ElementNode\n    const props = (node.codegenNode as VNodeCall)\n      .props as unknown as CallExpression\n\n    expect(props).toMatchObject({\n      type: NodeTypes.JS_CALL_EXPRESSION,\n      callee: NORMALIZE_PROPS,\n      arguments: [\n        {\n          type: NodeTypes.JS_OBJECT_EXPRESSION,\n          properties: [\n            {\n              key: {\n                content: '_ctx.value',\n                isStatic: false,\n              },\n              value: {\n                content: '_ctx.model',\n                isStatic: false,\n              },\n            },\n            {\n              key: {\n                children: [\n                  '\"onUpdate:\" + ',\n                  {\n                    content: '_ctx.value',\n                    isStatic: false,\n                  },\n                ],\n              },\n              value: {\n                children: [\n                  '$event => ((',\n                  {\n                    content: '_ctx.model',\n                    isStatic: false,\n                  },\n                  ') = $event)',\n                ],\n              },\n            },\n          ],\n        },\n      ],\n    })\n\n    expect(generate(root, { mode: 'module' }).code).toMatchSnapshot()\n  })\n\n  test('should cache update handler w/ cacheHandlers: true', () => {\n    const root = parseWithVModel('<input v-model=\"foo\" />', {\n      prefixIdentifiers: true,\n      cacheHandlers: true,\n    })\n    expect(root.cached.length).toBe(1)\n    const codegen = (root.children[0] as PlainElementNode)\n      .codegenNode as VNodeCall\n    // should not list cached prop in dynamicProps\n    expect(codegen.dynamicProps).toBe(`[\"modelValue\"]`)\n    expect((codegen.props as ObjectExpression).properties[1].value.type).toBe(\n      NodeTypes.JS_CACHE_EXPRESSION,\n    )\n  })\n\n  test('should not cache update handler if it refers v-for scope variables', () => {\n    const root = parseWithVModel(\n      '<input v-for=\"i in list\" v-model=\"foo[i]\" />',\n      {\n        prefixIdentifiers: true,\n        cacheHandlers: true,\n      },\n    )\n    expect(root.cached.length).toBe(0)\n    const codegen = (\n      (root.children[0] as ForNode).children[0] as PlainElementNode\n    ).codegenNode as VNodeCall\n    expect(codegen.dynamicProps).toBe(`[\"modelValue\", \"onUpdate:modelValue\"]`)\n    expect(\n      (codegen.props as ObjectExpression).properties[1].value.type,\n    ).not.toBe(NodeTypes.JS_CACHE_EXPRESSION)\n  })\n\n  test('should not cache update handler if it inside v-once', () => {\n    const root = parseWithVModel('<div v-once><input v-model=\"foo\" /></div>', {\n      prefixIdentifiers: true,\n      cacheHandlers: true,\n    })\n    expect(root.cached).not.toBe(2)\n    expect(root.cached.length).toBe(1)\n  })\n\n  test('should mark update handler dynamic if it refers slot scope variables', () => {\n    const root = parseWithVModel(\n      '<Comp v-slot=\"{ foo }\"><input v-model=\"foo.bar\"/></Comp>',\n      {\n        prefixIdentifiers: true,\n      },\n    )\n    const codegen = (\n      (root.children[0] as ComponentNode).children[0] as PlainElementNode\n    ).codegenNode as VNodeCall\n    expect(codegen.dynamicProps).toBe(`[\"modelValue\", \"onUpdate:modelValue\"]`)\n  })\n\n  test('should generate modelModifiers for component v-model', () => {\n    const root = parseWithVModel('<Comp v-model.trim.bar-baz=\"foo\" />', {\n      prefixIdentifiers: true,\n    })\n    const vnodeCall = (root.children[0] as ComponentNode)\n      .codegenNode as VNodeCall\n    // props\n    expect(vnodeCall.props).toMatchObject({\n      properties: [\n        { key: { content: `modelValue` } },\n        { key: { content: `onUpdate:modelValue` } },\n        {\n          key: { content: 'modelModifiers' },\n          value: {\n            content: `{ trim: true, \"bar-baz\": true }`,\n            isStatic: false,\n          },\n        },\n      ],\n    })\n    // should NOT include modelModifiers in dynamicPropNames because it's never\n    // gonna change\n    expect(vnodeCall.dynamicProps).toBe(`[\"modelValue\", \"onUpdate:modelValue\"]`)\n  })\n\n  test('should generate modelModifiers for component v-model with arguments', () => {\n    const root = parseWithVModel(\n      '<Comp v-model:foo.trim=\"foo\" v-model:bar.number=\"bar\" />',\n      {\n        prefixIdentifiers: true,\n      },\n    )\n    const vnodeCall = (root.children[0] as ComponentNode)\n      .codegenNode as VNodeCall\n    // props\n    expect(vnodeCall.props).toMatchObject({\n      properties: [\n        { key: { content: `foo` } },\n        { key: { content: `onUpdate:foo` } },\n        {\n          key: { content: 'fooModifiers' },\n          value: { content: `{ trim: true }`, isStatic: false },\n        },\n        { key: { content: `bar` } },\n        { key: { content: `onUpdate:bar` } },\n        {\n          key: { content: 'barModifiers' },\n          value: { content: `{ number: true }`, isStatic: false },\n        },\n      ],\n    })\n    // should NOT include modelModifiers in dynamicPropNames because it's never\n    // gonna change\n    expect(vnodeCall.dynamicProps).toBe(\n      `[\"foo\", \"onUpdate:foo\", \"bar\", \"onUpdate:bar\"]`,\n    )\n  })\n\n  describe('errors', () => {\n    test('missing expression', () => {\n      const onError = vi.fn()\n      parseWithVModel('<span v-model />', { onError })\n\n      expect(onError).toHaveBeenCalledTimes(1)\n      expect(onError).toHaveBeenCalledWith(\n        expect.objectContaining({\n          code: ErrorCodes.X_V_MODEL_NO_EXPRESSION,\n        }),\n      )\n    })\n\n    test('empty expression', () => {\n      const onError = vi.fn()\n      parseWithVModel('<span v-model=\"\" />', { onError })\n\n      expect(onError).toHaveBeenCalledTimes(1)\n      expect(onError).toHaveBeenCalledWith(\n        expect.objectContaining({\n          code: ErrorCodes.X_V_MODEL_MALFORMED_EXPRESSION,\n        }),\n      )\n    })\n\n    test('mal-formed expression', () => {\n      const onError = vi.fn()\n      parseWithVModel('<span v-model=\"a + b\" />', { onError })\n\n      expect(onError).toHaveBeenCalledTimes(1)\n      expect(onError).toHaveBeenCalledWith(\n        expect.objectContaining({\n          code: ErrorCodes.X_V_MODEL_MALFORMED_EXPRESSION,\n        }),\n      )\n    })\n\n    test('allow unicode', () => {\n      const onError = vi.fn()\n      parseWithVModel('<span v-model=\"变.量\" />', { onError })\n\n      expect(onError).toHaveBeenCalledTimes(0)\n    })\n\n    test('used on scope variable', () => {\n      const onError = vi.fn()\n      parseWithVModel('<span v-for=\"i in list\" v-model=\"i\" />', {\n        onError,\n        prefixIdentifiers: true,\n      })\n\n      expect(onError).toHaveBeenCalledTimes(1)\n      expect(onError).toHaveBeenCalledWith(\n        expect.objectContaining({\n          code: ErrorCodes.X_V_MODEL_ON_SCOPE_VARIABLE,\n        }),\n      )\n    })\n\n    test('used on props', () => {\n      const onError = vi.fn()\n      parseWithVModel('<div v-model=\"p\" />', {\n        onError,\n        bindingMetadata: {\n          p: BindingTypes.PROPS,\n        },\n      })\n\n      expect(onError).toHaveBeenCalledTimes(1)\n      expect(onError).toHaveBeenCalledWith(\n        expect.objectContaining({\n          code: ErrorCodes.X_V_MODEL_ON_PROPS,\n        }),\n      )\n    })\n\n    test('used on const binding', () => {\n      const onError = vi.fn()\n      parseWithVModel('<div v-model=\"c\" />', {\n        onError,\n        bindingMetadata: {\n          c: BindingTypes.LITERAL_CONST,\n        },\n      })\n\n      expect(onError).toHaveBeenCalledTimes(1)\n      expect(onError).toHaveBeenCalledWith(\n        expect.objectContaining({\n          code: ErrorCodes.X_V_MODEL_ON_CONST,\n        }),\n      )\n    })\n  })\n})\n"
  },
  {
    "path": "packages/compiler-core/__tests__/transforms/vOn.spec.ts",
    "content": "import {\n  type CompilerOptions,\n  type ElementNode,\n  ErrorCodes,\n  NodeTypes,\n  type ObjectExpression,\n  TO_HANDLER_KEY,\n  type VNodeCall,\n  helperNameMap,\n  baseParse as parse,\n  transform,\n} from '../../src'\nimport { transformFor } from '../../src/transforms/vFor'\nimport { transformOn } from '../../src/transforms/vOn'\nimport { transformElement } from '../../src/transforms/transformElement'\nimport { transformExpression } from '../../src/transforms/transformExpression'\n\nfunction parseWithVOn(template: string, options: CompilerOptions = {}) {\n  const ast = parse(template, options)\n  transform(ast, {\n    nodeTransforms: [transformExpression, transformElement, transformFor],\n    directiveTransforms: {\n      on: transformOn,\n    },\n    ...options,\n  })\n  return {\n    root: ast,\n    node: ast.children[0] as ElementNode,\n  }\n}\n\ndescribe('compiler: transform v-on', () => {\n  test('basic', () => {\n    const { node } = parseWithVOn(`<div v-on:click=\"onClick\"/>`)\n    expect((node.codegenNode as VNodeCall).props).toMatchObject({\n      properties: [\n        {\n          key: {\n            content: `onClick`,\n            isStatic: true,\n            loc: {\n              start: {\n                line: 1,\n                column: 11,\n              },\n              end: {\n                line: 1,\n                column: 16,\n              },\n            },\n          },\n          value: {\n            content: `onClick`,\n            isStatic: false,\n            loc: {\n              start: {\n                line: 1,\n                column: 18,\n              },\n              end: {\n                line: 1,\n                column: 25,\n              },\n            },\n          },\n        },\n      ],\n    })\n  })\n\n  test('dynamic arg', () => {\n    const { node } = parseWithVOn(`<div v-on:[event]=\"handler\"/>`)\n    expect((node.codegenNode as VNodeCall).props).toMatchObject({\n      properties: [\n        {\n          key: {\n            type: NodeTypes.COMPOUND_EXPRESSION,\n            children: [\n              `_${helperNameMap[TO_HANDLER_KEY]}(`,\n              { content: `event` },\n              `)`,\n            ],\n          },\n          value: {\n            type: NodeTypes.SIMPLE_EXPRESSION,\n            content: `handler`,\n            isStatic: false,\n          },\n        },\n      ],\n    })\n  })\n\n  test('dynamic arg with prefixing', () => {\n    const { node } = parseWithVOn(`<div v-on:[event]=\"handler\"/>`, {\n      prefixIdentifiers: true,\n    })\n    expect((node.codegenNode as VNodeCall).props).toMatchObject({\n      properties: [\n        {\n          key: {\n            type: NodeTypes.COMPOUND_EXPRESSION,\n            children: [\n              `_${helperNameMap[TO_HANDLER_KEY]}(`,\n              { content: `_ctx.event` },\n              `)`,\n            ],\n          },\n          value: {\n            type: NodeTypes.SIMPLE_EXPRESSION,\n            content: `_ctx.handler`,\n            isStatic: false,\n          },\n        },\n      ],\n    })\n  })\n\n  test('dynamic arg with complex exp prefixing', () => {\n    const { node } = parseWithVOn(`<div v-on:[event(foo)]=\"handler\"/>`, {\n      prefixIdentifiers: true,\n    })\n    expect((node.codegenNode as VNodeCall).props).toMatchObject({\n      properties: [\n        {\n          key: {\n            type: NodeTypes.COMPOUND_EXPRESSION,\n            children: [\n              `_${helperNameMap[TO_HANDLER_KEY]}(`,\n              { content: `_ctx.event` },\n              `(`,\n              { content: `_ctx.foo` },\n              `)`,\n              `)`,\n            ],\n          },\n          value: {\n            type: NodeTypes.SIMPLE_EXPRESSION,\n            content: `_ctx.handler`,\n            isStatic: false,\n          },\n        },\n      ],\n    })\n  })\n\n  test('should wrap as function if expression is inline statement', () => {\n    const { node } = parseWithVOn(`<div @click=\"i++\"/>`)\n    expect((node.codegenNode as VNodeCall).props).toMatchObject({\n      properties: [\n        {\n          key: { content: `onClick` },\n          value: {\n            type: NodeTypes.COMPOUND_EXPRESSION,\n            children: [`$event => (`, { content: `i++` }, `)`],\n          },\n        },\n      ],\n    })\n  })\n\n  test('should handle multiple inline statement', () => {\n    const { node } = parseWithVOn(`<div @click=\"foo();bar()\"/>`)\n    expect((node.codegenNode as VNodeCall).props).toMatchObject({\n      properties: [\n        {\n          key: { content: `onClick` },\n          value: {\n            type: NodeTypes.COMPOUND_EXPRESSION,\n            // should wrap with `{` for multiple statements\n            // in this case the return value is discarded and the behavior is\n            // consistent with 2.x\n            children: [`$event => {`, { content: `foo();bar()` }, `}`],\n          },\n        },\n      ],\n    })\n  })\n\n  test('should handle multi-line statement', () => {\n    const { node } = parseWithVOn(`<div @click=\"\\nfoo();\\nbar()\\n\"/>`)\n    expect((node.codegenNode as VNodeCall).props).toMatchObject({\n      properties: [\n        {\n          key: { content: `onClick` },\n          value: {\n            type: NodeTypes.COMPOUND_EXPRESSION,\n            // should wrap with `{` for multiple statements\n            // in this case the return value is discarded and the behavior is\n            // consistent with 2.x\n            children: [`$event => {`, { content: `\\nfoo();\\nbar()\\n` }, `}`],\n          },\n        },\n      ],\n    })\n  })\n\n  test('inline statement w/ prefixIdentifiers: true', () => {\n    const { node } = parseWithVOn(`<div @click=\"foo($event)\"/>`, {\n      prefixIdentifiers: true,\n    })\n    expect((node.codegenNode as VNodeCall).props).toMatchObject({\n      properties: [\n        {\n          key: { content: `onClick` },\n          value: {\n            type: NodeTypes.COMPOUND_EXPRESSION,\n            children: [\n              `$event => (`,\n              {\n                type: NodeTypes.COMPOUND_EXPRESSION,\n                children: [\n                  { content: `_ctx.foo` },\n                  `(`,\n                  // should NOT prefix $event\n                  { content: `$event` },\n                  `)`,\n                ],\n              },\n              `)`,\n            ],\n          },\n        },\n      ],\n    })\n  })\n\n  test('multiple inline statements w/ prefixIdentifiers: true', () => {\n    const { node } = parseWithVOn(`<div @click=\"foo($event);bar()\"/>`, {\n      prefixIdentifiers: true,\n    })\n    expect((node.codegenNode as VNodeCall).props).toMatchObject({\n      properties: [\n        {\n          key: { content: `onClick` },\n          value: {\n            type: NodeTypes.COMPOUND_EXPRESSION,\n            children: [\n              `$event => {`,\n              {\n                children: [\n                  { content: `_ctx.foo` },\n                  `(`,\n                  // should NOT prefix $event\n                  { content: `$event` },\n                  `);`,\n                  { content: `_ctx.bar` },\n                  `()`,\n                ],\n              },\n              `}`,\n            ],\n          },\n        },\n      ],\n    })\n  })\n\n  test('should NOT wrap as function if expression is already function expression', () => {\n    const { node } = parseWithVOn(`<div @click=\"$event => foo($event)\"/>`)\n    expect((node.codegenNode as VNodeCall).props).toMatchObject({\n      properties: [\n        {\n          key: { content: `onClick` },\n          value: {\n            type: NodeTypes.SIMPLE_EXPRESSION,\n            content: `$event => foo($event)`,\n          },\n        },\n      ],\n    })\n  })\n\n  test('should NOT wrap as function if expression is already function expression (with TypeScript)', () => {\n    const { node } = parseWithVOn(`<div @click=\"(e: any): any => foo(e)\"/>`)\n    expect((node.codegenNode as VNodeCall).props).toMatchObject({\n      properties: [\n        {\n          key: { content: `onClick` },\n          value: {\n            type: NodeTypes.SIMPLE_EXPRESSION,\n            content: `(e: any): any => foo(e)`,\n          },\n        },\n      ],\n    })\n\n    const { node: node2 } = parseWithVOn(\n      `<div @click=\"(e: (number | string)[]) => foo(e)\"/>`,\n    )\n    expect((node2.codegenNode as VNodeCall).props).toMatchObject({\n      properties: [\n        {\n          key: { content: `onClick` },\n          value: {\n            type: NodeTypes.SIMPLE_EXPRESSION,\n            content: `(e: (number | string)[]) => foo(e)`,\n          },\n        },\n      ],\n    })\n  })\n\n  test('should NOT wrap as function if expression is already function expression (async)', () => {\n    const { node } = parseWithVOn(\n      `<div @click=\"async $event => await foo($event)\"/>`,\n    )\n    expect((node.codegenNode as VNodeCall).props).toMatchObject({\n      properties: [\n        {\n          key: { content: `onClick` },\n          value: {\n            type: NodeTypes.SIMPLE_EXPRESSION,\n            content: `async $event => await foo($event)`,\n          },\n        },\n      ],\n    })\n  })\n\n  test('should NOT wrap as function if expression is already function expression (with newlines)', () => {\n    const { node } = parseWithVOn(\n      `<div @click=\"\n      $event => {\n        foo($event)\n      }\n    \"/>`,\n    )\n    expect((node.codegenNode as VNodeCall).props).toMatchObject({\n      properties: [\n        {\n          key: { content: `onClick` },\n          value: {\n            type: NodeTypes.SIMPLE_EXPRESSION,\n            content: `\n      $event => {\n        foo($event)\n      }\n    `,\n          },\n        },\n      ],\n    })\n  })\n\n  test('should NOT wrap as function if expression is already function expression (with newlines + function keyword)', () => {\n    const { node } = parseWithVOn(\n      `<div @click=\"\n      function($event) {\n        foo($event)\n      }\n    \"/>`,\n    )\n    expect((node.codegenNode as VNodeCall).props).toMatchObject({\n      properties: [\n        {\n          key: { content: `onClick` },\n          value: {\n            type: NodeTypes.SIMPLE_EXPRESSION,\n            content: `\n      function($event) {\n        foo($event)\n      }\n    `,\n          },\n        },\n      ],\n    })\n  })\n\n  test('should NOT wrap as function if expression is complex member expression', () => {\n    const { node } = parseWithVOn(`<div @click=\"a['b' + c]\"/>`)\n    expect((node.codegenNode as VNodeCall).props).toMatchObject({\n      properties: [\n        {\n          key: { content: `onClick` },\n          value: {\n            type: NodeTypes.SIMPLE_EXPRESSION,\n            content: `a['b' + c]`,\n          },\n        },\n      ],\n    })\n  })\n\n  test('complex member expression w/ prefixIdentifiers: true', () => {\n    const { node } = parseWithVOn(`<div @click=\"a['b' + c]\"/>`, {\n      prefixIdentifiers: true,\n    })\n    expect((node.codegenNode as VNodeCall).props).toMatchObject({\n      properties: [\n        {\n          key: { content: `onClick` },\n          value: {\n            type: NodeTypes.COMPOUND_EXPRESSION,\n            children: [\n              { content: `_ctx.a` },\n              `['b' + `,\n              { content: `_ctx.c` },\n              `]`,\n            ],\n          },\n        },\n      ],\n    })\n  })\n\n  test('function expression w/ prefixIdentifiers: true', () => {\n    const { node } = parseWithVOn(`<div @click=\"e => foo(e)\"/>`, {\n      prefixIdentifiers: true,\n    })\n    expect((node.codegenNode as VNodeCall).props).toMatchObject({\n      properties: [\n        {\n          key: { content: `onClick` },\n          value: {\n            type: NodeTypes.COMPOUND_EXPRESSION,\n            children: [\n              { content: `e` },\n              ` => `,\n              { content: `_ctx.foo` },\n              `(`,\n              { content: `e` },\n              `)`,\n            ],\n          },\n        },\n      ],\n    })\n  })\n\n  test('should error if no expression AND no modifier', () => {\n    const onError = vi.fn()\n    parseWithVOn(`<div v-on:click />`, { onError })\n    expect(onError.mock.calls[0][0]).toMatchObject({\n      code: ErrorCodes.X_V_ON_NO_EXPRESSION,\n      loc: {\n        start: {\n          line: 1,\n          column: 6,\n        },\n        end: {\n          line: 1,\n          column: 16,\n        },\n      },\n    })\n  })\n\n  test('should NOT error if no expression but has modifier', () => {\n    const onError = vi.fn()\n    parseWithVOn(`<div v-on:click.prevent />`, { onError })\n    expect(onError).not.toHaveBeenCalled()\n  })\n\n  test('case conversion for kebab-case events', () => {\n    const { node } = parseWithVOn(`<div v-on:foo-bar=\"onMount\"/>`)\n    expect((node.codegenNode as VNodeCall).props).toMatchObject({\n      properties: [\n        {\n          key: {\n            content: `onFooBar`,\n          },\n          value: {\n            content: `onMount`,\n          },\n        },\n      ],\n    })\n  })\n\n  test('error for vnode hooks', () => {\n    const onError = vi.fn()\n    parseWithVOn(`<div v-on:vnode-mounted=\"onMount\"/>`, { onError })\n    expect(onError.mock.calls[0][0]).toMatchObject({\n      code: ErrorCodes.X_VNODE_HOOKS,\n      loc: {\n        start: {\n          line: 1,\n          column: 11,\n        },\n        end: {\n          line: 1,\n          column: 24,\n        },\n      },\n    })\n  })\n\n  test('vue: prefixed events', () => {\n    const { node } = parseWithVOn(\n      `<div v-on:vue:mounted=\"onMount\" @vue:before-update=\"onBeforeUpdate\" />`,\n    )\n    expect((node.codegenNode as VNodeCall).props).toMatchObject({\n      properties: [\n        {\n          key: {\n            content: `onVnodeMounted`,\n          },\n          value: {\n            content: `onMount`,\n          },\n        },\n        {\n          key: {\n            content: `onVnodeBeforeUpdate`,\n          },\n          value: {\n            content: `onBeforeUpdate`,\n          },\n        },\n      ],\n    })\n  })\n\n  describe('cacheHandler', () => {\n    test('empty handler', () => {\n      const { root, node } = parseWithVOn(`<div v-on:click.prevent />`, {\n        prefixIdentifiers: true,\n        cacheHandlers: true,\n      })\n      expect(root.cached.length).toBe(1)\n      const vnodeCall = node.codegenNode as VNodeCall\n      // should not treat cached handler as dynamicProp, so no flags\n      expect(vnodeCall.patchFlag).toBeUndefined()\n      expect(\n        (vnodeCall.props as ObjectExpression).properties[0].value,\n      ).toMatchObject({\n        type: NodeTypes.JS_CACHE_EXPRESSION,\n        index: 0,\n        value: {\n          type: NodeTypes.SIMPLE_EXPRESSION,\n          content: `() => {}`,\n        },\n      })\n    })\n\n    test('member expression handler', () => {\n      const { root, node } = parseWithVOn(`<div v-on:click=\"foo\" />`, {\n        prefixIdentifiers: true,\n        cacheHandlers: true,\n      })\n      expect(root.cached.length).toBe(1)\n      const vnodeCall = node.codegenNode as VNodeCall\n      // should not treat cached handler as dynamicProp, so no flags\n      expect(vnodeCall.patchFlag).toBeUndefined()\n      expect(\n        (vnodeCall.props as ObjectExpression).properties[0].value,\n      ).toMatchObject({\n        type: NodeTypes.JS_CACHE_EXPRESSION,\n        index: 0,\n        value: {\n          type: NodeTypes.COMPOUND_EXPRESSION,\n          children: [\n            `(...args) => (`,\n            { content: `_ctx.foo && _ctx.foo(...args)` },\n            `)`,\n          ],\n        },\n      })\n    })\n\n    test('compound member expression handler', () => {\n      const { root, node } = parseWithVOn(`<div v-on:click=\"foo.bar\" />`, {\n        prefixIdentifiers: true,\n        cacheHandlers: true,\n      })\n      expect(root.cached.length).toBe(1)\n      const vnodeCall = node.codegenNode as VNodeCall\n      // should not treat cached handler as dynamicProp, so no flags\n      expect(vnodeCall.patchFlag).toBeUndefined()\n      expect(\n        (vnodeCall.props as ObjectExpression).properties[0].value,\n      ).toMatchObject({\n        type: NodeTypes.JS_CACHE_EXPRESSION,\n        index: 0,\n        value: {\n          type: NodeTypes.COMPOUND_EXPRESSION,\n          children: [\n            `(...args) => (`,\n            {\n              children: [\n                { content: `_ctx.foo` },\n                `.`,\n                { content: `bar` },\n                ` && `,\n                { content: `_ctx.foo` },\n                `.`,\n                { content: `bar` },\n                `(...args)`,\n              ],\n            },\n            `)`,\n          ],\n        },\n      })\n    })\n\n    test('bail on component member expression handler', () => {\n      const { root } = parseWithVOn(`<comp v-on:click=\"foo\" />`, {\n        prefixIdentifiers: true,\n        cacheHandlers: true,\n        isNativeTag: tag => tag === 'div',\n      })\n      expect(root.cached.length).toBe(0)\n    })\n\n    test('should not be cached inside v-once', () => {\n      const { root } = parseWithVOn(\n        `<div v-once><div v-on:click=\"foo\"/></div>`,\n        {\n          prefixIdentifiers: true,\n          cacheHandlers: true,\n        },\n      )\n      expect(root.cached.length).not.toBe(2)\n      expect(root.cached.length).toBe(1)\n    })\n\n    test('unicode identifier should not be cached (v-for)', () => {\n      const { root } = parseWithVOn(\n        `<div v-for=\"项 in items\" :key=\"value\"><div v-on:click=\"foo(项)\"/></div>`,\n        {\n          prefixIdentifiers: true,\n          cacheHandlers: true,\n        },\n      )\n      expect(root.cached.length).toBe(0)\n    })\n\n    test('inline function expression handler', () => {\n      const { root, node } = parseWithVOn(`<div v-on:click=\"() => foo()\" />`, {\n        prefixIdentifiers: true,\n        cacheHandlers: true,\n      })\n      expect(root.cached.length).toBe(1)\n      const vnodeCall = node.codegenNode as VNodeCall\n      // should not treat cached handler as dynamicProp, so no flags\n      expect(vnodeCall.patchFlag).toBeUndefined()\n      expect(\n        (vnodeCall.props as ObjectExpression).properties[0].value,\n      ).toMatchObject({\n        type: NodeTypes.JS_CACHE_EXPRESSION,\n        index: 0,\n        value: {\n          type: NodeTypes.COMPOUND_EXPRESSION,\n          children: [`() => `, { content: `_ctx.foo` }, `()`],\n        },\n      })\n    })\n\n    test('inline async arrow function expression handler', () => {\n      const { root, node } = parseWithVOn(\n        `<div v-on:click=\"async () => await foo()\" />`,\n        {\n          prefixIdentifiers: true,\n          cacheHandlers: true,\n        },\n      )\n      expect(root.cached.length).toBe(1)\n      const vnodeCall = node.codegenNode as VNodeCall\n      // should not treat cached handler as dynamicProp, so no flags\n      expect(vnodeCall.patchFlag).toBeUndefined()\n      expect(\n        (vnodeCall.props as ObjectExpression).properties[0].value,\n      ).toMatchObject({\n        type: NodeTypes.JS_CACHE_EXPRESSION,\n        index: 0,\n        value: {\n          type: NodeTypes.COMPOUND_EXPRESSION,\n          children: [`async () => await `, { content: `_ctx.foo` }, `()`],\n        },\n      })\n    })\n\n    test('inline async arrow function with no bracket expression handler', () => {\n      const { root, node } = parseWithVOn(\n        `<div v-on:click=\"async e => await foo(e)\" />`,\n        {\n          prefixIdentifiers: true,\n          cacheHandlers: true,\n        },\n      )\n\n      expect(root.cached.length).toBe(1)\n      const vnodeCall = node.codegenNode as VNodeCall\n      // should not treat cached handler as dynamicProp, so no flags\n      expect(vnodeCall.patchFlag).toBeUndefined()\n      expect(\n        (vnodeCall.props as ObjectExpression).properties[0].value,\n      ).toMatchObject({\n        type: NodeTypes.JS_CACHE_EXPRESSION,\n        index: 0,\n        value: {\n          type: NodeTypes.COMPOUND_EXPRESSION,\n          children: [\n            `async `,\n            { content: `e` },\n            ` => await `,\n            { content: `_ctx.foo` },\n            `(`,\n            { content: `e` },\n            `)`,\n          ],\n        },\n      })\n    })\n\n    test('inline async function expression handler', () => {\n      const { root, node } = parseWithVOn(\n        `<div v-on:click=\"async function () { await foo() } \" />`,\n        {\n          prefixIdentifiers: true,\n          cacheHandlers: true,\n        },\n      )\n      expect(root.cached.length).toBe(1)\n      const vnodeCall = node.codegenNode as VNodeCall\n      // should not treat cached handler as dynamicProp, so no flags\n      expect(vnodeCall.patchFlag).toBeUndefined()\n      expect(\n        (vnodeCall.props as ObjectExpression).properties[0].value,\n      ).toMatchObject({\n        type: NodeTypes.JS_CACHE_EXPRESSION,\n        index: 0,\n        value: {\n          type: NodeTypes.COMPOUND_EXPRESSION,\n          children: [\n            `async function () { await `,\n            { content: `_ctx.foo` },\n            `() } `,\n          ],\n        },\n      })\n    })\n\n    test('inline statement handler', () => {\n      const { root, node } = parseWithVOn(`<div v-on:click=\"foo++\" />`, {\n        prefixIdentifiers: true,\n        cacheHandlers: true,\n      })\n      expect(root.cached.length).toBe(1)\n      expect(root.cached.length).toBe(1)\n      const vnodeCall = node.codegenNode as VNodeCall\n      // should not treat cached handler as dynamicProp, so no flags\n      expect(vnodeCall.patchFlag).toBeUndefined()\n      expect(\n        (vnodeCall.props as ObjectExpression).properties[0].value,\n      ).toMatchObject({\n        type: NodeTypes.JS_CACHE_EXPRESSION,\n        index: 0,\n        value: {\n          type: NodeTypes.COMPOUND_EXPRESSION,\n          children: [\n            `$event => (`,\n            { children: [{ content: `_ctx.foo` }, `++`] },\n            `)`,\n          ],\n        },\n      })\n    })\n  })\n})\n"
  },
  {
    "path": "packages/compiler-core/__tests__/transforms/vOnce.spec.ts",
    "content": "import {\n  type CompilerOptions,\n  NodeTypes,\n  generate,\n  getBaseTransformPreset,\n  baseParse as parse,\n  transform,\n} from '../../src'\nimport { RENDER_SLOT, SET_BLOCK_TRACKING } from '../../src/runtimeHelpers'\n\nfunction transformWithOnce(template: string, options: CompilerOptions = {}) {\n  const ast = parse(template)\n  const [nodeTransforms, directiveTransforms] = getBaseTransformPreset()\n  transform(ast, {\n    nodeTransforms,\n    directiveTransforms,\n    ...options,\n  })\n  return ast\n}\n\ndescribe('compiler: v-once transform', () => {\n  test('as root node', () => {\n    const root = transformWithOnce(`<div :id=\"foo\" v-once />`)\n    expect(root.cached.length).toBe(1)\n    expect(root.helpers).toContain(SET_BLOCK_TRACKING)\n    expect(root.codegenNode).toMatchObject({\n      type: NodeTypes.JS_CACHE_EXPRESSION,\n      index: 0,\n      value: {\n        type: NodeTypes.VNODE_CALL,\n        tag: `\"div\"`,\n      },\n    })\n    expect(generate(root).code).toMatchSnapshot()\n  })\n\n  test('on nested plain element', () => {\n    const root = transformWithOnce(`<div><div :id=\"foo\" v-once /></div>`)\n    expect(root.cached.length).toBe(1)\n    expect(root.helpers).toContain(SET_BLOCK_TRACKING)\n    expect((root.children[0] as any).children[0].codegenNode).toMatchObject({\n      type: NodeTypes.JS_CACHE_EXPRESSION,\n      index: 0,\n      value: {\n        type: NodeTypes.VNODE_CALL,\n        tag: `\"div\"`,\n      },\n    })\n    expect(generate(root).code).toMatchSnapshot()\n  })\n\n  test('on component', () => {\n    const root = transformWithOnce(`<div><Comp :id=\"foo\" v-once /></div>`)\n    expect(root.cached.length).toBe(1)\n    expect(root.helpers).toContain(SET_BLOCK_TRACKING)\n    expect((root.children[0] as any).children[0].codegenNode).toMatchObject({\n      type: NodeTypes.JS_CACHE_EXPRESSION,\n      index: 0,\n      value: {\n        type: NodeTypes.VNODE_CALL,\n        tag: `_component_Comp`,\n      },\n    })\n    expect(generate(root).code).toMatchSnapshot()\n  })\n\n  test('on slot outlet', () => {\n    const root = transformWithOnce(`<div><slot v-once /></div>`)\n    expect(root.cached.length).toBe(1)\n    expect(root.helpers).toContain(SET_BLOCK_TRACKING)\n    expect((root.children[0] as any).children[0].codegenNode).toMatchObject({\n      type: NodeTypes.JS_CACHE_EXPRESSION,\n      index: 0,\n      value: {\n        type: NodeTypes.JS_CALL_EXPRESSION,\n        callee: RENDER_SLOT,\n      },\n    })\n    expect(generate(root).code).toMatchSnapshot()\n  })\n\n  // v-once inside v-once should not be cached\n  test('inside v-once', () => {\n    const root = transformWithOnce(`<div v-once><div v-once/></div>`)\n    expect(root.cached).not.toBe(2)\n    expect(root.cached.length).toBe(1)\n  })\n\n  // cached nodes should be ignored by hoistStatic transform\n  test('with hoistStatic: true', () => {\n    const root = transformWithOnce(`<div><div v-once /></div>`, {\n      hoistStatic: true,\n    })\n    expect(root.cached.length).toBe(1)\n    expect(root.helpers).toContain(SET_BLOCK_TRACKING)\n    expect(root.hoists.length).toBe(0)\n    expect((root.children[0] as any).children[0].codegenNode).toMatchObject({\n      type: NodeTypes.JS_CACHE_EXPRESSION,\n      index: 0,\n      value: {\n        type: NodeTypes.VNODE_CALL,\n        tag: `\"div\"`,\n      },\n    })\n    expect(generate(root).code).toMatchSnapshot()\n  })\n\n  test('with v-if/else', () => {\n    const root = transformWithOnce(`<div v-if=\"BOOLEAN\" v-once /><p v-else/>`)\n    expect(root.cached.length).toBe(1)\n    expect(root.helpers).toContain(SET_BLOCK_TRACKING)\n    expect(root.children[0]).toMatchObject({\n      type: NodeTypes.IF,\n      // should cache the entire v-if/else-if/else expression, not just a single branch\n      codegenNode: {\n        type: NodeTypes.JS_CACHE_EXPRESSION,\n        value: {\n          type: NodeTypes.JS_CONDITIONAL_EXPRESSION,\n          consequent: {\n            type: NodeTypes.VNODE_CALL,\n            tag: `\"div\"`,\n          },\n          alternate: {\n            type: NodeTypes.VNODE_CALL,\n            tag: `\"p\"`,\n          },\n        },\n      },\n    })\n  })\n\n  test('with v-for', () => {\n    const root = transformWithOnce(`<div v-for=\"i in list\" v-once />`)\n    expect(root.cached.length).toBe(1)\n    expect(root.helpers).toContain(SET_BLOCK_TRACKING)\n    expect(root.children[0]).toMatchObject({\n      type: NodeTypes.FOR,\n      // should cache the entire v-for expression, not just a single branch\n      codegenNode: {\n        type: NodeTypes.JS_CACHE_EXPRESSION,\n      },\n    })\n  })\n})\n"
  },
  {
    "path": "packages/compiler-core/__tests__/transforms/vSlot.spec.ts",
    "content": "import {\n  type CompilerOptions,\n  type ComponentNode,\n  type ElementNode,\n  ErrorCodes,\n  type ForNode,\n  NodeTypes,\n  type ObjectExpression,\n  type RenderSlotCall,\n  type SimpleExpressionNode,\n  type SlotsExpression,\n  type VNodeCall,\n  generate,\n  baseParse as parse,\n  transform,\n} from '../../src'\nimport { transformElement } from '../../src/transforms/transformElement'\nimport { transformOn } from '../../src/transforms/vOn'\nimport { transformBind } from '../../src/transforms/vBind'\nimport { transformExpression } from '../../src/transforms/transformExpression'\nimport { transformSlotOutlet } from '../../src/transforms/transformSlotOutlet'\nimport {\n  trackSlotScopes,\n  trackVForSlotScopes,\n} from '../../src/transforms/vSlot'\nimport { CREATE_SLOTS, RENDER_LIST } from '../../src/runtimeHelpers'\nimport { createObjectMatcher } from '../testUtils'\nimport { PatchFlags } from '@vue/shared'\nimport { transformFor } from '../../src/transforms/vFor'\nimport { transformIf } from '../../src/transforms/vIf'\nimport { transformText } from '../../src/transforms/transformText'\n\nfunction parseWithSlots(\n  template: string,\n  options: CompilerOptions & { transformText?: boolean } = {},\n) {\n  const ast = parse(template, {\n    whitespace: options.whitespace,\n  })\n  transform(ast, {\n    nodeTransforms: [\n      transformIf,\n      transformFor,\n      ...(options.prefixIdentifiers\n        ? [trackVForSlotScopes, transformExpression]\n        : []),\n      transformSlotOutlet,\n      transformElement,\n      trackSlotScopes,\n      ...(options.transformText ? [transformText] : []),\n    ],\n    directiveTransforms: {\n      on: transformOn,\n      bind: transformBind,\n    },\n    ...options,\n  })\n  return {\n    root: ast,\n    slots:\n      ast.children[0].type === NodeTypes.ELEMENT\n        ? ((ast.children[0].codegenNode as VNodeCall)\n            .children as SlotsExpression)\n        : null,\n  }\n}\n\nfunction createSlotMatcher(obj: Record<string, any>, isDynamic = false) {\n  return {\n    type: NodeTypes.JS_OBJECT_EXPRESSION,\n    properties: Object.keys(obj)\n      .map(key => {\n        return {\n          type: NodeTypes.JS_PROPERTY,\n          key: {\n            type: NodeTypes.SIMPLE_EXPRESSION,\n            isStatic: !/^\\[/.test(key),\n            content: key.replace(/^\\[|\\]$/g, ''),\n          },\n          value: obj[key],\n        } as any\n      })\n      .concat({\n        key: { content: `_` },\n        value: {\n          content: isDynamic ? `2 /* DYNAMIC */` : `1 /* STABLE */`,\n          isStatic: false,\n        },\n      }),\n  }\n}\n\ndescribe('compiler: transform component slots', () => {\n  test('implicit default slot', () => {\n    const { root, slots } = parseWithSlots(`<Comp><div/></Comp>`, {\n      prefixIdentifiers: true,\n    })\n    expect(slots).toMatchObject(\n      createSlotMatcher({\n        default: {\n          type: NodeTypes.JS_FUNCTION_EXPRESSION,\n          params: undefined,\n          returns: [\n            {\n              type: NodeTypes.ELEMENT,\n              tag: `div`,\n            },\n          ],\n        },\n      }),\n    )\n    expect(generate(root, { prefixIdentifiers: true }).code).toMatchSnapshot()\n  })\n\n  test('on-component default slot', () => {\n    const { root, slots } = parseWithSlots(\n      `<Comp v-slot=\"{ foo }\">{{ foo }}{{ bar }}</Comp>`,\n      { prefixIdentifiers: true },\n    )\n    expect(slots).toMatchObject(\n      createSlotMatcher({\n        default: {\n          type: NodeTypes.JS_FUNCTION_EXPRESSION,\n          params: {\n            type: NodeTypes.COMPOUND_EXPRESSION,\n            children: [`{ `, { content: `foo` }, ` }`],\n          },\n          returns: [\n            {\n              type: NodeTypes.INTERPOLATION,\n              content: {\n                content: `foo`,\n              },\n            },\n            {\n              type: NodeTypes.INTERPOLATION,\n              content: {\n                content: `_ctx.bar`,\n              },\n            },\n          ],\n        },\n      }),\n    )\n    expect(generate(root, { prefixIdentifiers: true }).code).toMatchSnapshot()\n  })\n\n  test('on component named slot', () => {\n    const { root, slots } = parseWithSlots(\n      `<Comp v-slot:named=\"{ foo }\">{{ foo }}{{ bar }}</Comp>`,\n      { prefixIdentifiers: true },\n    )\n    expect(slots).toMatchObject(\n      createSlotMatcher({\n        named: {\n          type: NodeTypes.JS_FUNCTION_EXPRESSION,\n          params: {\n            type: NodeTypes.COMPOUND_EXPRESSION,\n            children: [`{ `, { content: `foo` }, ` }`],\n          },\n          returns: [\n            {\n              type: NodeTypes.INTERPOLATION,\n              content: {\n                content: `foo`,\n              },\n            },\n            {\n              type: NodeTypes.INTERPOLATION,\n              content: {\n                content: `_ctx.bar`,\n              },\n            },\n          ],\n        },\n      }),\n    )\n    expect(generate(root, { prefixIdentifiers: true }).code).toMatchSnapshot()\n  })\n\n  test('template named slots', () => {\n    const { root, slots } = parseWithSlots(\n      `<Comp>\n        <template v-slot:one=\"{ foo }\">\n          {{ foo }}{{ bar }}\n        </template>\n        <template #two=\"{ bar }\">\n          {{ foo }}{{ bar }}\n        </template>\n      </Comp>`,\n      { prefixIdentifiers: true },\n    )\n    expect(slots).toMatchObject(\n      createSlotMatcher({\n        one: {\n          type: NodeTypes.JS_FUNCTION_EXPRESSION,\n          params: {\n            type: NodeTypes.COMPOUND_EXPRESSION,\n            children: [`{ `, { content: `foo` }, ` }`],\n          },\n          returns: [\n            {\n              type: NodeTypes.INTERPOLATION,\n              content: {\n                content: `foo`,\n              },\n            },\n            {\n              type: NodeTypes.INTERPOLATION,\n              content: {\n                content: `_ctx.bar`,\n              },\n            },\n          ],\n        },\n        two: {\n          type: NodeTypes.JS_FUNCTION_EXPRESSION,\n          params: {\n            type: NodeTypes.COMPOUND_EXPRESSION,\n            children: [`{ `, { content: `bar` }, ` }`],\n          },\n          returns: [\n            {\n              type: NodeTypes.INTERPOLATION,\n              content: {\n                content: `_ctx.foo`,\n              },\n            },\n            {\n              type: NodeTypes.INTERPOLATION,\n              content: {\n                content: `bar`,\n              },\n            },\n          ],\n        },\n      }),\n    )\n    expect(generate(root, { prefixIdentifiers: true }).code).toMatchSnapshot()\n  })\n\n  test('on component dynamically named slot', () => {\n    const { root, slots } = parseWithSlots(\n      `<Comp v-slot:[named]=\"{ foo }\">{{ foo }}{{ bar }}</Comp>`,\n      { prefixIdentifiers: true },\n    )\n    expect(slots).toMatchObject(\n      createSlotMatcher(\n        {\n          '[_ctx.named]': {\n            type: NodeTypes.JS_FUNCTION_EXPRESSION,\n            params: {\n              type: NodeTypes.COMPOUND_EXPRESSION,\n              children: [`{ `, { content: `foo` }, ` }`],\n            },\n            returns: [\n              {\n                type: NodeTypes.INTERPOLATION,\n                content: {\n                  content: `foo`,\n                },\n              },\n              {\n                type: NodeTypes.INTERPOLATION,\n                content: {\n                  content: `_ctx.bar`,\n                },\n              },\n            ],\n          },\n        },\n        true,\n      ),\n    )\n    expect(generate(root, { prefixIdentifiers: true }).code).toMatchSnapshot()\n  })\n\n  test('named slots w/ implicit default slot', () => {\n    const { root, slots } = parseWithSlots(\n      `<Comp>\n        <template #one>foo</template>bar<span/>\n      </Comp>`,\n    )\n    expect(slots).toMatchObject(\n      createSlotMatcher({\n        one: {\n          type: NodeTypes.JS_FUNCTION_EXPRESSION,\n          params: undefined,\n          returns: [\n            {\n              type: NodeTypes.TEXT,\n              content: `foo`,\n            },\n          ],\n        },\n        default: {\n          type: NodeTypes.JS_FUNCTION_EXPRESSION,\n          params: undefined,\n          returns: [\n            {\n              type: NodeTypes.TEXT,\n              content: `bar`,\n            },\n            {\n              type: NodeTypes.ELEMENT,\n              tag: `span`,\n            },\n          ],\n        },\n      }),\n    )\n    expect(generate(root).code).toMatchSnapshot()\n  })\n\n  test('named slots w/ implicit default slot containing non-breaking space', () => {\n    const { root, slots } = parseWithSlots(\n      `<Comp>\n        \\u00a0\n        <template #one>foo</template>\n      </Comp>`,\n    )\n    expect(slots).toMatchObject(\n      createSlotMatcher({\n        one: {\n          type: NodeTypes.JS_FUNCTION_EXPRESSION,\n          params: undefined,\n          returns: [\n            {\n              type: NodeTypes.TEXT,\n              content: `foo`,\n            },\n          ],\n        },\n        default: {\n          type: NodeTypes.JS_FUNCTION_EXPRESSION,\n          params: undefined,\n          returns: [\n            {\n              type: NodeTypes.TEXT,\n              content: ` \\u00a0 `,\n            },\n          ],\n        },\n      }),\n    )\n    expect(generate(root).code).toMatchSnapshot()\n  })\n\n  test('dynamically named slots', () => {\n    const { root, slots } = parseWithSlots(\n      `<Comp>\n        <template v-slot:[one]=\"{ foo }\">\n          {{ foo }}{{ bar }}\n        </template>\n        <template #[two]=\"{ bar }\">\n          {{ foo }}{{ bar }}\n        </template>\n      </Comp>`,\n      { prefixIdentifiers: true },\n    )\n    expect(slots).toMatchObject(\n      createSlotMatcher(\n        {\n          '[_ctx.one]': {\n            type: NodeTypes.JS_FUNCTION_EXPRESSION,\n            params: {\n              type: NodeTypes.COMPOUND_EXPRESSION,\n              children: [`{ `, { content: `foo` }, ` }`],\n            },\n            returns: [\n              {\n                type: NodeTypes.INTERPOLATION,\n                content: {\n                  content: `foo`,\n                },\n              },\n              {\n                type: NodeTypes.INTERPOLATION,\n                content: {\n                  content: `_ctx.bar`,\n                },\n              },\n            ],\n          },\n          '[_ctx.two]': {\n            type: NodeTypes.JS_FUNCTION_EXPRESSION,\n            params: {\n              type: NodeTypes.COMPOUND_EXPRESSION,\n              children: [`{ `, { content: `bar` }, ` }`],\n            },\n            returns: [\n              {\n                type: NodeTypes.INTERPOLATION,\n                content: {\n                  content: `_ctx.foo`,\n                },\n              },\n              {\n                type: NodeTypes.INTERPOLATION,\n                content: {\n                  content: `bar`,\n                },\n              },\n            ],\n          },\n        },\n        true,\n      ),\n    )\n    expect(generate(root, { prefixIdentifiers: true }).code).toMatchSnapshot()\n  })\n\n  test('nested slots scoping', () => {\n    const { root, slots } = parseWithSlots(\n      `<Comp>\n        <template #default=\"{ foo }\">\n          <Inner v-slot=\"{ bar }\">\n            {{ foo }}{{ bar }}{{ baz }}\n          </Inner>\n          {{ foo }}{{ bar }}{{ baz }}\n        </template>\n      </Comp>`,\n      { prefixIdentifiers: true },\n    )\n    expect(slots).toMatchObject(\n      createSlotMatcher({\n        default: {\n          type: NodeTypes.JS_FUNCTION_EXPRESSION,\n          params: {\n            type: NodeTypes.COMPOUND_EXPRESSION,\n            children: [`{ `, { content: `foo` }, ` }`],\n          },\n          returns: [\n            {\n              type: NodeTypes.ELEMENT,\n              codegenNode: {\n                type: NodeTypes.VNODE_CALL,\n                tag: `_component_Inner`,\n                props: undefined,\n                children: createSlotMatcher(\n                  {\n                    default: {\n                      type: NodeTypes.JS_FUNCTION_EXPRESSION,\n                      params: {\n                        type: NodeTypes.COMPOUND_EXPRESSION,\n                        children: [`{ `, { content: `bar` }, ` }`],\n                      },\n                      returns: [\n                        {\n                          type: NodeTypes.INTERPOLATION,\n                          content: {\n                            content: `foo`,\n                          },\n                        },\n                        {\n                          type: NodeTypes.INTERPOLATION,\n                          content: {\n                            content: `bar`,\n                          },\n                        },\n                        {\n                          type: NodeTypes.INTERPOLATION,\n                          content: {\n                            content: `_ctx.baz`,\n                          },\n                        },\n                      ],\n                    },\n                  },\n                  true,\n                ),\n                // nested slot should be forced dynamic, since scope variables\n                // are not tracked as dependencies of the slot.\n                patchFlag: PatchFlags.DYNAMIC_SLOTS,\n              },\n            },\n            // test scope\n            {\n              type: NodeTypes.TEXT,\n              content: ` `,\n            },\n            {\n              type: NodeTypes.INTERPOLATION,\n              content: {\n                content: `foo`,\n              },\n            },\n            {\n              type: NodeTypes.INTERPOLATION,\n              content: {\n                content: `_ctx.bar`,\n              },\n            },\n            {\n              type: NodeTypes.INTERPOLATION,\n              content: {\n                content: `_ctx.baz`,\n              },\n            },\n          ],\n        },\n      }),\n    )\n    expect(generate(root, { prefixIdentifiers: true }).code).toMatchSnapshot()\n  })\n\n  test('should force dynamic when inside v-for', () => {\n    const { root } = parseWithSlots(\n      `<div v-for=\"i in list\">\n        <Comp v-slot=\"bar\">foo</Comp>\n      </div>`,\n    )\n    const div = ((root.children[0] as ForNode).children[0] as ElementNode)\n      .codegenNode as any\n    const comp = div.children[0]\n    expect(comp.codegenNode.patchFlag).toBe(PatchFlags.DYNAMIC_SLOTS)\n  })\n\n  test('should only force dynamic slots when actually using scope vars w/ prefixIdentifiers: true', () => {\n    function assertDynamicSlots(\n      template: string,\n      expectedPatchFlag?: PatchFlags,\n    ) {\n      const { root } = parseWithSlots(template, { prefixIdentifiers: true })\n      let flag: any\n      if (root.children[0].type === NodeTypes.FOR) {\n        const div = (root.children[0].children[0] as ElementNode)\n          .codegenNode as any\n        const comp = div.children[0]\n        flag = comp.codegenNode.patchFlag\n      } else {\n        const innerComp = (root.children[0] as ComponentNode)\n          .children[0] as ComponentNode\n        flag = (innerComp.codegenNode as VNodeCall).patchFlag\n      }\n      if (expectedPatchFlag) {\n        expect(flag).toBe(expectedPatchFlag)\n      } else {\n        expect(flag).toBeUndefined()\n      }\n    }\n\n    assertDynamicSlots(\n      `<div v-for=\"i in list\">\n        <Comp v-slot=\"bar\">foo</Comp>\n      </div>`,\n    )\n\n    assertDynamicSlots(\n      `<div v-for=\"i in list\">\n        <Comp v-slot=\"bar\">{{ i }}</Comp>\n      </div>`,\n      PatchFlags.DYNAMIC_SLOTS,\n    )\n\n    // reference the component's own slot variable should not force dynamic slots\n    assertDynamicSlots(\n      `<Comp v-slot=\"foo\">\n        <Comp v-slot=\"bar\">{{ bar }}</Comp>\n      </Comp>`,\n    )\n\n    assertDynamicSlots(\n      `<Comp v-slot=\"foo\">\n        <Comp v-slot=\"bar\">{{ foo }}</Comp>\n      </Comp>`,\n      PatchFlags.DYNAMIC_SLOTS,\n    )\n\n    // #2564\n    assertDynamicSlots(\n      `<div v-for=\"i in list\">\n        <Comp v-slot=\"bar\"><button @click=\"fn(i)\" /></Comp>\n      </div>`,\n      PatchFlags.DYNAMIC_SLOTS,\n    )\n\n    assertDynamicSlots(\n      `<div v-for=\"i in list\">\n        <Comp v-slot=\"bar\"><button @click=\"fn()\" /></Comp>\n      </div>`,\n    )\n\n    // #9380\n    assertDynamicSlots(\n      `<div v-for=\"i in list\">\n        <Comp :i=\"i\">foo</Comp>\n      </div>`,\n      PatchFlags.PROPS,\n    )\n\n    assertDynamicSlots(\n      `<div v-for=\"i in list\">\n        <Comp v-slot=\"{ value = i }\"><button @click=\"fn()\" /></Comp>\n      </div>`,\n      PatchFlags.DYNAMIC_SLOTS,\n    )\n\n    assertDynamicSlots(\n      `<div v-for=\"i in list\">\n        <Comp v-slot:[i]><button @click=\"fn()\" /></Comp>\n      </div>`,\n      PatchFlags.DYNAMIC_SLOTS,\n    )\n  })\n\n  test('named slot with v-if', () => {\n    const { root, slots } = parseWithSlots(\n      `<Comp>\n        <template #one v-if=\"ok\">hello</template>\n      </Comp>`,\n    )\n    expect(slots).toMatchObject({\n      type: NodeTypes.JS_CALL_EXPRESSION,\n      callee: CREATE_SLOTS,\n      arguments: [\n        createObjectMatcher({\n          _: `[2 /* DYNAMIC */]`,\n        }),\n        {\n          type: NodeTypes.JS_ARRAY_EXPRESSION,\n          elements: [\n            {\n              type: NodeTypes.JS_CONDITIONAL_EXPRESSION,\n              test: { content: `ok` },\n              consequent: createObjectMatcher({\n                name: `one`,\n                fn: {\n                  type: NodeTypes.JS_FUNCTION_EXPRESSION,\n                  returns: [{ type: NodeTypes.TEXT, content: `hello` }],\n                },\n                key: `0`,\n              }),\n              alternate: {\n                content: `undefined`,\n                isStatic: false,\n              },\n            },\n          ],\n        },\n      ],\n    })\n    expect((root as any).children[0].codegenNode.patchFlag).toBe(\n      PatchFlags.DYNAMIC_SLOTS,\n    )\n    expect(generate(root).code).toMatchSnapshot()\n  })\n\n  test('named slot with v-if + prefixIdentifiers: true', () => {\n    const { root, slots } = parseWithSlots(\n      `<Comp>\n        <template #one=\"props\" v-if=\"ok\">{{ props }}</template>\n      </Comp>`,\n      { prefixIdentifiers: true },\n    )\n    expect(slots).toMatchObject({\n      type: NodeTypes.JS_CALL_EXPRESSION,\n      callee: CREATE_SLOTS,\n      arguments: [\n        createObjectMatcher({\n          _: `[2 /* DYNAMIC */]`,\n        }),\n        {\n          type: NodeTypes.JS_ARRAY_EXPRESSION,\n          elements: [\n            {\n              type: NodeTypes.JS_CONDITIONAL_EXPRESSION,\n              test: { content: `_ctx.ok` },\n              consequent: createObjectMatcher({\n                name: `one`,\n                fn: {\n                  type: NodeTypes.JS_FUNCTION_EXPRESSION,\n                  params: { content: `props` },\n                  returns: [\n                    {\n                      type: NodeTypes.INTERPOLATION,\n                      content: { content: `props` },\n                    },\n                  ],\n                },\n                key: `0`,\n              }),\n              alternate: {\n                content: `undefined`,\n                isStatic: false,\n              },\n            },\n          ],\n        },\n      ],\n    })\n    expect((root as any).children[0].codegenNode.patchFlag).toBe(\n      PatchFlags.DYNAMIC_SLOTS,\n    )\n    expect(generate(root, { prefixIdentifiers: true }).code).toMatchSnapshot()\n  })\n\n  test('named slot with v-if + v-else-if + v-else', () => {\n    const { root, slots } = parseWithSlots(\n      `<Comp>\n        <template #one v-if=\"ok\">foo</template>\n        <template #two=\"props\" v-else-if=\"orNot\">bar</template>\n        <template #one v-else>baz</template>\n      </Comp>`,\n    )\n    expect(slots).toMatchObject({\n      type: NodeTypes.JS_CALL_EXPRESSION,\n      callee: CREATE_SLOTS,\n      arguments: [\n        createObjectMatcher({\n          _: `[2 /* DYNAMIC */]`,\n        }),\n        {\n          type: NodeTypes.JS_ARRAY_EXPRESSION,\n          elements: [\n            {\n              type: NodeTypes.JS_CONDITIONAL_EXPRESSION,\n              test: { content: `ok` },\n              consequent: createObjectMatcher({\n                name: `one`,\n                fn: {\n                  type: NodeTypes.JS_FUNCTION_EXPRESSION,\n                  params: undefined,\n                  returns: [{ type: NodeTypes.TEXT, content: `foo` }],\n                },\n                key: `0`,\n              }),\n              alternate: {\n                type: NodeTypes.JS_CONDITIONAL_EXPRESSION,\n                test: { content: `orNot` },\n                consequent: createObjectMatcher({\n                  name: `two`,\n                  fn: {\n                    type: NodeTypes.JS_FUNCTION_EXPRESSION,\n                    params: { content: `props` },\n                    returns: [{ type: NodeTypes.TEXT, content: `bar` }],\n                  },\n                  key: `1`,\n                }),\n                alternate: createObjectMatcher({\n                  name: `one`,\n                  fn: {\n                    type: NodeTypes.JS_FUNCTION_EXPRESSION,\n                    params: undefined,\n                    returns: [{ type: NodeTypes.TEXT, content: `baz` }],\n                  },\n                  key: `2`,\n                }),\n              },\n            },\n          ],\n        },\n      ],\n    })\n    expect((root as any).children[0].codegenNode.patchFlag).toBe(\n      PatchFlags.DYNAMIC_SLOTS,\n    )\n    expect((root as any).children[0].children.length).toBe(3)\n    expect(generate(root).code).toMatchSnapshot()\n  })\n\n  test('named slot with v-for w/ prefixIdentifiers: true', () => {\n    const { root, slots } = parseWithSlots(\n      `<Comp>\n        <template v-for=\"name in list\" #[name]>{{ name }}</template>\n      </Comp>`,\n      { prefixIdentifiers: true },\n    )\n    expect(slots).toMatchObject({\n      type: NodeTypes.JS_CALL_EXPRESSION,\n      callee: CREATE_SLOTS,\n      arguments: [\n        createObjectMatcher({\n          _: `[2 /* DYNAMIC */]`,\n        }),\n        {\n          type: NodeTypes.JS_ARRAY_EXPRESSION,\n          elements: [\n            {\n              type: NodeTypes.JS_CALL_EXPRESSION,\n              callee: RENDER_LIST,\n              arguments: [\n                { content: `_ctx.list` },\n                {\n                  type: NodeTypes.JS_FUNCTION_EXPRESSION,\n                  params: [{ content: `name` }],\n                  returns: createObjectMatcher({\n                    name: `[name]`,\n                    fn: {\n                      type: NodeTypes.JS_FUNCTION_EXPRESSION,\n                      returns: [\n                        {\n                          type: NodeTypes.INTERPOLATION,\n                          content: { content: `name`, isStatic: false },\n                        },\n                      ],\n                    },\n                  }),\n                },\n              ],\n            },\n          ],\n        },\n      ],\n    })\n    expect((root as any).children[0].codegenNode.patchFlag).toBe(\n      PatchFlags.DYNAMIC_SLOTS,\n    )\n    expect(generate(root, { prefixIdentifiers: true }).code).toMatchSnapshot()\n  })\n\n  describe('forwarded slots', () => {\n    const toMatch = {\n      type: NodeTypes.JS_OBJECT_EXPRESSION,\n      properties: [\n        {\n          key: { content: `default` },\n          value: { type: NodeTypes.JS_FUNCTION_EXPRESSION },\n        },\n        {\n          key: { content: `_` },\n          value: { content: `3 /* FORWARDED */` },\n        },\n      ],\n    }\n    test('<slot> tag only', () => {\n      const { slots } = parseWithSlots(`<Comp><slot/></Comp>`)\n      expect(slots).toMatchObject(toMatch)\n    })\n\n    test('<slot> tag w/ v-if', () => {\n      const { slots } = parseWithSlots(`<Comp><slot v-if=\"ok\"/></Comp>`)\n      expect(slots).toMatchObject(toMatch)\n    })\n\n    test('<slot> tag w/ v-for', () => {\n      const { slots } = parseWithSlots(`<Comp><slot v-for=\"a in b\"/></Comp>`)\n      expect(slots).toMatchObject(toMatch)\n    })\n\n    test('<slot> tag w/ template', () => {\n      const { slots } = parseWithSlots(\n        `<Comp><template #default><slot/></template></Comp>`,\n      )\n      expect(slots).toMatchObject(toMatch)\n    })\n\n    test('<slot w/ nested component>', () => {\n      const { slots } = parseWithSlots(`<Comp><Comp><slot/></Comp></Comp>`)\n      expect(slots).toMatchObject(toMatch)\n    })\n\n    // # fix: #6900\n    test('consistent behavior of @xxx:modelValue and @xxx:model-value', () => {\n      const { root: rootUpper } = parseWithSlots(\n        `<div><slot @foo:modelValue=\"handler\" /></div>`,\n      )\n      const slotNodeUpper = (rootUpper.codegenNode! as VNodeCall)\n        .children as ElementNode[]\n      const propertiesObjUpper = (\n        slotNodeUpper[0].codegenNode! as RenderSlotCall\n      ).arguments[2]\n      expect(propertiesObjUpper).toMatchObject({\n        properties: [\n          {\n            key: {\n              type: NodeTypes.SIMPLE_EXPRESSION,\n              content: 'onFoo:modelValue',\n            },\n            value: {\n              type: NodeTypes.SIMPLE_EXPRESSION,\n              content: `handler`,\n              isStatic: false,\n            },\n          },\n        ],\n      })\n\n      const { root } = parseWithSlots(\n        `<div><slot @foo:model-Value=\"handler\" /></div>`,\n      )\n      const slotNode = (root.codegenNode! as VNodeCall)\n        .children as ElementNode[]\n      const propertiesObj = (slotNode[0].codegenNode! as RenderSlotCall)\n        .arguments[2]\n      expect(propertiesObj).toMatchObject({\n        properties: [\n          {\n            key: {\n              type: NodeTypes.SIMPLE_EXPRESSION,\n              content: 'onFoo:modelValue',\n            },\n            value: {\n              type: NodeTypes.SIMPLE_EXPRESSION,\n              content: `handler`,\n              isStatic: false,\n            },\n          },\n        ],\n      })\n    })\n  })\n\n  describe('errors', () => {\n    test('error on extraneous children w/ named default slot', () => {\n      const onError = vi.fn()\n      const source = `<Comp><template #default>foo</template>bar</Comp>`\n      parseWithSlots(source, { onError })\n      const index = source.indexOf('bar')\n      expect(onError.mock.calls[0][0]).toMatchObject({\n        code: ErrorCodes.X_V_SLOT_EXTRANEOUS_DEFAULT_SLOT_CHILDREN,\n        loc: {\n          start: {\n            offset: index,\n            line: 1,\n            column: index + 1,\n          },\n          end: {\n            offset: index + 3,\n            line: 1,\n            column: index + 4,\n          },\n        },\n      })\n    })\n\n    test('error on duplicated slot names', () => {\n      const onError = vi.fn()\n      const source = `<Comp><template #foo></template><template #foo></template></Comp>`\n      parseWithSlots(source, { onError })\n      const index = source.lastIndexOf('#foo')\n      expect(onError.mock.calls[0][0]).toMatchObject({\n        code: ErrorCodes.X_V_SLOT_DUPLICATE_SLOT_NAMES,\n        loc: {\n          start: {\n            offset: index,\n            line: 1,\n            column: index + 1,\n          },\n          end: {\n            offset: index + 4,\n            line: 1,\n            column: index + 5,\n          },\n        },\n      })\n    })\n\n    test('error on invalid mixed slot usage', () => {\n      const onError = vi.fn()\n      const source = `<Comp v-slot=\"foo\"><template #foo></template></Comp>`\n      parseWithSlots(source, { onError })\n      const index = source.lastIndexOf('#foo')\n      expect(onError.mock.calls[0][0]).toMatchObject({\n        code: ErrorCodes.X_V_SLOT_MIXED_SLOT_USAGE,\n        loc: {\n          start: {\n            offset: index,\n            line: 1,\n            column: index + 1,\n          },\n          end: {\n            offset: index + 4,\n            line: 1,\n            column: index + 5,\n          },\n        },\n      })\n    })\n\n    test('error on v-slot usage on plain elements', () => {\n      const onError = vi.fn()\n      const source = `<div v-slot/>`\n      parseWithSlots(source, { onError })\n      const index = source.indexOf('v-slot')\n      expect(onError.mock.calls[0][0]).toMatchObject({\n        code: ErrorCodes.X_V_SLOT_MISPLACED,\n        loc: {\n          start: {\n            offset: index,\n            line: 1,\n            column: index + 1,\n          },\n          end: {\n            offset: index + 6,\n            line: 1,\n            column: index + 7,\n          },\n        },\n      })\n    })\n  })\n\n  describe(`with whitespace: 'preserve'`, () => {\n    test('named default slot + implicit whitespace content', () => {\n      const source = `\n      <Comp>\n        <template #header> Header </template>\n        <template #default> Default </template>\n      </Comp>\n      `\n      const { root } = parseWithSlots(source, {\n        whitespace: 'preserve',\n      })\n\n      expect(\n        `Extraneous children found when component already has explicitly named default slot.`,\n      ).not.toHaveBeenWarned()\n      expect(generate(root, { prefixIdentifiers: true }).code).toMatchSnapshot()\n    })\n\n    test('implicit default slot', () => {\n      const source = `\n      <Comp>\n        <template #header> Header </template>\n        <p/>\n      </Comp>\n      `\n      const { root } = parseWithSlots(source, {\n        whitespace: 'preserve',\n      })\n\n      expect(\n        `Extraneous children found when component already has explicitly named default slot.`,\n      ).not.toHaveBeenWarned()\n      expect(generate(root, { prefixIdentifiers: true }).code).toMatchSnapshot()\n    })\n\n    test('should not generate whitespace only default slot', () => {\n      const source = `\n      <Comp>\n        <template #header> Header </template>\n        <template #footer> Footer </template>\n      </Comp>\n      `\n      const { root } = parseWithSlots(source, {\n        whitespace: 'preserve',\n      })\n\n      // slots is vnodeCall's children as an ObjectExpression\n      const slots = (root as any).children[0].codegenNode.children\n        .properties as ObjectExpression['properties']\n\n      // should be: header, footer, _ (no default)\n      expect(slots.length).toBe(3)\n      expect(\n        slots.some(p => (p.key as SimpleExpressionNode).content === 'default'),\n      ).toBe(false)\n\n      expect(generate(root, { prefixIdentifiers: true }).code).toMatchSnapshot()\n    })\n\n    test('implicit default slot with non-breaking space', () => {\n      const source = `\n      <Comp>\n        &nbsp;\n        <template #header> Header </template>\n      </Comp>\n      `\n      const { root } = parseWithSlots(source, {\n        whitespace: 'preserve',\n      })\n\n      const slots = (root as any).children[0].codegenNode.children\n        .properties as ObjectExpression['properties']\n\n      expect(\n        slots.some(p => (p.key as SimpleExpressionNode).content === 'default'),\n      ).toBe(true)\n\n      expect(generate(root, { prefixIdentifiers: true }).code).toMatchSnapshot()\n    })\n\n    test('named slot with v-if + v-else', () => {\n      const source = `\n        <Comp>\n          <template #one v-if=\"ok\">foo</template>\n          <template #two v-else>baz</template>\n        </Comp>\n      `\n      const { root } = parseWithSlots(source, {\n        whitespace: 'preserve',\n      })\n\n      expect(generate(root, { prefixIdentifiers: true }).code).toMatchSnapshot()\n    })\n\n    test('named slot with v-if + v-else and comments', () => {\n      const source = `\n        <Comp>\n          <template #one v-if=\"ok\">foo</template>\n          <!-- start -->\n\n          <!-- end -->\n          <template #two v-else>baz</template>\n        </Comp>\n      `\n      const { root } = parseWithSlots(source, {\n        transformText: true,\n        whitespace: 'preserve',\n      })\n\n      expect(generate(root, { prefixIdentifiers: true }).code).toMatchSnapshot()\n    })\n  })\n})\n"
  },
  {
    "path": "packages/compiler-core/__tests__/utils.spec.ts",
    "content": "import { babelParse, walkIdentifiers } from '@vue/compiler-sfc'\nimport {\n  type ExpressionNode,\n  type TransformContext,\n  isReferencedIdentifier,\n} from '../src'\nimport { type Position, createSimpleExpression } from '../src/ast'\nimport {\n  advancePositionWithClone,\n  isMemberExpressionBrowser,\n  isMemberExpressionNode,\n  toValidAssetId,\n} from '../src/utils'\n\nfunction p(line: number, column: number, offset: number): Position {\n  return { column, line, offset }\n}\n\ndescribe('advancePositionWithClone', () => {\n  test('same line', () => {\n    const pos = p(1, 1, 0)\n    const newPos = advancePositionWithClone(pos, 'foo\\nbar', 2)\n\n    expect(newPos.column).toBe(3)\n    expect(newPos.line).toBe(1)\n    expect(newPos.offset).toBe(2)\n  })\n\n  test('same line', () => {\n    const pos = p(1, 1, 0)\n    const newPos = advancePositionWithClone(pos, 'foo\\nbar', 4)\n\n    expect(newPos.column).toBe(1)\n    expect(newPos.line).toBe(2)\n    expect(newPos.offset).toBe(4)\n  })\n\n  test('multiple lines', () => {\n    const pos = p(1, 1, 0)\n    const newPos = advancePositionWithClone(pos, 'foo\\nbar\\nbaz', 10)\n\n    expect(newPos.column).toBe(3)\n    expect(newPos.line).toBe(3)\n    expect(newPos.offset).toBe(10)\n  })\n})\n\ndescribe('isMemberExpression', () => {\n  function commonAssertions(raw: (exp: ExpressionNode) => boolean) {\n    const fn = (str: string) => raw(createSimpleExpression(str))\n    // should work\n    expect(fn('obj.foo')).toBe(true)\n    expect(fn('obj[foo]')).toBe(true)\n    expect(fn('obj[arr[0]]')).toBe(true)\n    expect(fn('obj[arr[ret.bar]]')).toBe(true)\n    expect(fn('obj[arr[ret[bar]]]')).toBe(true)\n    expect(fn('obj[arr[ret[bar]]].baz')).toBe(true)\n    expect(fn('obj[1 + 1]')).toBe(true)\n    expect(fn(`obj[x[0]]`)).toBe(true)\n    expect(fn('obj[1][2]')).toBe(true)\n    expect(fn('obj[1][2].foo[3].bar.baz')).toBe(true)\n    expect(fn(`a[b[c.d]][0]`)).toBe(true)\n    expect(fn('obj?.foo')).toBe(true)\n    expect(fn('foo().test')).toBe(true)\n\n    // strings\n    expect(fn(`a['foo' + bar[baz][\"qux\"]]`)).toBe(true)\n\n    // multiline whitespaces\n    expect(fn('obj \\n .foo \\n [bar \\n + baz]')).toBe(true)\n    expect(fn(`\\n model\\n.\\nfoo \\n`)).toBe(true)\n\n    // should fail\n    expect(fn('a \\n b')).toBe(false)\n    expect(fn('obj[foo')).toBe(false)\n    expect(fn('objfoo]')).toBe(false)\n    expect(fn('obj[arr[0]')).toBe(false)\n    expect(fn('obj[arr0]]')).toBe(false)\n    expect(fn('a + b')).toBe(false)\n    expect(fn('foo()')).toBe(false)\n    expect(fn('a?b:c')).toBe(false)\n    expect(fn(`state['text'] = $event`)).toBe(false)\n  }\n\n  test('browser', () => {\n    commonAssertions(isMemberExpressionBrowser)\n    expect(isMemberExpressionBrowser(createSimpleExpression('123[a]'))).toBe(\n      false,\n    )\n  })\n\n  test('node', () => {\n    const ctx = { expressionPlugins: ['typescript'] } as any as TransformContext\n    const fn = (str: string) =>\n      isMemberExpressionNode(createSimpleExpression(str), ctx)\n    commonAssertions(exp => isMemberExpressionNode(exp, ctx))\n\n    // TS-specific checks\n    expect(fn('foo as string')).toBe(true)\n    expect(fn(`foo.bar as string`)).toBe(true)\n    expect(fn(`foo['bar'] as string`)).toBe(true)\n    expect(fn(`foo[bar as string]`)).toBe(true)\n    expect(fn(`(foo as string)`)).toBe(true)\n    expect(fn(`123[a]`)).toBe(true)\n    expect(fn(`foo() as string`)).toBe(false)\n    expect(fn(`a + b as string`)).toBe(false)\n    // #9865\n    expect(fn('\"\"')).toBe(false)\n    expect(fn('undefined')).toBe(false)\n    expect(fn('null')).toBe(false)\n  })\n})\n\ntest('toValidAssetId', () => {\n  expect(toValidAssetId('foo', 'component')).toBe('_component_foo')\n  expect(toValidAssetId('p', 'directive')).toBe('_directive_p')\n  expect(toValidAssetId('div', 'filter')).toBe('_filter_div')\n  expect(toValidAssetId('foo-bar', 'component')).toBe('_component_foo_bar')\n  expect(toValidAssetId('test-测试-1', 'component')).toBe(\n    '_component_test_2797935797_1',\n  )\n})\n\ndescribe('isReferencedIdentifier', () => {\n  test('identifiers in function parameters should not be inferred as references', () => {\n    expect.assertions(4)\n    const ast = babelParse(`(({ title }) => [])`)\n    walkIdentifiers(\n      ast.program.body[0],\n      (node, parent, parentStack, isReference) => {\n        expect(isReference).toBe(false)\n        expect(isReferencedIdentifier(node, parent, parentStack)).toBe(false)\n      },\n      true,\n    )\n  })\n})\n"
  },
  {
    "path": "packages/compiler-core/index.js",
    "content": "'use strict'\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./dist/compiler-core.cjs.prod.js')\n} else {\n  module.exports = require('./dist/compiler-core.cjs.js')\n}\n"
  },
  {
    "path": "packages/compiler-core/package.json",
    "content": "{\n  \"name\": \"@vue/compiler-core\",\n  \"version\": \"3.5.30\",\n  \"description\": \"@vue/compiler-core\",\n  \"main\": \"index.js\",\n  \"module\": \"dist/compiler-core.esm-bundler.js\",\n  \"types\": \"dist/compiler-core.d.ts\",\n  \"files\": [\n    \"index.js\",\n    \"dist\"\n  ],\n  \"exports\": {\n    \".\": {\n      \"types\": \"./dist/compiler-core.d.ts\",\n      \"node\": {\n        \"production\": \"./dist/compiler-core.cjs.prod.js\",\n        \"development\": \"./dist/compiler-core.cjs.js\",\n        \"default\": \"./index.js\"\n      },\n      \"module\": \"./dist/compiler-core.esm-bundler.js\",\n      \"import\": \"./dist/compiler-core.esm-bundler.js\",\n      \"require\": \"./index.js\"\n    },\n    \"./*\": \"./*\"\n  },\n  \"buildOptions\": {\n    \"name\": \"VueCompilerCore\",\n    \"compat\": true,\n    \"formats\": [\n      \"esm-bundler\",\n      \"cjs\"\n    ]\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/vuejs/core.git\",\n    \"directory\": \"packages/compiler-core\"\n  },\n  \"keywords\": [\n    \"vue\"\n  ],\n  \"author\": \"Evan You\",\n  \"license\": \"MIT\",\n  \"bugs\": {\n    \"url\": \"https://github.com/vuejs/core/issues\"\n  },\n  \"homepage\": \"https://github.com/vuejs/core/tree/main/packages/compiler-core#readme\",\n  \"dependencies\": {\n    \"@babel/parser\": \"catalog:\",\n    \"@vue/shared\": \"workspace:*\",\n    \"entities\": \"catalog:\",\n    \"estree-walker\": \"catalog:\",\n    \"source-map-js\": \"catalog:\"\n  },\n  \"devDependencies\": {\n    \"@babel/types\": \"catalog:\"\n  }\n}\n"
  },
  {
    "path": "packages/compiler-core/src/ast.ts",
    "content": "import { type PatchFlags, isString } from '@vue/shared'\nimport {\n  CREATE_BLOCK,\n  CREATE_ELEMENT_BLOCK,\n  CREATE_ELEMENT_VNODE,\n  type CREATE_SLOTS,\n  CREATE_VNODE,\n  type FRAGMENT,\n  OPEN_BLOCK,\n  type RENDER_LIST,\n  type RENDER_SLOT,\n  WITH_DIRECTIVES,\n  type WITH_MEMO,\n} from './runtimeHelpers'\nimport type { PropsExpression } from './transforms/transformElement'\nimport type { ImportItem, TransformContext } from './transform'\nimport type { Node as BabelNode } from '@babel/types'\n\n// Vue template is a platform-agnostic superset of HTML (syntax only).\n// More namespaces can be declared by platform specific compilers.\nexport type Namespace = number\n\nexport enum Namespaces {\n  HTML,\n  SVG,\n  MATH_ML,\n}\n\nexport enum NodeTypes {\n  ROOT,\n  ELEMENT,\n  TEXT,\n  COMMENT,\n  SIMPLE_EXPRESSION,\n  INTERPOLATION,\n  ATTRIBUTE,\n  DIRECTIVE,\n  // containers\n  COMPOUND_EXPRESSION,\n  IF,\n  IF_BRANCH,\n  FOR,\n  TEXT_CALL,\n  // codegen\n  VNODE_CALL,\n  JS_CALL_EXPRESSION,\n  JS_OBJECT_EXPRESSION,\n  JS_PROPERTY,\n  JS_ARRAY_EXPRESSION,\n  JS_FUNCTION_EXPRESSION,\n  JS_CONDITIONAL_EXPRESSION,\n  JS_CACHE_EXPRESSION,\n\n  // ssr codegen\n  JS_BLOCK_STATEMENT,\n  JS_TEMPLATE_LITERAL,\n  JS_IF_STATEMENT,\n  JS_ASSIGNMENT_EXPRESSION,\n  JS_SEQUENCE_EXPRESSION,\n  JS_RETURN_STATEMENT,\n}\n\nexport enum ElementTypes {\n  ELEMENT,\n  COMPONENT,\n  SLOT,\n  TEMPLATE,\n}\n\nexport interface Node {\n  type: NodeTypes\n  loc: SourceLocation\n}\n\n// The node's range. The `start` is inclusive and `end` is exclusive.\n// [start, end)\nexport interface SourceLocation {\n  start: Position\n  end: Position\n  source: string\n}\n\nexport interface Position {\n  offset: number // from start of file\n  line: number\n  column: number\n}\n\nexport type ParentNode = RootNode | ElementNode | IfBranchNode | ForNode\n\nexport type ExpressionNode = SimpleExpressionNode | CompoundExpressionNode\n\nexport type TemplateChildNode =\n  | ElementNode\n  | InterpolationNode\n  | CompoundExpressionNode\n  | TextNode\n  | CommentNode\n  | IfNode\n  | IfBranchNode\n  | ForNode\n  | TextCallNode\n\nexport interface RootNode extends Node {\n  type: NodeTypes.ROOT\n  source: string\n  children: TemplateChildNode[]\n  helpers: Set<symbol>\n  components: string[]\n  directives: string[]\n  hoists: (JSChildNode | null)[]\n  imports: ImportItem[]\n  cached: (CacheExpression | null)[]\n  temps: number\n  ssrHelpers?: symbol[]\n  codegenNode?: TemplateChildNode | JSChildNode | BlockStatement\n  transformed?: boolean\n\n  // v2 compat only\n  filters?: string[]\n}\n\nexport type ElementNode =\n  | PlainElementNode\n  | ComponentNode\n  | SlotOutletNode\n  | TemplateNode\n\nexport interface BaseElementNode extends Node {\n  type: NodeTypes.ELEMENT\n  ns: Namespace\n  tag: string\n  tagType: ElementTypes\n  props: Array<AttributeNode | DirectiveNode>\n  children: TemplateChildNode[]\n  isSelfClosing?: boolean\n  innerLoc?: SourceLocation // only for SFC root level elements\n}\n\nexport interface PlainElementNode extends BaseElementNode {\n  tagType: ElementTypes.ELEMENT\n  codegenNode:\n    | VNodeCall\n    | SimpleExpressionNode // when hoisted\n    | CacheExpression // when cached by v-once\n    | MemoExpression // when cached by v-memo\n    | undefined\n  ssrCodegenNode?: TemplateLiteral\n}\n\nexport interface ComponentNode extends BaseElementNode {\n  tagType: ElementTypes.COMPONENT\n  codegenNode:\n    | VNodeCall\n    | CacheExpression // when cached by v-once\n    | MemoExpression // when cached by v-memo\n    | undefined\n  ssrCodegenNode?: CallExpression\n}\n\nexport interface SlotOutletNode extends BaseElementNode {\n  tagType: ElementTypes.SLOT\n  codegenNode:\n    | RenderSlotCall\n    | CacheExpression // when cached by v-once\n    | undefined\n  ssrCodegenNode?: CallExpression\n}\n\nexport interface TemplateNode extends BaseElementNode {\n  tagType: ElementTypes.TEMPLATE\n  // TemplateNode is a container type that always gets compiled away\n  codegenNode: undefined\n}\n\nexport interface TextNode extends Node {\n  type: NodeTypes.TEXT\n  content: string\n}\n\nexport interface CommentNode extends Node {\n  type: NodeTypes.COMMENT\n  content: string\n}\n\nexport interface AttributeNode extends Node {\n  type: NodeTypes.ATTRIBUTE\n  name: string\n  nameLoc: SourceLocation\n  value: TextNode | undefined\n}\n\nexport interface DirectiveNode extends Node {\n  type: NodeTypes.DIRECTIVE\n  /**\n   * the normalized name without prefix or shorthands, e.g. \"bind\", \"on\"\n   */\n  name: string\n  /**\n   * the raw attribute name, preserving shorthand, and including arg & modifiers\n   * this is only used during parse.\n   */\n  rawName?: string\n  exp: ExpressionNode | undefined\n  arg: ExpressionNode | undefined\n  modifiers: SimpleExpressionNode[]\n  /**\n   * optional property to cache the expression parse result for v-for\n   */\n  forParseResult?: ForParseResult\n}\n\n/**\n * Static types have several levels.\n * Higher levels implies lower levels. e.g. a node that can be stringified\n * can always be hoisted and skipped for patch.\n */\nexport enum ConstantTypes {\n  NOT_CONSTANT = 0,\n  CAN_SKIP_PATCH,\n  CAN_CACHE,\n  CAN_STRINGIFY,\n}\n\nexport interface SimpleExpressionNode extends Node {\n  type: NodeTypes.SIMPLE_EXPRESSION\n  content: string\n  isStatic: boolean\n  constType: ConstantTypes\n  /**\n   * - `null` means the expression is a simple identifier that doesn't need\n   *    parsing\n   * - `false` means there was a parsing error\n   */\n  ast?: BabelNode | null | false\n  /**\n   * Indicates this is an identifier for a hoist vnode call and points to the\n   * hoisted node.\n   */\n  hoisted?: JSChildNode\n  /**\n   * an expression parsed as the params of a function will track\n   * the identifiers declared inside the function body.\n   */\n  identifiers?: string[]\n  isHandlerKey?: boolean\n}\n\nexport interface InterpolationNode extends Node {\n  type: NodeTypes.INTERPOLATION\n  content: ExpressionNode\n}\n\nexport interface CompoundExpressionNode extends Node {\n  type: NodeTypes.COMPOUND_EXPRESSION\n  /**\n   * - `null` means the expression is a simple identifier that doesn't need\n   *    parsing\n   * - `false` means there was a parsing error\n   */\n  ast?: BabelNode | null | false\n  children: (\n    | SimpleExpressionNode\n    | CompoundExpressionNode\n    | InterpolationNode\n    | TextNode\n    | string\n    | symbol\n  )[]\n\n  /**\n   * an expression parsed as the params of a function will track\n   * the identifiers declared inside the function body.\n   */\n  identifiers?: string[]\n  isHandlerKey?: boolean\n}\n\nexport interface IfNode extends Node {\n  type: NodeTypes.IF\n  branches: IfBranchNode[]\n  codegenNode?: IfConditionalExpression | CacheExpression // <div v-if v-once>\n}\n\nexport interface IfBranchNode extends Node {\n  type: NodeTypes.IF_BRANCH\n  condition: ExpressionNode | undefined // else\n  children: TemplateChildNode[]\n  userKey?: AttributeNode | DirectiveNode\n  isTemplateIf?: boolean\n}\n\nexport interface ForNode extends Node {\n  type: NodeTypes.FOR\n  source: ExpressionNode\n  valueAlias: ExpressionNode | undefined\n  keyAlias: ExpressionNode | undefined\n  objectIndexAlias: ExpressionNode | undefined\n  parseResult: ForParseResult\n  children: TemplateChildNode[]\n  codegenNode?: ForCodegenNode\n}\n\nexport interface ForParseResult {\n  source: ExpressionNode\n  value: ExpressionNode | undefined\n  key: ExpressionNode | undefined\n  index: ExpressionNode | undefined\n  finalized: boolean\n}\n\nexport interface TextCallNode extends Node {\n  type: NodeTypes.TEXT_CALL\n  content: TextNode | InterpolationNode | CompoundExpressionNode\n  codegenNode: CallExpression | SimpleExpressionNode // when hoisted\n}\n\nexport type TemplateTextChildNode =\n  | TextNode\n  | InterpolationNode\n  | CompoundExpressionNode\n\nexport interface VNodeCall extends Node {\n  type: NodeTypes.VNODE_CALL\n  tag: string | symbol | CallExpression\n  props: PropsExpression | undefined\n  children:\n    | TemplateChildNode[] // multiple children\n    | TemplateTextChildNode // single text child\n    | SlotsExpression // component slots\n    | ForRenderListExpression // v-for fragment call\n    | SimpleExpressionNode // hoisted\n    | CacheExpression // cached\n    | undefined\n  patchFlag: PatchFlags | undefined\n  dynamicProps: string | SimpleExpressionNode | undefined\n  directives: DirectiveArguments | undefined\n  isBlock: boolean\n  disableTracking: boolean\n  isComponent: boolean\n}\n\n// JS Node Types ---------------------------------------------------------------\n\n// We also include a number of JavaScript AST nodes for code generation.\n// The AST is an intentionally minimal subset just to meet the exact needs of\n// Vue render function generation.\n\nexport type JSChildNode =\n  | VNodeCall\n  | CallExpression\n  | ObjectExpression\n  | ArrayExpression\n  | ExpressionNode\n  | FunctionExpression\n  | ConditionalExpression\n  | CacheExpression\n  | AssignmentExpression\n  | SequenceExpression\n\nexport interface CallExpression extends Node {\n  type: NodeTypes.JS_CALL_EXPRESSION\n  callee: string | symbol\n  arguments: (\n    | string\n    | symbol\n    | JSChildNode\n    | SSRCodegenNode\n    | TemplateChildNode\n    | TemplateChildNode[]\n  )[]\n}\n\nexport interface ObjectExpression extends Node {\n  type: NodeTypes.JS_OBJECT_EXPRESSION\n  properties: Array<Property>\n}\n\nexport interface Property extends Node {\n  type: NodeTypes.JS_PROPERTY\n  key: ExpressionNode\n  value: JSChildNode\n}\n\nexport interface ArrayExpression extends Node {\n  type: NodeTypes.JS_ARRAY_EXPRESSION\n  elements: Array<string | Node>\n}\n\nexport interface FunctionExpression extends Node {\n  type: NodeTypes.JS_FUNCTION_EXPRESSION\n  params: ExpressionNode | string | (ExpressionNode | string)[] | undefined\n  returns?: TemplateChildNode | TemplateChildNode[] | JSChildNode\n  body?: BlockStatement | IfStatement\n  newline: boolean\n  /**\n   * This flag is for codegen to determine whether it needs to generate the\n   * withScopeId() wrapper\n   */\n  isSlot: boolean\n  /**\n   * __COMPAT__ only, indicates a slot function that should be excluded from\n   * the legacy $scopedSlots instance property.\n   */\n  isNonScopedSlot?: boolean\n}\n\nexport interface ConditionalExpression extends Node {\n  type: NodeTypes.JS_CONDITIONAL_EXPRESSION\n  test: JSChildNode\n  consequent: JSChildNode\n  alternate: JSChildNode\n  newline: boolean\n}\n\nexport interface CacheExpression extends Node {\n  type: NodeTypes.JS_CACHE_EXPRESSION\n  index: number\n  value: JSChildNode\n  needPauseTracking: boolean\n  inVOnce: boolean\n  needArraySpread: boolean\n}\n\nexport interface MemoExpression extends CallExpression {\n  callee: typeof WITH_MEMO\n  arguments: [ExpressionNode, MemoFactory, string, string]\n}\n\ninterface MemoFactory extends FunctionExpression {\n  returns: BlockCodegenNode\n}\n\n// SSR-specific Node Types -----------------------------------------------------\n\nexport type SSRCodegenNode =\n  | BlockStatement\n  | TemplateLiteral\n  | IfStatement\n  | AssignmentExpression\n  | ReturnStatement\n  | SequenceExpression\n\nexport interface BlockStatement extends Node {\n  type: NodeTypes.JS_BLOCK_STATEMENT\n  body: (JSChildNode | IfStatement)[]\n}\n\nexport interface TemplateLiteral extends Node {\n  type: NodeTypes.JS_TEMPLATE_LITERAL\n  elements: (string | JSChildNode)[]\n}\n\nexport interface IfStatement extends Node {\n  type: NodeTypes.JS_IF_STATEMENT\n  test: ExpressionNode\n  consequent: BlockStatement\n  alternate: IfStatement | BlockStatement | ReturnStatement | undefined\n}\n\nexport interface AssignmentExpression extends Node {\n  type: NodeTypes.JS_ASSIGNMENT_EXPRESSION\n  left: SimpleExpressionNode\n  right: JSChildNode\n}\n\nexport interface SequenceExpression extends Node {\n  type: NodeTypes.JS_SEQUENCE_EXPRESSION\n  expressions: JSChildNode[]\n}\n\nexport interface ReturnStatement extends Node {\n  type: NodeTypes.JS_RETURN_STATEMENT\n  returns: TemplateChildNode | TemplateChildNode[] | JSChildNode\n}\n\n// Codegen Node Types ----------------------------------------------------------\n\nexport interface DirectiveArguments extends ArrayExpression {\n  elements: DirectiveArgumentNode[]\n}\n\nexport interface DirectiveArgumentNode extends ArrayExpression {\n  elements: // dir, exp, arg, modifiers\n    | [string]\n    | [string, ExpressionNode]\n    | [string, ExpressionNode, ExpressionNode]\n    | [string, ExpressionNode, ExpressionNode, ObjectExpression]\n}\n\n// renderSlot(...)\nexport interface RenderSlotCall extends CallExpression {\n  callee: typeof RENDER_SLOT\n  arguments: // $slots, name, props, fallback\n    | [string, string | ExpressionNode]\n    | [string, string | ExpressionNode, PropsExpression]\n    | [\n        string,\n        string | ExpressionNode,\n        PropsExpression | '{}',\n        TemplateChildNode[],\n      ]\n}\n\nexport type SlotsExpression = SlotsObjectExpression | DynamicSlotsExpression\n\n// { foo: () => [...] }\nexport interface SlotsObjectExpression extends ObjectExpression {\n  properties: SlotsObjectProperty[]\n}\n\nexport interface SlotsObjectProperty extends Property {\n  value: SlotFunctionExpression\n}\n\nexport interface SlotFunctionExpression extends FunctionExpression {\n  returns: TemplateChildNode[] | CacheExpression\n}\n\n// createSlots({ ... }, [\n//    foo ? () => [] : undefined,\n//    renderList(list, i => () => [i])\n// ])\nexport interface DynamicSlotsExpression extends CallExpression {\n  callee: typeof CREATE_SLOTS\n  arguments: [SlotsObjectExpression, DynamicSlotEntries]\n}\n\nexport interface DynamicSlotEntries extends ArrayExpression {\n  elements: (ConditionalDynamicSlotNode | ListDynamicSlotNode)[]\n}\n\nexport interface ConditionalDynamicSlotNode extends ConditionalExpression {\n  consequent: DynamicSlotNode\n  alternate: DynamicSlotNode | SimpleExpressionNode\n}\n\nexport interface ListDynamicSlotNode extends CallExpression {\n  callee: typeof RENDER_LIST\n  arguments: [ExpressionNode, ListDynamicSlotIterator]\n}\n\nexport interface ListDynamicSlotIterator extends FunctionExpression {\n  returns: DynamicSlotNode\n}\n\nexport interface DynamicSlotNode extends ObjectExpression {\n  properties: [Property, DynamicSlotFnProperty]\n}\n\nexport interface DynamicSlotFnProperty extends Property {\n  value: SlotFunctionExpression\n}\n\nexport type BlockCodegenNode = VNodeCall | RenderSlotCall\n\nexport interface IfConditionalExpression extends ConditionalExpression {\n  consequent: BlockCodegenNode | MemoExpression\n  alternate: BlockCodegenNode | IfConditionalExpression | MemoExpression\n}\n\nexport interface ForCodegenNode extends VNodeCall {\n  isBlock: true\n  tag: typeof FRAGMENT\n  props: undefined\n  children: ForRenderListExpression\n  patchFlag: PatchFlags\n  disableTracking: boolean\n}\n\nexport interface ForRenderListExpression extends CallExpression {\n  callee: typeof RENDER_LIST\n  arguments: [ExpressionNode, ForIteratorExpression]\n}\n\nexport interface ForIteratorExpression extends FunctionExpression {\n  returns?: BlockCodegenNode\n}\n\n// AST Utilities ---------------------------------------------------------------\n\n// Some expressions, e.g. sequence and conditional expressions, are never\n// associated with template nodes, so their source locations are just a stub.\n// Container types like CompoundExpression also don't need a real location.\nexport const locStub: SourceLocation = {\n  start: { line: 1, column: 1, offset: 0 },\n  end: { line: 1, column: 1, offset: 0 },\n  source: '',\n}\n\nexport function createRoot(\n  children: TemplateChildNode[],\n  source = '',\n): RootNode {\n  return {\n    type: NodeTypes.ROOT,\n    source,\n    children,\n    helpers: new Set(),\n    components: [],\n    directives: [],\n    hoists: [],\n    imports: [],\n    cached: [],\n    temps: 0,\n    codegenNode: undefined,\n    loc: locStub,\n  }\n}\n\nexport function createVNodeCall(\n  context: TransformContext | null,\n  tag: VNodeCall['tag'],\n  props?: VNodeCall['props'],\n  children?: VNodeCall['children'],\n  patchFlag?: VNodeCall['patchFlag'],\n  dynamicProps?: VNodeCall['dynamicProps'],\n  directives?: VNodeCall['directives'],\n  isBlock: VNodeCall['isBlock'] = false,\n  disableTracking: VNodeCall['disableTracking'] = false,\n  isComponent: VNodeCall['isComponent'] = false,\n  loc: SourceLocation = locStub,\n): VNodeCall {\n  if (context) {\n    if (isBlock) {\n      context.helper(OPEN_BLOCK)\n      context.helper(getVNodeBlockHelper(context.inSSR, isComponent))\n    } else {\n      context.helper(getVNodeHelper(context.inSSR, isComponent))\n    }\n    if (directives) {\n      context.helper(WITH_DIRECTIVES)\n    }\n  }\n\n  return {\n    type: NodeTypes.VNODE_CALL,\n    tag,\n    props,\n    children,\n    patchFlag,\n    dynamicProps,\n    directives,\n    isBlock,\n    disableTracking,\n    isComponent,\n    loc,\n  }\n}\n\nexport function createArrayExpression(\n  elements: ArrayExpression['elements'],\n  loc: SourceLocation = locStub,\n): ArrayExpression {\n  return {\n    type: NodeTypes.JS_ARRAY_EXPRESSION,\n    loc,\n    elements,\n  }\n}\n\nexport function createObjectExpression(\n  properties: ObjectExpression['properties'],\n  loc: SourceLocation = locStub,\n): ObjectExpression {\n  return {\n    type: NodeTypes.JS_OBJECT_EXPRESSION,\n    loc,\n    properties,\n  }\n}\n\nexport function createObjectProperty(\n  key: Property['key'] | string,\n  value: Property['value'],\n): Property {\n  return {\n    type: NodeTypes.JS_PROPERTY,\n    loc: locStub,\n    key: isString(key) ? createSimpleExpression(key, true) : key,\n    value,\n  }\n}\n\nexport function createSimpleExpression(\n  content: SimpleExpressionNode['content'],\n  isStatic: SimpleExpressionNode['isStatic'] = false,\n  loc: SourceLocation = locStub,\n  constType: ConstantTypes = ConstantTypes.NOT_CONSTANT,\n): SimpleExpressionNode {\n  return {\n    type: NodeTypes.SIMPLE_EXPRESSION,\n    loc,\n    content,\n    isStatic,\n    constType: isStatic ? ConstantTypes.CAN_STRINGIFY : constType,\n  }\n}\n\nexport function createInterpolation(\n  content: InterpolationNode['content'] | string,\n  loc: SourceLocation,\n): InterpolationNode {\n  return {\n    type: NodeTypes.INTERPOLATION,\n    loc,\n    content: isString(content)\n      ? createSimpleExpression(content, false, loc)\n      : content,\n  }\n}\n\nexport function createCompoundExpression(\n  children: CompoundExpressionNode['children'],\n  loc: SourceLocation = locStub,\n): CompoundExpressionNode {\n  return {\n    type: NodeTypes.COMPOUND_EXPRESSION,\n    loc,\n    children,\n  }\n}\n\ntype InferCodegenNodeType<T> = T extends typeof RENDER_SLOT\n  ? RenderSlotCall\n  : CallExpression\n\nexport function createCallExpression<T extends CallExpression['callee']>(\n  callee: T,\n  args: CallExpression['arguments'] = [],\n  loc: SourceLocation = locStub,\n): InferCodegenNodeType<T> {\n  return {\n    type: NodeTypes.JS_CALL_EXPRESSION,\n    loc,\n    callee,\n    arguments: args,\n  } as InferCodegenNodeType<T>\n}\n\nexport function createFunctionExpression(\n  params: FunctionExpression['params'],\n  returns: FunctionExpression['returns'] = undefined,\n  newline: boolean = false,\n  isSlot: boolean = false,\n  loc: SourceLocation = locStub,\n): FunctionExpression {\n  return {\n    type: NodeTypes.JS_FUNCTION_EXPRESSION,\n    params,\n    returns,\n    newline,\n    isSlot,\n    loc,\n  }\n}\n\nexport function createConditionalExpression(\n  test: ConditionalExpression['test'],\n  consequent: ConditionalExpression['consequent'],\n  alternate: ConditionalExpression['alternate'],\n  newline = true,\n): ConditionalExpression {\n  return {\n    type: NodeTypes.JS_CONDITIONAL_EXPRESSION,\n    test,\n    consequent,\n    alternate,\n    newline,\n    loc: locStub,\n  }\n}\n\nexport function createCacheExpression(\n  index: number,\n  value: JSChildNode,\n  needPauseTracking: boolean = false,\n  inVOnce: boolean = false,\n): CacheExpression {\n  return {\n    type: NodeTypes.JS_CACHE_EXPRESSION,\n    index,\n    value,\n    needPauseTracking: needPauseTracking,\n    inVOnce,\n    needArraySpread: false,\n    loc: locStub,\n  }\n}\n\nexport function createBlockStatement(\n  body: BlockStatement['body'],\n): BlockStatement {\n  return {\n    type: NodeTypes.JS_BLOCK_STATEMENT,\n    body,\n    loc: locStub,\n  }\n}\n\nexport function createTemplateLiteral(\n  elements: TemplateLiteral['elements'],\n): TemplateLiteral {\n  return {\n    type: NodeTypes.JS_TEMPLATE_LITERAL,\n    elements,\n    loc: locStub,\n  }\n}\n\nexport function createIfStatement(\n  test: IfStatement['test'],\n  consequent: IfStatement['consequent'],\n  alternate?: IfStatement['alternate'],\n): IfStatement {\n  return {\n    type: NodeTypes.JS_IF_STATEMENT,\n    test,\n    consequent,\n    alternate,\n    loc: locStub,\n  }\n}\n\nexport function createAssignmentExpression(\n  left: AssignmentExpression['left'],\n  right: AssignmentExpression['right'],\n): AssignmentExpression {\n  return {\n    type: NodeTypes.JS_ASSIGNMENT_EXPRESSION,\n    left,\n    right,\n    loc: locStub,\n  }\n}\n\nexport function createSequenceExpression(\n  expressions: SequenceExpression['expressions'],\n): SequenceExpression {\n  return {\n    type: NodeTypes.JS_SEQUENCE_EXPRESSION,\n    expressions,\n    loc: locStub,\n  }\n}\n\nexport function createReturnStatement(\n  returns: ReturnStatement['returns'],\n): ReturnStatement {\n  return {\n    type: NodeTypes.JS_RETURN_STATEMENT,\n    returns,\n    loc: locStub,\n  }\n}\n\nexport function getVNodeHelper(\n  ssr: boolean,\n  isComponent: boolean,\n): typeof CREATE_VNODE | typeof CREATE_ELEMENT_VNODE {\n  return ssr || isComponent ? CREATE_VNODE : CREATE_ELEMENT_VNODE\n}\n\nexport function getVNodeBlockHelper(\n  ssr: boolean,\n  isComponent: boolean,\n): typeof CREATE_BLOCK | typeof CREATE_ELEMENT_BLOCK {\n  return ssr || isComponent ? CREATE_BLOCK : CREATE_ELEMENT_BLOCK\n}\n\nexport function convertToBlock(\n  node: VNodeCall,\n  { helper, removeHelper, inSSR }: TransformContext,\n): void {\n  if (!node.isBlock) {\n    node.isBlock = true\n    removeHelper(getVNodeHelper(inSSR, node.isComponent))\n    helper(OPEN_BLOCK)\n    helper(getVNodeBlockHelper(inSSR, node.isComponent))\n  }\n}\n"
  },
  {
    "path": "packages/compiler-core/src/babelUtils.ts",
    "content": "// should only use types from @babel/types\n// do not import runtime methods\nimport type {\n  BlockStatement,\n  ForInStatement,\n  ForOfStatement,\n  ForStatement,\n  Function,\n  Identifier,\n  Node,\n  ObjectProperty,\n  Program,\n  SwitchCase,\n  SwitchStatement,\n} from '@babel/types'\nimport { walk } from 'estree-walker'\n\n/**\n * Return value indicates whether the AST walked can be a constant\n */\nexport function walkIdentifiers(\n  root: Node,\n  onIdentifier: (\n    node: Identifier,\n    parent: Node | null,\n    parentStack: Node[],\n    isReference: boolean,\n    isLocal: boolean,\n  ) => void,\n  includeAll = false,\n  parentStack: Node[] = [],\n  knownIds: Record<string, number> = Object.create(null),\n): void {\n  if (__BROWSER__) {\n    return\n  }\n\n  const rootExp =\n    root.type === 'Program'\n      ? root.body[0].type === 'ExpressionStatement' && root.body[0].expression\n      : root\n\n  walk(root, {\n    enter(node: Node & { scopeIds?: Set<string> }, parent: Node | null) {\n      parent && parentStack.push(parent)\n      if (\n        parent &&\n        parent.type.startsWith('TS') &&\n        !TS_NODE_TYPES.includes(parent.type)\n      ) {\n        return this.skip()\n      }\n      if (node.type === 'Identifier') {\n        const isLocal = !!knownIds[node.name]\n        const isRefed = isReferencedIdentifier(node, parent, parentStack)\n        if (includeAll || (isRefed && !isLocal)) {\n          onIdentifier(node, parent, parentStack, isRefed, isLocal)\n        }\n      } else if (\n        node.type === 'ObjectProperty' &&\n        // eslint-disable-next-line no-restricted-syntax\n        parent?.type === 'ObjectPattern'\n      ) {\n        // mark property in destructure pattern\n        ;(node as any).inPattern = true\n      } else if (isFunctionType(node)) {\n        if (node.scopeIds) {\n          node.scopeIds.forEach(id => markKnownIds(id, knownIds))\n        } else {\n          // walk function expressions and add its arguments to known identifiers\n          // so that we don't prefix them\n          walkFunctionParams(node, id =>\n            markScopeIdentifier(node, id, knownIds),\n          )\n        }\n      } else if (node.type === 'BlockStatement') {\n        if (node.scopeIds) {\n          node.scopeIds.forEach(id => markKnownIds(id, knownIds))\n        } else {\n          // #3445 record block-level local variables\n          walkBlockDeclarations(node, id =>\n            markScopeIdentifier(node, id, knownIds),\n          )\n        }\n      } else if (node.type === 'SwitchStatement') {\n        if (node.scopeIds) {\n          node.scopeIds.forEach(id => markKnownIds(id, knownIds))\n        } else {\n          // record switch case block-level local variables\n          walkSwitchStatement(node, false, id =>\n            markScopeIdentifier(node, id, knownIds),\n          )\n        }\n      } else if (node.type === 'CatchClause' && node.param) {\n        if (node.scopeIds) {\n          node.scopeIds.forEach(id => markKnownIds(id, knownIds))\n        } else {\n          for (const id of extractIdentifiers(node.param)) {\n            markScopeIdentifier(node, id, knownIds)\n          }\n        }\n      } else if (isForStatement(node)) {\n        if (node.scopeIds) {\n          node.scopeIds.forEach(id => markKnownIds(id, knownIds))\n        } else {\n          walkForStatement(node, false, id =>\n            markScopeIdentifier(node, id, knownIds),\n          )\n        }\n      }\n    },\n    leave(node: Node & { scopeIds?: Set<string> }, parent: Node | null) {\n      parent && parentStack.pop()\n      if (node !== rootExp && node.scopeIds) {\n        for (const id of node.scopeIds) {\n          knownIds[id]--\n          if (knownIds[id] === 0) {\n            delete knownIds[id]\n          }\n        }\n      }\n    },\n  })\n}\n\nexport function isReferencedIdentifier(\n  id: Identifier,\n  parent: Node | null,\n  parentStack: Node[],\n): boolean {\n  if (__BROWSER__) {\n    return false\n  }\n\n  if (!parent) {\n    return true\n  }\n\n  // is a special keyword but parsed as identifier\n  if (id.name === 'arguments') {\n    return false\n  }\n\n  if (isReferenced(id, parent, parentStack[parentStack.length - 2])) {\n    return true\n  }\n\n  // babel's isReferenced check returns false for ids being assigned to, so we\n  // need to cover those cases here\n  switch (parent.type) {\n    case 'AssignmentExpression':\n    case 'AssignmentPattern':\n      return true\n    case 'ObjectProperty':\n      return parent.key !== id && isInDestructureAssignment(parent, parentStack)\n    case 'ArrayPattern':\n      return isInDestructureAssignment(parent, parentStack)\n  }\n\n  return false\n}\n\nexport function isInDestructureAssignment(\n  parent: Node,\n  parentStack: Node[],\n): boolean {\n  if (\n    parent &&\n    (parent.type === 'ObjectProperty' || parent.type === 'ArrayPattern')\n  ) {\n    let i = parentStack.length\n    while (i--) {\n      const p = parentStack[i]\n      if (p.type === 'AssignmentExpression') {\n        return true\n      } else if (p.type !== 'ObjectProperty' && !p.type.endsWith('Pattern')) {\n        break\n      }\n    }\n  }\n  return false\n}\n\nexport function isInNewExpression(parentStack: Node[]): boolean {\n  let i = parentStack.length\n  while (i--) {\n    const p = parentStack[i]\n    if (p.type === 'NewExpression') {\n      return true\n    } else if (p.type !== 'MemberExpression') {\n      break\n    }\n  }\n  return false\n}\n\nexport function walkFunctionParams(\n  node: Function,\n  onIdent: (id: Identifier) => void,\n): void {\n  for (const p of node.params) {\n    for (const id of extractIdentifiers(p)) {\n      onIdent(id)\n    }\n  }\n}\n\nexport function walkBlockDeclarations(\n  block: BlockStatement | SwitchCase | Program,\n  onIdent: (node: Identifier) => void,\n): void {\n  const body = block.type === 'SwitchCase' ? block.consequent : block.body\n  for (const stmt of body) {\n    if (stmt.type === 'VariableDeclaration') {\n      if (stmt.declare) continue\n      for (const decl of stmt.declarations) {\n        for (const id of extractIdentifiers(decl.id)) {\n          onIdent(id)\n        }\n      }\n    } else if (\n      stmt.type === 'FunctionDeclaration' ||\n      stmt.type === 'ClassDeclaration'\n    ) {\n      if (stmt.declare || !stmt.id) continue\n      onIdent(stmt.id)\n    } else if (isForStatement(stmt)) {\n      walkForStatement(stmt, true, onIdent)\n    } else if (stmt.type === 'SwitchStatement') {\n      walkSwitchStatement(stmt, true, onIdent)\n    }\n  }\n}\n\nfunction isForStatement(\n  stmt: Node,\n): stmt is ForStatement | ForOfStatement | ForInStatement {\n  return (\n    stmt.type === 'ForOfStatement' ||\n    stmt.type === 'ForInStatement' ||\n    stmt.type === 'ForStatement'\n  )\n}\n\nfunction walkForStatement(\n  stmt: ForStatement | ForOfStatement | ForInStatement,\n  isVar: boolean,\n  onIdent: (id: Identifier) => void,\n) {\n  const variable = stmt.type === 'ForStatement' ? stmt.init : stmt.left\n  if (\n    variable &&\n    variable.type === 'VariableDeclaration' &&\n    (variable.kind === 'var' ? isVar : !isVar)\n  ) {\n    for (const decl of variable.declarations) {\n      for (const id of extractIdentifiers(decl.id)) {\n        onIdent(id)\n      }\n    }\n  }\n}\n\nfunction walkSwitchStatement(\n  stmt: SwitchStatement,\n  isVar: boolean,\n  onIdent: (id: Identifier) => void,\n) {\n  for (const cs of stmt.cases) {\n    for (const stmt of cs.consequent) {\n      if (\n        stmt.type === 'VariableDeclaration' &&\n        (stmt.kind === 'var' ? isVar : !isVar)\n      ) {\n        for (const decl of stmt.declarations) {\n          for (const id of extractIdentifiers(decl.id)) {\n            onIdent(id)\n          }\n        }\n      }\n    }\n    walkBlockDeclarations(cs, onIdent)\n  }\n}\n\nexport function extractIdentifiers(\n  param: Node,\n  nodes: Identifier[] = [],\n): Identifier[] {\n  switch (param.type) {\n    case 'Identifier':\n      nodes.push(param)\n      break\n\n    case 'MemberExpression':\n      let object: any = param\n      while (object.type === 'MemberExpression') {\n        object = object.object\n      }\n      nodes.push(object)\n      break\n\n    case 'ObjectPattern':\n      for (const prop of param.properties) {\n        if (prop.type === 'RestElement') {\n          extractIdentifiers(prop.argument, nodes)\n        } else {\n          extractIdentifiers(prop.value, nodes)\n        }\n      }\n      break\n\n    case 'ArrayPattern':\n      param.elements.forEach(element => {\n        if (element) extractIdentifiers(element, nodes)\n      })\n      break\n\n    case 'RestElement':\n      extractIdentifiers(param.argument, nodes)\n      break\n\n    case 'AssignmentPattern':\n      extractIdentifiers(param.left, nodes)\n      break\n  }\n\n  return nodes\n}\n\nfunction markKnownIds(name: string, knownIds: Record<string, number>) {\n  if (name in knownIds) {\n    knownIds[name]++\n  } else {\n    knownIds[name] = 1\n  }\n}\n\nfunction markScopeIdentifier(\n  node: Node & { scopeIds?: Set<string> },\n  child: Identifier,\n  knownIds: Record<string, number>,\n) {\n  const { name } = child\n  if (node.scopeIds && node.scopeIds.has(name)) {\n    return\n  }\n  markKnownIds(name, knownIds)\n  ;(node.scopeIds || (node.scopeIds = new Set())).add(name)\n}\n\nexport const isFunctionType = (node: Node): node is Function => {\n  return /Function(?:Expression|Declaration)$|Method$/.test(node.type)\n}\n\nexport const isStaticProperty = (node: Node): node is ObjectProperty =>\n  node &&\n  (node.type === 'ObjectProperty' || node.type === 'ObjectMethod') &&\n  !node.computed\n\nexport const isStaticPropertyKey = (node: Node, parent: Node): boolean =>\n  isStaticProperty(parent) && parent.key === node\n\n/**\n * Copied from https://github.com/babel/babel/blob/main/packages/babel-types/src/validators/isReferenced.ts\n * To avoid runtime dependency on @babel/types (which includes process references)\n * This file should not change very often in babel but we may need to keep it\n * up-to-date from time to time.\n *\n * https://github.com/babel/babel/blob/main/LICENSE\n *\n */\nfunction isReferenced(node: Node, parent: Node, grandparent?: Node): boolean {\n  switch (parent.type) {\n    // yes: PARENT[NODE]\n    // yes: NODE.child\n    // no: parent.NODE\n    case 'MemberExpression':\n    case 'OptionalMemberExpression':\n      if (parent.property === node) {\n        return !!parent.computed\n      }\n      return parent.object === node\n\n    case 'JSXMemberExpression':\n      return parent.object === node\n    // no: let NODE = init;\n    // yes: let id = NODE;\n    case 'VariableDeclarator':\n      return parent.init === node\n\n    // yes: () => NODE\n    // no: (NODE) => {}\n    case 'ArrowFunctionExpression':\n      return parent.body === node\n\n    // no: class { #NODE; }\n    // no: class { get #NODE() {} }\n    // no: class { #NODE() {} }\n    // no: class { fn() { return this.#NODE; } }\n    case 'PrivateName':\n      return false\n\n    // no: class { NODE() {} }\n    // yes: class { [NODE]() {} }\n    // no: class { foo(NODE) {} }\n    case 'ClassMethod':\n    case 'ClassPrivateMethod':\n    case 'ObjectMethod':\n      if (parent.key === node) {\n        return !!parent.computed\n      }\n      return false\n\n    // yes: { [NODE]: \"\" }\n    // no: { NODE: \"\" }\n    // depends: { NODE }\n    // depends: { key: NODE }\n    case 'ObjectProperty':\n      if (parent.key === node) {\n        return !!parent.computed\n      }\n      // parent.value === node\n      return !grandparent || grandparent.type !== 'ObjectPattern'\n    // no: class { NODE = value; }\n    // yes: class { [NODE] = value; }\n    // yes: class { key = NODE; }\n    case 'ClassProperty':\n      if (parent.key === node) {\n        return !!parent.computed\n      }\n      return true\n    case 'ClassPrivateProperty':\n      return parent.key !== node\n\n    // no: class NODE {}\n    // yes: class Foo extends NODE {}\n    case 'ClassDeclaration':\n    case 'ClassExpression':\n      return parent.superClass === node\n\n    // yes: left = NODE;\n    // no: NODE = right;\n    case 'AssignmentExpression':\n      return parent.right === node\n\n    // no: [NODE = foo] = [];\n    // yes: [foo = NODE] = [];\n    case 'AssignmentPattern':\n      return parent.right === node\n\n    // no: NODE: for (;;) {}\n    case 'LabeledStatement':\n      return false\n\n    // no: try {} catch (NODE) {}\n    case 'CatchClause':\n      return false\n\n    // no: function foo(...NODE) {}\n    case 'RestElement':\n      return false\n\n    case 'BreakStatement':\n    case 'ContinueStatement':\n      return false\n\n    // no: function NODE() {}\n    // no: function foo(NODE) {}\n    case 'FunctionDeclaration':\n    case 'FunctionExpression':\n      return false\n\n    // no: export NODE from \"foo\";\n    // no: export * as NODE from \"foo\";\n    case 'ExportNamespaceSpecifier':\n    case 'ExportDefaultSpecifier':\n      return false\n\n    // no: export { foo as NODE };\n    // yes: export { NODE as foo };\n    // no: export { NODE as foo } from \"foo\";\n    case 'ExportSpecifier':\n      // @ts-expect-error\n      // eslint-disable-next-line no-restricted-syntax\n      if (grandparent?.source) {\n        return false\n      }\n      return parent.local === node\n\n    // no: import NODE from \"foo\";\n    // no: import * as NODE from \"foo\";\n    // no: import { NODE as foo } from \"foo\";\n    // no: import { foo as NODE } from \"foo\";\n    // no: import NODE from \"bar\";\n    case 'ImportDefaultSpecifier':\n    case 'ImportNamespaceSpecifier':\n    case 'ImportSpecifier':\n      return false\n\n    // no: import \"foo\" assert { NODE: \"json\" }\n    case 'ImportAttribute':\n      return false\n\n    // no: <div NODE=\"foo\" />\n    case 'JSXAttribute':\n      return false\n\n    // no: [NODE] = [];\n    // no: ({ NODE }) = [];\n    case 'ObjectPattern':\n    case 'ArrayPattern':\n      return false\n\n    // no: new.NODE\n    // no: NODE.target\n    case 'MetaProperty':\n      return false\n\n    // yes: type X = { someProperty: NODE }\n    // no: type X = { NODE: OtherType }\n    case 'ObjectTypeProperty':\n      return parent.key !== node\n\n    // yes: enum X { Foo = NODE }\n    // no: enum X { NODE }\n    case 'TSEnumMember':\n      return parent.id !== node\n\n    // yes: { [NODE]: value }\n    // no: { NODE: value }\n    case 'TSPropertySignature':\n      if (parent.key === node) {\n        return !!parent.computed\n      }\n\n      return true\n  }\n\n  return true\n}\n\nexport const TS_NODE_TYPES: string[] = [\n  'TSAsExpression', // foo as number\n  'TSTypeAssertion', // (<number>foo)\n  'TSNonNullExpression', // foo!\n  'TSInstantiationExpression', // foo<string>\n  'TSSatisfiesExpression', // foo satisfies T\n]\n\nexport function unwrapTSNode(node: Node): Node {\n  if (TS_NODE_TYPES.includes(node.type)) {\n    return unwrapTSNode((node as any).expression)\n  } else {\n    return node\n  }\n}\n"
  },
  {
    "path": "packages/compiler-core/src/codegen.ts",
    "content": "import type { CodegenOptions } from './options'\nimport {\n  type ArrayExpression,\n  type AssignmentExpression,\n  type CacheExpression,\n  type CallExpression,\n  type CommentNode,\n  type CompoundExpressionNode,\n  type ConditionalExpression,\n  type ExpressionNode,\n  type FunctionExpression,\n  type IfStatement,\n  type InterpolationNode,\n  type JSChildNode,\n  NodeTypes,\n  type ObjectExpression,\n  type Position,\n  type ReturnStatement,\n  type RootNode,\n  type SSRCodegenNode,\n  type SequenceExpression,\n  type SimpleExpressionNode,\n  type TemplateChildNode,\n  type TemplateLiteral,\n  type TextNode,\n  type VNodeCall,\n  getVNodeBlockHelper,\n  getVNodeHelper,\n  locStub,\n} from './ast'\nimport { SourceMapGenerator } from 'source-map-js'\nimport {\n  advancePositionWithMutation,\n  assert,\n  isSimpleIdentifier,\n  toValidAssetId,\n} from './utils'\nimport {\n  PatchFlagNames,\n  type PatchFlags,\n  isArray,\n  isString,\n  isSymbol,\n} from '@vue/shared'\nimport {\n  CREATE_COMMENT,\n  CREATE_ELEMENT_VNODE,\n  CREATE_STATIC,\n  CREATE_TEXT,\n  CREATE_VNODE,\n  OPEN_BLOCK,\n  RESOLVE_COMPONENT,\n  RESOLVE_DIRECTIVE,\n  RESOLVE_FILTER,\n  SET_BLOCK_TRACKING,\n  TO_DISPLAY_STRING,\n  WITH_CTX,\n  WITH_DIRECTIVES,\n  helperNameMap,\n} from './runtimeHelpers'\nimport type { ImportItem } from './transform'\n\n/**\n * The `SourceMapGenerator` type from `source-map-js` is a bit incomplete as it\n * misses `toJSON()`. We also need to add types for internal properties which we\n * need to access for better performance.\n *\n * Since TS 5.3, dts generation starts to strangely include broken triple slash\n * references for source-map-js, so we are inlining all source map related types\n * here to to workaround that.\n */\nexport interface CodegenSourceMapGenerator {\n  setSourceContent(sourceFile: string, sourceContent: string): void\n  // SourceMapGenerator has this method but the types do not include it\n  toJSON(): RawSourceMap\n  _sources: Set<string>\n  _names: Set<string>\n  _mappings: {\n    add(mapping: MappingItem): void\n  }\n}\n\nexport interface RawSourceMap {\n  file?: string\n  sourceRoot?: string\n  version: string\n  sources: string[]\n  names: string[]\n  sourcesContent?: string[]\n  mappings: string\n}\n\ninterface MappingItem {\n  source: string\n  generatedLine: number\n  generatedColumn: number\n  originalLine: number\n  originalColumn: number\n  name: string | null\n}\n\nconst PURE_ANNOTATION = `/*@__PURE__*/`\n\nconst aliasHelper = (s: symbol) => `${helperNameMap[s]}: _${helperNameMap[s]}`\n\ntype CodegenNode = TemplateChildNode | JSChildNode | SSRCodegenNode\n\nexport interface CodegenResult {\n  code: string\n  preamble: string\n  ast: RootNode\n  map?: RawSourceMap\n}\n\nenum NewlineType {\n  Start = 0,\n  End = -1,\n  None = -2,\n  Unknown = -3,\n}\n\nexport interface CodegenContext extends Omit<\n  Required<CodegenOptions>,\n  'bindingMetadata' | 'inline'\n> {\n  source: string\n  code: string\n  line: number\n  column: number\n  offset: number\n  indentLevel: number\n  pure: boolean\n  map?: CodegenSourceMapGenerator\n  helper(key: symbol): string\n  push(code: string, newlineIndex?: number, node?: CodegenNode): void\n  indent(): void\n  deindent(withoutNewLine?: boolean): void\n  newline(): void\n}\n\nfunction createCodegenContext(\n  ast: RootNode,\n  {\n    mode = 'function',\n    prefixIdentifiers = mode === 'module',\n    sourceMap = false,\n    filename = `template.vue.html`,\n    scopeId = null,\n    optimizeImports = false,\n    runtimeGlobalName = `Vue`,\n    runtimeModuleName = `vue`,\n    ssrRuntimeModuleName = 'vue/server-renderer',\n    ssr = false,\n    isTS = false,\n    inSSR = false,\n  }: CodegenOptions,\n): CodegenContext {\n  const context: CodegenContext = {\n    mode,\n    prefixIdentifiers,\n    sourceMap,\n    filename,\n    scopeId,\n    optimizeImports,\n    runtimeGlobalName,\n    runtimeModuleName,\n    ssrRuntimeModuleName,\n    ssr,\n    isTS,\n    inSSR,\n    source: ast.source,\n    code: ``,\n    column: 1,\n    line: 1,\n    offset: 0,\n    indentLevel: 0,\n    pure: false,\n    map: undefined,\n    helper(key) {\n      return `_${helperNameMap[key]}`\n    },\n    push(code, newlineIndex = NewlineType.None, node) {\n      context.code += code\n      if (!__BROWSER__ && context.map) {\n        if (node) {\n          let name\n          if (node.type === NodeTypes.SIMPLE_EXPRESSION && !node.isStatic) {\n            const content = node.content.replace(/^_ctx\\./, '')\n            if (content !== node.content && isSimpleIdentifier(content)) {\n              name = content\n            }\n          }\n          if (node.loc.source) {\n            addMapping(node.loc.start, name)\n          }\n        }\n        if (newlineIndex === NewlineType.Unknown) {\n          // multiple newlines, full iteration\n          advancePositionWithMutation(context, code)\n        } else {\n          // fast paths\n          context.offset += code.length\n          if (newlineIndex === NewlineType.None) {\n            // no newlines; fast path to avoid newline detection\n            if (__TEST__ && code.includes('\\n')) {\n              throw new Error(\n                `CodegenContext.push() called newlineIndex: none, but contains` +\n                  `newlines: ${code.replace(/\\n/g, '\\\\n')}`,\n              )\n            }\n            context.column += code.length\n          } else {\n            // single newline at known index\n            if (newlineIndex === NewlineType.End) {\n              newlineIndex = code.length - 1\n            }\n            if (\n              __TEST__ &&\n              (code.charAt(newlineIndex) !== '\\n' ||\n                code.slice(0, newlineIndex).includes('\\n') ||\n                code.slice(newlineIndex + 1).includes('\\n'))\n            ) {\n              throw new Error(\n                `CodegenContext.push() called with newlineIndex: ${newlineIndex} ` +\n                  `but does not conform: ${code.replace(/\\n/g, '\\\\n')}`,\n              )\n            }\n            context.line++\n            context.column = code.length - newlineIndex\n          }\n        }\n        if (node && node.loc !== locStub && node.loc.source) {\n          addMapping(node.loc.end)\n        }\n      }\n    },\n    indent() {\n      newline(++context.indentLevel)\n    },\n    deindent(withoutNewLine = false) {\n      if (withoutNewLine) {\n        --context.indentLevel\n      } else {\n        newline(--context.indentLevel)\n      }\n    },\n    newline() {\n      newline(context.indentLevel)\n    },\n  }\n\n  function newline(n: number) {\n    context.push('\\n' + `  `.repeat(n), NewlineType.Start)\n  }\n\n  function addMapping(loc: Position, name: string | null = null) {\n    // we use the private property to directly add the mapping\n    // because the addMapping() implementation in source-map-js has a bunch of\n    // unnecessary arg and validation checks that are pure overhead in our case.\n    const { _names, _mappings } = context.map!\n    if (name !== null && !_names.has(name)) _names.add(name)\n    _mappings.add({\n      originalLine: loc.line,\n      originalColumn: loc.column - 1, // source-map column is 0 based\n      generatedLine: context.line,\n      generatedColumn: context.column - 1,\n      source: filename,\n      name,\n    })\n  }\n\n  if (!__BROWSER__ && sourceMap) {\n    // lazy require source-map implementation, only in non-browser builds\n    context.map =\n      new SourceMapGenerator() as unknown as CodegenSourceMapGenerator\n    context.map.setSourceContent(filename, context.source)\n    context.map._sources.add(filename)\n  }\n\n  return context\n}\n\nexport function generate(\n  ast: RootNode,\n  options: CodegenOptions & {\n    onContextCreated?: (context: CodegenContext) => void\n  } = {},\n): CodegenResult {\n  const context = createCodegenContext(ast, options)\n  if (options.onContextCreated) options.onContextCreated(context)\n  const {\n    mode,\n    push,\n    prefixIdentifiers,\n    indent,\n    deindent,\n    newline,\n    scopeId,\n    ssr,\n  } = context\n\n  const helpers = Array.from(ast.helpers)\n  const hasHelpers = helpers.length > 0\n  const useWithBlock = !prefixIdentifiers && mode !== 'module'\n  const genScopeId = !__BROWSER__ && scopeId != null && mode === 'module'\n  const isSetupInlined = !__BROWSER__ && !!options.inline\n\n  // preambles\n  // in setup() inline mode, the preamble is generated in a sub context\n  // and returned separately.\n  const preambleContext = isSetupInlined\n    ? createCodegenContext(ast, options)\n    : context\n  if (!__BROWSER__ && mode === 'module') {\n    genModulePreamble(ast, preambleContext, genScopeId, isSetupInlined)\n  } else {\n    genFunctionPreamble(ast, preambleContext)\n  }\n  // enter render function\n  const functionName = ssr ? `ssrRender` : `render`\n  const args = ssr ? ['_ctx', '_push', '_parent', '_attrs'] : ['_ctx', '_cache']\n  if (!__BROWSER__ && options.bindingMetadata && !options.inline) {\n    // binding optimization args\n    args.push('$props', '$setup', '$data', '$options')\n  }\n  const signature =\n    !__BROWSER__ && options.isTS\n      ? args.map(arg => `${arg}: any`).join(',')\n      : args.join(', ')\n\n  if (isSetupInlined) {\n    push(`(${signature}) => {`)\n  } else {\n    push(`function ${functionName}(${signature}) {`)\n  }\n  indent()\n\n  if (useWithBlock) {\n    push(`with (_ctx) {`)\n    indent()\n    // function mode const declarations should be inside with block\n    // also they should be renamed to avoid collision with user properties\n    if (hasHelpers) {\n      push(\n        `const { ${helpers.map(aliasHelper).join(', ')} } = _Vue\\n`,\n        NewlineType.End,\n      )\n      newline()\n    }\n  }\n\n  // generate asset resolution statements\n  if (ast.components.length) {\n    genAssets(ast.components, 'component', context)\n    if (ast.directives.length || ast.temps > 0) {\n      newline()\n    }\n  }\n  if (ast.directives.length) {\n    genAssets(ast.directives, 'directive', context)\n    if (ast.temps > 0) {\n      newline()\n    }\n  }\n  if (__COMPAT__ && ast.filters && ast.filters.length) {\n    newline()\n    genAssets(ast.filters, 'filter', context)\n    newline()\n  }\n\n  if (ast.temps > 0) {\n    push(`let `)\n    for (let i = 0; i < ast.temps; i++) {\n      push(`${i > 0 ? `, ` : ``}_temp${i}`)\n    }\n  }\n  if (ast.components.length || ast.directives.length || ast.temps) {\n    push(`\\n`, NewlineType.Start)\n    newline()\n  }\n\n  // generate the VNode tree expression\n  if (!ssr) {\n    push(`return `)\n  }\n  if (ast.codegenNode) {\n    genNode(ast.codegenNode, context)\n  } else {\n    push(`null`)\n  }\n\n  if (useWithBlock) {\n    deindent()\n    push(`}`)\n  }\n\n  deindent()\n  push(`}`)\n\n  return {\n    ast,\n    code: context.code,\n    preamble: isSetupInlined ? preambleContext.code : ``,\n    map: context.map ? context.map.toJSON() : undefined,\n  }\n}\n\nfunction genFunctionPreamble(ast: RootNode, context: CodegenContext) {\n  const {\n    ssr,\n    prefixIdentifiers,\n    push,\n    newline,\n    runtimeModuleName,\n    runtimeGlobalName,\n    ssrRuntimeModuleName,\n  } = context\n  const VueBinding =\n    !__BROWSER__ && ssr\n      ? `require(${JSON.stringify(runtimeModuleName)})`\n      : runtimeGlobalName\n  // Generate const declaration for helpers\n  // In prefix mode, we place the const declaration at top so it's done\n  // only once; But if we not prefixing, we place the declaration inside the\n  // with block so it doesn't incur the `in` check cost for every helper access.\n  const helpers = Array.from(ast.helpers)\n  if (helpers.length > 0) {\n    if (!__BROWSER__ && prefixIdentifiers) {\n      push(\n        `const { ${helpers.map(aliasHelper).join(', ')} } = ${VueBinding}\\n`,\n        NewlineType.End,\n      )\n    } else {\n      // \"with\" mode.\n      // save Vue in a separate variable to avoid collision\n      push(`const _Vue = ${VueBinding}\\n`, NewlineType.End)\n      // in \"with\" mode, helpers are declared inside the with block to avoid\n      // has check cost, but hoists are lifted out of the function - we need\n      // to provide the helper here.\n      if (ast.hoists.length) {\n        const staticHelpers = [\n          CREATE_VNODE,\n          CREATE_ELEMENT_VNODE,\n          CREATE_COMMENT,\n          CREATE_TEXT,\n          CREATE_STATIC,\n        ]\n          .filter(helper => helpers.includes(helper))\n          .map(aliasHelper)\n          .join(', ')\n        push(`const { ${staticHelpers} } = _Vue\\n`, NewlineType.End)\n      }\n    }\n  }\n  // generate variables for ssr helpers\n  if (!__BROWSER__ && ast.ssrHelpers && ast.ssrHelpers.length) {\n    // ssr guarantees prefixIdentifier: true\n    push(\n      `const { ${ast.ssrHelpers\n        .map(aliasHelper)\n        .join(', ')} } = require(\"${ssrRuntimeModuleName}\")\\n`,\n      NewlineType.End,\n    )\n  }\n  genHoists(ast.hoists, context)\n  newline()\n  push(`return `)\n}\n\nfunction genModulePreamble(\n  ast: RootNode,\n  context: CodegenContext,\n  genScopeId: boolean,\n  inline?: boolean,\n) {\n  const {\n    push,\n    newline,\n    optimizeImports,\n    runtimeModuleName,\n    ssrRuntimeModuleName,\n  } = context\n\n  // generate import statements for helpers\n  if (ast.helpers.size) {\n    const helpers = Array.from(ast.helpers)\n    if (optimizeImports) {\n      // when bundled with webpack with code-split, calling an import binding\n      // as a function leads to it being wrapped with `Object(a.b)` or `(0,a.b)`,\n      // incurring both payload size increase and potential perf overhead.\n      // therefore we assign the imports to variables (which is a constant ~50b\n      // cost per-component instead of scaling with template size)\n      push(\n        `import { ${helpers\n          .map(s => helperNameMap[s])\n          .join(', ')} } from ${JSON.stringify(runtimeModuleName)}\\n`,\n        NewlineType.End,\n      )\n      push(\n        `\\n// Binding optimization for webpack code-split\\nconst ${helpers\n          .map(s => `_${helperNameMap[s]} = ${helperNameMap[s]}`)\n          .join(', ')}\\n`,\n        NewlineType.End,\n      )\n    } else {\n      push(\n        `import { ${helpers\n          .map(s => `${helperNameMap[s]} as _${helperNameMap[s]}`)\n          .join(', ')} } from ${JSON.stringify(runtimeModuleName)}\\n`,\n        NewlineType.End,\n      )\n    }\n  }\n\n  if (ast.ssrHelpers && ast.ssrHelpers.length) {\n    push(\n      `import { ${ast.ssrHelpers\n        .map(s => `${helperNameMap[s]} as _${helperNameMap[s]}`)\n        .join(', ')} } from \"${ssrRuntimeModuleName}\"\\n`,\n      NewlineType.End,\n    )\n  }\n\n  if (ast.imports.length) {\n    genImports(ast.imports, context)\n    newline()\n  }\n\n  genHoists(ast.hoists, context)\n  newline()\n\n  if (!inline) {\n    push(`export `)\n  }\n}\n\nfunction genAssets(\n  assets: string[],\n  type: 'component' | 'directive' | 'filter',\n  { helper, push, newline, isTS }: CodegenContext,\n) {\n  const resolver = helper(\n    __COMPAT__ && type === 'filter'\n      ? RESOLVE_FILTER\n      : type === 'component'\n        ? RESOLVE_COMPONENT\n        : RESOLVE_DIRECTIVE,\n  )\n  for (let i = 0; i < assets.length; i++) {\n    let id = assets[i]\n    // potential component implicit self-reference inferred from SFC filename\n    const maybeSelfReference = id.endsWith('__self')\n    if (maybeSelfReference) {\n      id = id.slice(0, -6)\n    }\n    push(\n      `const ${toValidAssetId(id, type)} = ${resolver}(${JSON.stringify(id)}${\n        maybeSelfReference ? `, true` : ``\n      })${isTS ? `!` : ``}`,\n    )\n    if (i < assets.length - 1) {\n      newline()\n    }\n  }\n}\n\nfunction genHoists(hoists: (JSChildNode | null)[], context: CodegenContext) {\n  if (!hoists.length) {\n    return\n  }\n  context.pure = true\n  const { push, newline } = context\n  newline()\n\n  for (let i = 0; i < hoists.length; i++) {\n    const exp = hoists[i]\n    if (exp) {\n      push(`const _hoisted_${i + 1} = `)\n      genNode(exp, context)\n      newline()\n    }\n  }\n\n  context.pure = false\n}\n\nfunction genImports(importsOptions: ImportItem[], context: CodegenContext) {\n  if (!importsOptions.length) {\n    return\n  }\n  importsOptions.forEach(imports => {\n    context.push(`import `)\n    genNode(imports.exp, context)\n    context.push(` from '${imports.path}'`)\n    context.newline()\n  })\n}\n\nfunction isText(n: string | CodegenNode) {\n  return (\n    isString(n) ||\n    n.type === NodeTypes.SIMPLE_EXPRESSION ||\n    n.type === NodeTypes.TEXT ||\n    n.type === NodeTypes.INTERPOLATION ||\n    n.type === NodeTypes.COMPOUND_EXPRESSION\n  )\n}\n\nfunction genNodeListAsArray(\n  nodes: (string | CodegenNode | TemplateChildNode[])[],\n  context: CodegenContext,\n) {\n  const multilines =\n    nodes.length > 3 ||\n    ((!__BROWSER__ || __DEV__) && nodes.some(n => isArray(n) || !isText(n)))\n  context.push(`[`)\n  multilines && context.indent()\n  genNodeList(nodes, context, multilines)\n  multilines && context.deindent()\n  context.push(`]`)\n}\n\nfunction genNodeList(\n  nodes: (string | symbol | CodegenNode | TemplateChildNode[])[],\n  context: CodegenContext,\n  multilines: boolean = false,\n  comma: boolean = true,\n) {\n  const { push, newline } = context\n  for (let i = 0; i < nodes.length; i++) {\n    const node = nodes[i]\n    if (isString(node)) {\n      push(node, NewlineType.Unknown)\n    } else if (isArray(node)) {\n      genNodeListAsArray(node, context)\n    } else {\n      genNode(node, context)\n    }\n    if (i < nodes.length - 1) {\n      if (multilines) {\n        comma && push(',')\n        newline()\n      } else {\n        comma && push(', ')\n      }\n    }\n  }\n}\n\nfunction genNode(node: CodegenNode | symbol | string, context: CodegenContext) {\n  if (isString(node)) {\n    context.push(node, NewlineType.Unknown)\n    return\n  }\n  if (isSymbol(node)) {\n    context.push(context.helper(node))\n    return\n  }\n  switch (node.type) {\n    case NodeTypes.ELEMENT:\n    case NodeTypes.IF:\n    case NodeTypes.FOR:\n      __DEV__ &&\n        assert(\n          node.codegenNode != null,\n          `Codegen node is missing for element/if/for node. ` +\n            `Apply appropriate transforms first.`,\n        )\n      genNode(node.codegenNode!, context)\n      break\n    case NodeTypes.TEXT:\n      genText(node, context)\n      break\n    case NodeTypes.SIMPLE_EXPRESSION:\n      genExpression(node, context)\n      break\n    case NodeTypes.INTERPOLATION:\n      genInterpolation(node, context)\n      break\n    case NodeTypes.TEXT_CALL:\n      genNode(node.codegenNode, context)\n      break\n    case NodeTypes.COMPOUND_EXPRESSION:\n      genCompoundExpression(node, context)\n      break\n    case NodeTypes.COMMENT:\n      genComment(node, context)\n      break\n    case NodeTypes.VNODE_CALL:\n      genVNodeCall(node, context)\n      break\n\n    case NodeTypes.JS_CALL_EXPRESSION:\n      genCallExpression(node, context)\n      break\n    case NodeTypes.JS_OBJECT_EXPRESSION:\n      genObjectExpression(node, context)\n      break\n    case NodeTypes.JS_ARRAY_EXPRESSION:\n      genArrayExpression(node, context)\n      break\n    case NodeTypes.JS_FUNCTION_EXPRESSION:\n      genFunctionExpression(node, context)\n      break\n    case NodeTypes.JS_CONDITIONAL_EXPRESSION:\n      genConditionalExpression(node, context)\n      break\n    case NodeTypes.JS_CACHE_EXPRESSION:\n      genCacheExpression(node, context)\n      break\n    case NodeTypes.JS_BLOCK_STATEMENT:\n      genNodeList(node.body, context, true, false)\n      break\n\n    // SSR only types\n    case NodeTypes.JS_TEMPLATE_LITERAL:\n      !__BROWSER__ && genTemplateLiteral(node, context)\n      break\n    case NodeTypes.JS_IF_STATEMENT:\n      !__BROWSER__ && genIfStatement(node, context)\n      break\n    case NodeTypes.JS_ASSIGNMENT_EXPRESSION:\n      !__BROWSER__ && genAssignmentExpression(node, context)\n      break\n    case NodeTypes.JS_SEQUENCE_EXPRESSION:\n      !__BROWSER__ && genSequenceExpression(node, context)\n      break\n    case NodeTypes.JS_RETURN_STATEMENT:\n      !__BROWSER__ && genReturnStatement(node, context)\n      break\n\n    /* v8 ignore start */\n    case NodeTypes.IF_BRANCH:\n      // noop\n      break\n    default:\n      if (__DEV__) {\n        assert(false, `unhandled codegen node type: ${(node as any).type}`)\n        // make sure we exhaust all possible types\n        const exhaustiveCheck: never = node\n        return exhaustiveCheck\n      }\n    /* v8 ignore stop */\n  }\n}\n\nfunction genText(\n  node: TextNode | SimpleExpressionNode,\n  context: CodegenContext,\n) {\n  context.push(JSON.stringify(node.content), NewlineType.Unknown, node)\n}\n\nfunction genExpression(node: SimpleExpressionNode, context: CodegenContext) {\n  const { content, isStatic } = node\n  context.push(\n    isStatic ? JSON.stringify(content) : content,\n    NewlineType.Unknown,\n    node,\n  )\n}\n\nfunction genInterpolation(node: InterpolationNode, context: CodegenContext) {\n  const { push, helper, pure } = context\n  if (pure) push(PURE_ANNOTATION)\n  push(`${helper(TO_DISPLAY_STRING)}(`)\n  genNode(node.content, context)\n  push(`)`)\n}\n\nfunction genCompoundExpression(\n  node: CompoundExpressionNode,\n  context: CodegenContext,\n) {\n  for (let i = 0; i < node.children!.length; i++) {\n    const child = node.children![i]\n    if (isString(child)) {\n      context.push(child, NewlineType.Unknown)\n    } else {\n      genNode(child, context)\n    }\n  }\n}\n\nfunction genExpressionAsPropertyKey(\n  node: ExpressionNode,\n  context: CodegenContext,\n) {\n  const { push } = context\n  if (node.type === NodeTypes.COMPOUND_EXPRESSION) {\n    push(`[`)\n    genCompoundExpression(node, context)\n    push(`]`)\n  } else if (node.isStatic) {\n    // only quote keys if necessary\n    const text = isSimpleIdentifier(node.content)\n      ? node.content\n      : JSON.stringify(node.content)\n    push(text, NewlineType.None, node)\n  } else {\n    push(`[${node.content}]`, NewlineType.Unknown, node)\n  }\n}\n\nfunction genComment(node: CommentNode, context: CodegenContext) {\n  const { push, helper, pure } = context\n  if (pure) {\n    push(PURE_ANNOTATION)\n  }\n  push(\n    `${helper(CREATE_COMMENT)}(${JSON.stringify(node.content)})`,\n    NewlineType.Unknown,\n    node,\n  )\n}\n\nfunction genVNodeCall(node: VNodeCall, context: CodegenContext) {\n  const { push, helper, pure } = context\n  const {\n    tag,\n    props,\n    children,\n    patchFlag,\n    dynamicProps,\n    directives,\n    isBlock,\n    disableTracking,\n    isComponent,\n  } = node\n\n  // add dev annotations to patch flags\n  let patchFlagString\n  if (patchFlag) {\n    if (__DEV__) {\n      if (patchFlag < 0) {\n        // special flags (negative and mutually exclusive)\n        patchFlagString = patchFlag + ` /* ${PatchFlagNames[patchFlag]} */`\n      } else {\n        // bitwise flags\n        const flagNames = Object.keys(PatchFlagNames)\n          .map(Number)\n          .filter(n => n > 0 && patchFlag & n)\n          .map(n => PatchFlagNames[n as PatchFlags])\n          .join(`, `)\n        patchFlagString = patchFlag + ` /* ${flagNames} */`\n      }\n    } else {\n      patchFlagString = String(patchFlag)\n    }\n  }\n\n  if (directives) {\n    push(helper(WITH_DIRECTIVES) + `(`)\n  }\n  if (isBlock) {\n    push(`(${helper(OPEN_BLOCK)}(${disableTracking ? `true` : ``}), `)\n  }\n  if (pure) {\n    push(PURE_ANNOTATION)\n  }\n  const callHelper: symbol = isBlock\n    ? getVNodeBlockHelper(context.inSSR, isComponent)\n    : getVNodeHelper(context.inSSR, isComponent)\n  push(helper(callHelper) + `(`, NewlineType.None, node)\n  genNodeList(\n    genNullableArgs([tag, props, children, patchFlagString, dynamicProps]),\n    context,\n  )\n  push(`)`)\n  if (isBlock) {\n    push(`)`)\n  }\n  if (directives) {\n    push(`, `)\n    genNode(directives, context)\n    push(`)`)\n  }\n}\n\nfunction genNullableArgs(args: any[]): CallExpression['arguments'] {\n  let i = args.length\n  while (i--) {\n    if (args[i] != null) break\n  }\n  return args.slice(0, i + 1).map(arg => arg || `null`)\n}\n\n// JavaScript\nfunction genCallExpression(node: CallExpression, context: CodegenContext) {\n  const { push, helper, pure } = context\n  const callee = isString(node.callee) ? node.callee : helper(node.callee)\n  if (pure) {\n    push(PURE_ANNOTATION)\n  }\n  push(callee + `(`, NewlineType.None, node)\n  genNodeList(node.arguments, context)\n  push(`)`)\n}\n\nfunction genObjectExpression(node: ObjectExpression, context: CodegenContext) {\n  const { push, indent, deindent, newline } = context\n  const { properties } = node\n  if (!properties.length) {\n    push(`{}`, NewlineType.None, node)\n    return\n  }\n  const multilines =\n    properties.length > 1 ||\n    ((!__BROWSER__ || __DEV__) &&\n      properties.some(p => p.value.type !== NodeTypes.SIMPLE_EXPRESSION))\n  push(multilines ? `{` : `{ `)\n  multilines && indent()\n  for (let i = 0; i < properties.length; i++) {\n    const { key, value } = properties[i]\n    // key\n    genExpressionAsPropertyKey(key, context)\n    push(`: `)\n    // value\n    genNode(value, context)\n    if (i < properties.length - 1) {\n      // will only reach this if it's multilines\n      push(`,`)\n      newline()\n    }\n  }\n  multilines && deindent()\n  push(multilines ? `}` : ` }`)\n}\n\nfunction genArrayExpression(node: ArrayExpression, context: CodegenContext) {\n  genNodeListAsArray(node.elements as CodegenNode[], context)\n}\n\nfunction genFunctionExpression(\n  node: FunctionExpression,\n  context: CodegenContext,\n) {\n  const { push, indent, deindent } = context\n  const { params, returns, body, newline, isSlot } = node\n  if (isSlot) {\n    // wrap slot functions with owner context\n    push(`_${helperNameMap[WITH_CTX]}(`)\n  }\n  push(`(`, NewlineType.None, node)\n  if (isArray(params)) {\n    genNodeList(params, context)\n  } else if (params) {\n    genNode(params, context)\n  }\n  push(`) => `)\n  if (newline || body) {\n    push(`{`)\n    indent()\n  }\n  if (returns) {\n    if (newline) {\n      push(`return `)\n    }\n    if (isArray(returns)) {\n      genNodeListAsArray(returns, context)\n    } else {\n      genNode(returns, context)\n    }\n  } else if (body) {\n    genNode(body, context)\n  }\n  if (newline || body) {\n    deindent()\n    push(`}`)\n  }\n  if (isSlot) {\n    if (__COMPAT__ && node.isNonScopedSlot) {\n      push(`, undefined, true`)\n    }\n    push(`)`)\n  }\n}\n\nfunction genConditionalExpression(\n  node: ConditionalExpression,\n  context: CodegenContext,\n) {\n  const { test, consequent, alternate, newline: needNewline } = node\n  const { push, indent, deindent, newline } = context\n  if (test.type === NodeTypes.SIMPLE_EXPRESSION) {\n    const needsParens = !isSimpleIdentifier(test.content)\n    needsParens && push(`(`)\n    genExpression(test, context)\n    needsParens && push(`)`)\n  } else {\n    push(`(`)\n    genNode(test, context)\n    push(`)`)\n  }\n  needNewline && indent()\n  context.indentLevel++\n  needNewline || push(` `)\n  push(`? `)\n  genNode(consequent, context)\n  context.indentLevel--\n  needNewline && newline()\n  needNewline || push(` `)\n  push(`: `)\n  const isNested = alternate.type === NodeTypes.JS_CONDITIONAL_EXPRESSION\n  if (!isNested) {\n    context.indentLevel++\n  }\n  genNode(alternate, context)\n  if (!isNested) {\n    context.indentLevel--\n  }\n  needNewline && deindent(true /* without newline */)\n}\n\nfunction genCacheExpression(node: CacheExpression, context: CodegenContext) {\n  const { push, helper, indent, deindent, newline } = context\n  const { needPauseTracking, needArraySpread } = node\n  if (needArraySpread) {\n    push(`[...(`)\n  }\n  push(`_cache[${node.index}] || (`)\n  if (needPauseTracking) {\n    indent()\n    push(`${helper(SET_BLOCK_TRACKING)}(-1`)\n    if (node.inVOnce) push(`, true`)\n    push(`),`)\n    newline()\n    push(`(`)\n  }\n  push(`_cache[${node.index}] = `)\n  genNode(node.value, context)\n  if (needPauseTracking) {\n    push(`).cacheIndex = ${node.index},`)\n    newline()\n    push(`${helper(SET_BLOCK_TRACKING)}(1),`)\n    newline()\n    push(`_cache[${node.index}]`)\n    deindent()\n  }\n  push(`)`)\n  if (needArraySpread) {\n    push(`)]`)\n  }\n}\n\nfunction genTemplateLiteral(node: TemplateLiteral, context: CodegenContext) {\n  const { push, indent, deindent } = context\n  push('`')\n  const l = node.elements.length\n  const multilines = l > 3\n  for (let i = 0; i < l; i++) {\n    const e = node.elements[i]\n    if (isString(e)) {\n      push(e.replace(/(`|\\$|\\\\)/g, '\\\\$1'), NewlineType.Unknown)\n    } else {\n      push('${')\n      if (multilines) indent()\n      genNode(e, context)\n      if (multilines) deindent()\n      push('}')\n    }\n  }\n  push('`')\n}\n\nfunction genIfStatement(node: IfStatement, context: CodegenContext) {\n  const { push, indent, deindent } = context\n  const { test, consequent, alternate } = node\n  push(`if (`)\n  genNode(test, context)\n  push(`) {`)\n  indent()\n  genNode(consequent, context)\n  deindent()\n  push(`}`)\n  if (alternate) {\n    push(` else `)\n    if (alternate.type === NodeTypes.JS_IF_STATEMENT) {\n      genIfStatement(alternate, context)\n    } else {\n      push(`{`)\n      indent()\n      genNode(alternate, context)\n      deindent()\n      push(`}`)\n    }\n  }\n}\n\nfunction genAssignmentExpression(\n  node: AssignmentExpression,\n  context: CodegenContext,\n) {\n  genNode(node.left, context)\n  context.push(` = `)\n  genNode(node.right, context)\n}\n\nfunction genSequenceExpression(\n  node: SequenceExpression,\n  context: CodegenContext,\n) {\n  context.push(`(`)\n  genNodeList(node.expressions, context)\n  context.push(`)`)\n}\n\nfunction genReturnStatement(\n  { returns }: ReturnStatement,\n  context: CodegenContext,\n) {\n  context.push(`return `)\n  if (isArray(returns)) {\n    genNodeListAsArray(returns, context)\n  } else {\n    genNode(returns, context)\n  }\n}\n"
  },
  {
    "path": "packages/compiler-core/src/compat/compatConfig.ts",
    "content": "import type { SourceLocation } from '../ast'\nimport type { CompilerError } from '../errors'\nimport type { MergedParserOptions } from '../parser'\nimport type { TransformContext } from '../transform'\n\nexport type CompilerCompatConfig = Partial<\n  Record<CompilerDeprecationTypes, boolean | 'suppress-warning'>\n> & {\n  MODE?: 2 | 3\n}\n\nexport interface CompilerCompatOptions {\n  compatConfig?: CompilerCompatConfig\n}\n\nexport enum CompilerDeprecationTypes {\n  COMPILER_IS_ON_ELEMENT = 'COMPILER_IS_ON_ELEMENT',\n  COMPILER_V_BIND_SYNC = 'COMPILER_V_BIND_SYNC',\n  COMPILER_V_BIND_OBJECT_ORDER = 'COMPILER_V_BIND_OBJECT_ORDER',\n  COMPILER_V_ON_NATIVE = 'COMPILER_V_ON_NATIVE',\n  COMPILER_V_IF_V_FOR_PRECEDENCE = 'COMPILER_V_IF_V_FOR_PRECEDENCE',\n  COMPILER_NATIVE_TEMPLATE = 'COMPILER_NATIVE_TEMPLATE',\n  COMPILER_INLINE_TEMPLATE = 'COMPILER_INLINE_TEMPLATE',\n  COMPILER_FILTERS = 'COMPILER_FILTERS',\n}\n\ntype DeprecationData = {\n  message: string | ((...args: any[]) => string)\n  link?: string\n}\n\nconst deprecationData: Record<CompilerDeprecationTypes, DeprecationData> = {\n  [CompilerDeprecationTypes.COMPILER_IS_ON_ELEMENT]: {\n    message:\n      `Platform-native elements with \"is\" prop will no longer be ` +\n      `treated as components in Vue 3 unless the \"is\" value is explicitly ` +\n      `prefixed with \"vue:\".`,\n    link: `https://v3-migration.vuejs.org/breaking-changes/custom-elements-interop.html`,\n  },\n\n  [CompilerDeprecationTypes.COMPILER_V_BIND_SYNC]: {\n    message: key =>\n      `.sync modifier for v-bind has been removed. Use v-model with ` +\n      `argument instead. \\`v-bind:${key}.sync\\` should be changed to ` +\n      `\\`v-model:${key}\\`.`,\n    link: `https://v3-migration.vuejs.org/breaking-changes/v-model.html`,\n  },\n\n  [CompilerDeprecationTypes.COMPILER_V_BIND_OBJECT_ORDER]: {\n    message:\n      `v-bind=\"obj\" usage is now order sensitive and behaves like JavaScript ` +\n      `object spread: it will now overwrite an existing non-mergeable attribute ` +\n      `that appears before v-bind in the case of conflict. ` +\n      `To retain 2.x behavior, move v-bind to make it the first attribute. ` +\n      `You can also suppress this warning if the usage is intended.`,\n    link: `https://v3-migration.vuejs.org/breaking-changes/v-bind.html`,\n  },\n\n  [CompilerDeprecationTypes.COMPILER_V_ON_NATIVE]: {\n    message: `.native modifier for v-on has been removed as is no longer necessary.`,\n    link: `https://v3-migration.vuejs.org/breaking-changes/v-on-native-modifier-removed.html`,\n  },\n\n  [CompilerDeprecationTypes.COMPILER_V_IF_V_FOR_PRECEDENCE]: {\n    message:\n      `v-if / v-for precedence when used on the same element has changed ` +\n      `in Vue 3: v-if now takes higher precedence and will no longer have ` +\n      `access to v-for scope variables. It is best to avoid the ambiguity ` +\n      `with <template> tags or use a computed property that filters v-for ` +\n      `data source.`,\n    link: `https://v3-migration.vuejs.org/breaking-changes/v-if-v-for.html`,\n  },\n\n  [CompilerDeprecationTypes.COMPILER_NATIVE_TEMPLATE]: {\n    message:\n      `<template> with no special directives will render as a native template ` +\n      `element instead of its inner content in Vue 3.`,\n  },\n\n  [CompilerDeprecationTypes.COMPILER_INLINE_TEMPLATE]: {\n    message: `\"inline-template\" has been removed in Vue 3.`,\n    link: `https://v3-migration.vuejs.org/breaking-changes/inline-template-attribute.html`,\n  },\n\n  [CompilerDeprecationTypes.COMPILER_FILTERS]: {\n    message:\n      `filters have been removed in Vue 3. ` +\n      `The \"|\" symbol will be treated as native JavaScript bitwise OR operator. ` +\n      `Use method calls or computed properties instead.`,\n    link: `https://v3-migration.vuejs.org/breaking-changes/filters.html`,\n  },\n}\n\nfunction getCompatValue(\n  key: CompilerDeprecationTypes | 'MODE',\n  { compatConfig }: MergedParserOptions | TransformContext,\n) {\n  const value = compatConfig && compatConfig[key]\n  if (key === 'MODE') {\n    return value || 3 // compiler defaults to v3 behavior\n  } else {\n    return value\n  }\n}\n\nexport function isCompatEnabled(\n  key: CompilerDeprecationTypes,\n  context: MergedParserOptions | TransformContext,\n): boolean {\n  const mode = getCompatValue('MODE', context)\n  const value = getCompatValue(key, context)\n  // in v3 mode, only enable if explicitly set to true\n  // otherwise enable for any non-false value\n  return mode === 3 ? value === true : value !== false\n}\n\nexport function checkCompatEnabled(\n  key: CompilerDeprecationTypes,\n  context: MergedParserOptions | TransformContext,\n  loc: SourceLocation | null,\n  ...args: any[]\n): boolean {\n  const enabled = isCompatEnabled(key, context)\n  if (__DEV__ && enabled) {\n    warnDeprecation(key, context, loc, ...args)\n  }\n  return enabled\n}\n\nexport function warnDeprecation(\n  key: CompilerDeprecationTypes,\n  context: MergedParserOptions | TransformContext,\n  loc: SourceLocation | null,\n  ...args: any[]\n): void {\n  const val = getCompatValue(key, context)\n  if (val === 'suppress-warning') {\n    return\n  }\n  const { message, link } = deprecationData[key]\n  const msg = `(deprecation ${key}) ${\n    typeof message === 'function' ? message(...args) : message\n  }${link ? `\\n  Details: ${link}` : ``}`\n\n  const err = new SyntaxError(msg) as CompilerError\n  err.code = key\n  if (loc) err.loc = loc\n  context.onWarn(err)\n}\n"
  },
  {
    "path": "packages/compiler-core/src/compat/transformFilter.ts",
    "content": "import { RESOLVE_FILTER } from '../runtimeHelpers'\nimport {\n  type AttributeNode,\n  type DirectiveNode,\n  type ExpressionNode,\n  NodeTypes,\n  type SimpleExpressionNode,\n} from '../ast'\nimport {\n  CompilerDeprecationTypes,\n  isCompatEnabled,\n  warnDeprecation,\n} from './compatConfig'\nimport type { NodeTransform, TransformContext } from '../transform'\nimport { toValidAssetId } from '../utils'\n\nconst validDivisionCharRE = /[\\w).+\\-_$\\]]/\n\nexport const transformFilter: NodeTransform = (node, context) => {\n  if (!isCompatEnabled(CompilerDeprecationTypes.COMPILER_FILTERS, context)) {\n    return\n  }\n\n  if (node.type === NodeTypes.INTERPOLATION) {\n    // filter rewrite is applied before expression transform so only\n    // simple expressions are possible at this stage\n    rewriteFilter(node.content, context)\n  } else if (node.type === NodeTypes.ELEMENT) {\n    node.props.forEach((prop: AttributeNode | DirectiveNode) => {\n      if (\n        prop.type === NodeTypes.DIRECTIVE &&\n        prop.name !== 'for' &&\n        prop.exp\n      ) {\n        rewriteFilter(prop.exp, context)\n      }\n    })\n  }\n}\n\nfunction rewriteFilter(node: ExpressionNode, context: TransformContext) {\n  if (node.type === NodeTypes.SIMPLE_EXPRESSION) {\n    parseFilter(node, context)\n  } else {\n    for (let i = 0; i < node.children.length; i++) {\n      const child = node.children[i]\n      if (typeof child !== 'object') continue\n      if (child.type === NodeTypes.SIMPLE_EXPRESSION) {\n        parseFilter(child, context)\n      } else if (child.type === NodeTypes.COMPOUND_EXPRESSION) {\n        rewriteFilter(node, context)\n      } else if (child.type === NodeTypes.INTERPOLATION) {\n        rewriteFilter(child.content, context)\n      }\n    }\n  }\n}\n\nfunction parseFilter(node: SimpleExpressionNode, context: TransformContext) {\n  const exp = node.content\n  let inSingle = false\n  let inDouble = false\n  let inTemplateString = false\n  let inRegex = false\n  let curly = 0\n  let square = 0\n  let paren = 0\n  let lastFilterIndex = 0\n  let c,\n    prev,\n    i: number,\n    expression,\n    filters: string[] = []\n\n  for (i = 0; i < exp.length; i++) {\n    prev = c\n    c = exp.charCodeAt(i)\n    if (inSingle) {\n      if (c === 0x27 && prev !== 0x5c) inSingle = false\n    } else if (inDouble) {\n      if (c === 0x22 && prev !== 0x5c) inDouble = false\n    } else if (inTemplateString) {\n      if (c === 0x60 && prev !== 0x5c) inTemplateString = false\n    } else if (inRegex) {\n      if (c === 0x2f && prev !== 0x5c) inRegex = false\n    } else if (\n      c === 0x7c && // pipe\n      exp.charCodeAt(i + 1) !== 0x7c &&\n      exp.charCodeAt(i - 1) !== 0x7c &&\n      !curly &&\n      !square &&\n      !paren\n    ) {\n      if (expression === undefined) {\n        // first filter, end of expression\n        lastFilterIndex = i + 1\n        expression = exp.slice(0, i).trim()\n      } else {\n        pushFilter()\n      }\n    } else {\n      switch (c) {\n        case 0x22:\n          inDouble = true\n          break // \"\n        case 0x27:\n          inSingle = true\n          break // '\n        case 0x60:\n          inTemplateString = true\n          break // `\n        case 0x28:\n          paren++\n          break // (\n        case 0x29:\n          paren--\n          break // )\n        case 0x5b:\n          square++\n          break // [\n        case 0x5d:\n          square--\n          break // ]\n        case 0x7b:\n          curly++\n          break // {\n        case 0x7d:\n          curly--\n          break // }\n      }\n      if (c === 0x2f) {\n        // /\n        let j = i - 1\n        let p\n        // find first non-whitespace prev char\n        for (; j >= 0; j--) {\n          p = exp.charAt(j)\n          if (p !== ' ') break\n        }\n        if (!p || !validDivisionCharRE.test(p)) {\n          inRegex = true\n        }\n      }\n    }\n  }\n\n  if (expression === undefined) {\n    expression = exp.slice(0, i).trim()\n  } else if (lastFilterIndex !== 0) {\n    pushFilter()\n  }\n\n  function pushFilter() {\n    filters.push(exp.slice(lastFilterIndex, i).trim())\n    lastFilterIndex = i + 1\n  }\n\n  if (filters.length) {\n    __DEV__ &&\n      warnDeprecation(\n        CompilerDeprecationTypes.COMPILER_FILTERS,\n        context,\n        node.loc,\n      )\n    for (i = 0; i < filters.length; i++) {\n      expression = wrapFilter(expression, filters[i], context)\n    }\n    node.content = expression\n    // reset ast since the content is replaced\n    node.ast = undefined\n  }\n}\n\nfunction wrapFilter(\n  exp: string,\n  filter: string,\n  context: TransformContext,\n): string {\n  context.helper(RESOLVE_FILTER)\n  const i = filter.indexOf('(')\n  if (i < 0) {\n    context.filters!.add(filter)\n    return `${toValidAssetId(filter, 'filter')}(${exp})`\n  } else {\n    const name = filter.slice(0, i)\n    const args = filter.slice(i + 1)\n    context.filters!.add(name)\n    return `${toValidAssetId(name, 'filter')}(${exp}${\n      args !== ')' ? ',' + args : args\n    }`\n  }\n}\n"
  },
  {
    "path": "packages/compiler-core/src/compile.ts",
    "content": "import type { CompilerOptions } from './options'\nimport { baseParse } from './parser'\nimport {\n  type DirectiveTransform,\n  type NodeTransform,\n  transform,\n} from './transform'\nimport { type CodegenResult, generate } from './codegen'\nimport type { RootNode } from './ast'\nimport { extend, isString } from '@vue/shared'\nimport { transformIf } from './transforms/vIf'\nimport { transformFor } from './transforms/vFor'\nimport { transformExpression } from './transforms/transformExpression'\nimport { transformSlotOutlet } from './transforms/transformSlotOutlet'\nimport { transformElement } from './transforms/transformElement'\nimport { transformOn } from './transforms/vOn'\nimport { transformBind } from './transforms/vBind'\nimport { trackSlotScopes, trackVForSlotScopes } from './transforms/vSlot'\nimport { transformText } from './transforms/transformText'\nimport { transformOnce } from './transforms/vOnce'\nimport { transformModel } from './transforms/vModel'\nimport { transformFilter } from './compat/transformFilter'\nimport { ErrorCodes, createCompilerError, defaultOnError } from './errors'\nimport { transformMemo } from './transforms/vMemo'\nimport { transformVBindShorthand } from './transforms/transformVBindShorthand'\n\nexport type TransformPreset = [\n  NodeTransform[],\n  Record<string, DirectiveTransform>,\n]\n\nexport function getBaseTransformPreset(\n  prefixIdentifiers?: boolean,\n): TransformPreset {\n  return [\n    [\n      transformVBindShorthand,\n      transformOnce,\n      transformIf,\n      transformMemo,\n      transformFor,\n      ...(__COMPAT__ ? [transformFilter] : []),\n      ...(!__BROWSER__ && prefixIdentifiers\n        ? [\n            // order is important\n            trackVForSlotScopes,\n            transformExpression,\n          ]\n        : __BROWSER__ && __DEV__\n          ? [transformExpression]\n          : []),\n      transformSlotOutlet,\n      transformElement,\n      trackSlotScopes,\n      transformText,\n    ],\n    {\n      on: transformOn,\n      bind: transformBind,\n      model: transformModel,\n    },\n  ]\n}\n\n// we name it `baseCompile` so that higher order compilers like\n// @vue/compiler-dom can export `compile` while re-exporting everything else.\nexport function baseCompile(\n  source: string | RootNode,\n  options: CompilerOptions = {},\n): CodegenResult {\n  const onError = options.onError || defaultOnError\n  const isModuleMode = options.mode === 'module'\n  /* v8 ignore start */\n  if (__BROWSER__) {\n    if (options.prefixIdentifiers === true) {\n      onError(createCompilerError(ErrorCodes.X_PREFIX_ID_NOT_SUPPORTED))\n    } else if (isModuleMode) {\n      onError(createCompilerError(ErrorCodes.X_MODULE_MODE_NOT_SUPPORTED))\n    }\n  }\n  /* v8 ignore stop */\n\n  const prefixIdentifiers =\n    !__BROWSER__ && (options.prefixIdentifiers === true || isModuleMode)\n  if (!prefixIdentifiers && options.cacheHandlers) {\n    onError(createCompilerError(ErrorCodes.X_CACHE_HANDLER_NOT_SUPPORTED))\n  }\n  if (options.scopeId && !isModuleMode) {\n    onError(createCompilerError(ErrorCodes.X_SCOPE_ID_NOT_SUPPORTED))\n  }\n\n  const resolvedOptions = extend({}, options, {\n    prefixIdentifiers,\n  })\n  const ast = isString(source) ? baseParse(source, resolvedOptions) : source\n  const [nodeTransforms, directiveTransforms] =\n    getBaseTransformPreset(prefixIdentifiers)\n\n  if (!__BROWSER__ && options.isTS) {\n    const { expressionPlugins } = options\n    if (!expressionPlugins || !expressionPlugins.includes('typescript')) {\n      options.expressionPlugins = [...(expressionPlugins || []), 'typescript']\n    }\n  }\n\n  transform(\n    ast,\n    extend({}, resolvedOptions, {\n      nodeTransforms: [\n        ...nodeTransforms,\n        ...(options.nodeTransforms || []), // user transforms\n      ],\n      directiveTransforms: extend(\n        {},\n        directiveTransforms,\n        options.directiveTransforms || {}, // user transforms\n      ),\n    }),\n  )\n\n  return generate(ast, resolvedOptions)\n}\n"
  },
  {
    "path": "packages/compiler-core/src/errors.ts",
    "content": "import type { SourceLocation } from './ast'\n\nexport interface CompilerError extends SyntaxError {\n  code: number | string\n  loc?: SourceLocation\n}\n\nexport interface CoreCompilerError extends CompilerError {\n  code: ErrorCodes\n}\n\nexport function defaultOnError(error: CompilerError): never {\n  throw error\n}\n\nexport function defaultOnWarn(msg: CompilerError): void {\n  __DEV__ && console.warn(`[Vue warn] ${msg.message}`)\n}\n\ntype InferCompilerError<T> = T extends ErrorCodes\n  ? CoreCompilerError\n  : CompilerError\n\nexport function createCompilerError<T extends number>(\n  code: T,\n  loc?: SourceLocation,\n  messages?: { [code: number]: string },\n  additionalMessage?: string,\n): InferCompilerError<T> {\n  const msg =\n    __DEV__ || !__BROWSER__\n      ? (messages || errorMessages)[code] + (additionalMessage || ``)\n      : `https://vuejs.org/error-reference/#compiler-${code}`\n  const error = new SyntaxError(String(msg)) as InferCompilerError<T>\n  error.code = code\n  error.loc = loc\n  return error\n}\n\nexport enum ErrorCodes {\n  // parse errors\n  ABRUPT_CLOSING_OF_EMPTY_COMMENT,\n  CDATA_IN_HTML_CONTENT,\n  DUPLICATE_ATTRIBUTE,\n  END_TAG_WITH_ATTRIBUTES,\n  END_TAG_WITH_TRAILING_SOLIDUS,\n  EOF_BEFORE_TAG_NAME,\n  EOF_IN_CDATA,\n  EOF_IN_COMMENT,\n  EOF_IN_SCRIPT_HTML_COMMENT_LIKE_TEXT,\n  EOF_IN_TAG,\n  INCORRECTLY_CLOSED_COMMENT,\n  INCORRECTLY_OPENED_COMMENT,\n  INVALID_FIRST_CHARACTER_OF_TAG_NAME,\n  MISSING_ATTRIBUTE_VALUE,\n  MISSING_END_TAG_NAME,\n  MISSING_WHITESPACE_BETWEEN_ATTRIBUTES,\n  NESTED_COMMENT,\n  UNEXPECTED_CHARACTER_IN_ATTRIBUTE_NAME,\n  UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_VALUE,\n  UNEXPECTED_EQUALS_SIGN_BEFORE_ATTRIBUTE_NAME,\n  UNEXPECTED_NULL_CHARACTER,\n  UNEXPECTED_QUESTION_MARK_INSTEAD_OF_TAG_NAME,\n  UNEXPECTED_SOLIDUS_IN_TAG,\n\n  // Vue-specific parse errors\n  X_INVALID_END_TAG,\n  X_MISSING_END_TAG,\n  X_MISSING_INTERPOLATION_END,\n  X_MISSING_DIRECTIVE_NAME,\n  X_MISSING_DYNAMIC_DIRECTIVE_ARGUMENT_END,\n\n  // transform errors\n  X_V_IF_NO_EXPRESSION,\n  X_V_IF_SAME_KEY,\n  X_V_ELSE_NO_ADJACENT_IF,\n  X_V_FOR_NO_EXPRESSION,\n  X_V_FOR_MALFORMED_EXPRESSION,\n  X_V_FOR_TEMPLATE_KEY_PLACEMENT,\n  X_V_BIND_NO_EXPRESSION,\n  X_V_ON_NO_EXPRESSION,\n  X_V_SLOT_UNEXPECTED_DIRECTIVE_ON_SLOT_OUTLET,\n  X_V_SLOT_MIXED_SLOT_USAGE,\n  X_V_SLOT_DUPLICATE_SLOT_NAMES,\n  X_V_SLOT_EXTRANEOUS_DEFAULT_SLOT_CHILDREN,\n  X_V_SLOT_MISPLACED,\n  X_V_MODEL_NO_EXPRESSION,\n  X_V_MODEL_MALFORMED_EXPRESSION,\n  X_V_MODEL_ON_SCOPE_VARIABLE,\n  X_V_MODEL_ON_PROPS,\n  X_V_MODEL_ON_CONST,\n  X_INVALID_EXPRESSION,\n  X_KEEP_ALIVE_INVALID_CHILDREN,\n\n  // generic errors\n  X_PREFIX_ID_NOT_SUPPORTED,\n  X_MODULE_MODE_NOT_SUPPORTED,\n  X_CACHE_HANDLER_NOT_SUPPORTED,\n  X_SCOPE_ID_NOT_SUPPORTED,\n  X_VNODE_HOOKS,\n\n  // placed here to preserve order for the current minor\n  // TODO adjust order in 3.5\n  X_V_BIND_INVALID_SAME_NAME_ARGUMENT,\n\n  // Special value for higher-order compilers to pick up the last code\n  // to avoid collision of error codes. This should always be kept as the last\n  // item.\n  __EXTEND_POINT__,\n}\n\nexport const errorMessages: Record<ErrorCodes, string> = {\n  // parse errors\n  [ErrorCodes.ABRUPT_CLOSING_OF_EMPTY_COMMENT]: 'Illegal comment.',\n  [ErrorCodes.CDATA_IN_HTML_CONTENT]:\n    'CDATA section is allowed only in XML context.',\n  [ErrorCodes.DUPLICATE_ATTRIBUTE]: 'Duplicate attribute.',\n  [ErrorCodes.END_TAG_WITH_ATTRIBUTES]: 'End tag cannot have attributes.',\n  [ErrorCodes.END_TAG_WITH_TRAILING_SOLIDUS]: \"Illegal '/' in tags.\",\n  [ErrorCodes.EOF_BEFORE_TAG_NAME]: 'Unexpected EOF in tag.',\n  [ErrorCodes.EOF_IN_CDATA]: 'Unexpected EOF in CDATA section.',\n  [ErrorCodes.EOF_IN_COMMENT]: 'Unexpected EOF in comment.',\n  [ErrorCodes.EOF_IN_SCRIPT_HTML_COMMENT_LIKE_TEXT]:\n    'Unexpected EOF in script.',\n  [ErrorCodes.EOF_IN_TAG]: 'Unexpected EOF in tag.',\n  [ErrorCodes.INCORRECTLY_CLOSED_COMMENT]: 'Incorrectly closed comment.',\n  [ErrorCodes.INCORRECTLY_OPENED_COMMENT]: 'Incorrectly opened comment.',\n  [ErrorCodes.INVALID_FIRST_CHARACTER_OF_TAG_NAME]:\n    \"Illegal tag name. Use '&lt;' to print '<'.\",\n  [ErrorCodes.MISSING_ATTRIBUTE_VALUE]: 'Attribute value was expected.',\n  [ErrorCodes.MISSING_END_TAG_NAME]: 'End tag name was expected.',\n  [ErrorCodes.MISSING_WHITESPACE_BETWEEN_ATTRIBUTES]:\n    'Whitespace was expected.',\n  [ErrorCodes.NESTED_COMMENT]: \"Unexpected '<!--' in comment.\",\n  [ErrorCodes.UNEXPECTED_CHARACTER_IN_ATTRIBUTE_NAME]:\n    'Attribute name cannot contain U+0022 (\"), U+0027 (\\'), and U+003C (<).',\n  [ErrorCodes.UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_VALUE]:\n    'Unquoted attribute value cannot contain U+0022 (\"), U+0027 (\\'), U+003C (<), U+003D (=), and U+0060 (`).',\n  [ErrorCodes.UNEXPECTED_EQUALS_SIGN_BEFORE_ATTRIBUTE_NAME]:\n    \"Attribute name cannot start with '='.\",\n  [ErrorCodes.UNEXPECTED_QUESTION_MARK_INSTEAD_OF_TAG_NAME]:\n    \"'<?' is allowed only in XML context.\",\n  [ErrorCodes.UNEXPECTED_NULL_CHARACTER]: `Unexpected null character.`,\n  [ErrorCodes.UNEXPECTED_SOLIDUS_IN_TAG]: \"Illegal '/' in tags.\",\n\n  // Vue-specific parse errors\n  [ErrorCodes.X_INVALID_END_TAG]: 'Invalid end tag.',\n  [ErrorCodes.X_MISSING_END_TAG]: 'Element is missing end tag.',\n  [ErrorCodes.X_MISSING_INTERPOLATION_END]:\n    'Interpolation end sign was not found.',\n  [ErrorCodes.X_MISSING_DYNAMIC_DIRECTIVE_ARGUMENT_END]:\n    'End bracket for dynamic directive argument was not found. ' +\n    'Note that dynamic directive argument cannot contain spaces.',\n  [ErrorCodes.X_MISSING_DIRECTIVE_NAME]: 'Legal directive name was expected.',\n\n  // transform errors\n  [ErrorCodes.X_V_IF_NO_EXPRESSION]: `v-if/v-else-if is missing expression.`,\n  [ErrorCodes.X_V_IF_SAME_KEY]: `v-if/else branches must use unique keys.`,\n  [ErrorCodes.X_V_ELSE_NO_ADJACENT_IF]: `v-else/v-else-if has no adjacent v-if or v-else-if.`,\n  [ErrorCodes.X_V_FOR_NO_EXPRESSION]: `v-for is missing expression.`,\n  [ErrorCodes.X_V_FOR_MALFORMED_EXPRESSION]: `v-for has invalid expression.`,\n  [ErrorCodes.X_V_FOR_TEMPLATE_KEY_PLACEMENT]: `<template v-for> key should be placed on the <template> tag.`,\n  [ErrorCodes.X_V_BIND_NO_EXPRESSION]: `v-bind is missing expression.`,\n  [ErrorCodes.X_V_BIND_INVALID_SAME_NAME_ARGUMENT]: `v-bind with same-name shorthand only allows static argument.`,\n  [ErrorCodes.X_V_ON_NO_EXPRESSION]: `v-on is missing expression.`,\n  [ErrorCodes.X_V_SLOT_UNEXPECTED_DIRECTIVE_ON_SLOT_OUTLET]: `Unexpected custom directive on <slot> outlet.`,\n  [ErrorCodes.X_V_SLOT_MIXED_SLOT_USAGE]:\n    `Mixed v-slot usage on both the component and nested <template>. ` +\n    `When there are multiple named slots, all slots should use <template> ` +\n    `syntax to avoid scope ambiguity.`,\n  [ErrorCodes.X_V_SLOT_DUPLICATE_SLOT_NAMES]: `Duplicate slot names found. `,\n  [ErrorCodes.X_V_SLOT_EXTRANEOUS_DEFAULT_SLOT_CHILDREN]:\n    `Extraneous children found when component already has explicitly named ` +\n    `default slot. These children will be ignored.`,\n  [ErrorCodes.X_V_SLOT_MISPLACED]: `v-slot can only be used on components or <template> tags.`,\n  [ErrorCodes.X_V_MODEL_NO_EXPRESSION]: `v-model is missing expression.`,\n  [ErrorCodes.X_V_MODEL_MALFORMED_EXPRESSION]: `v-model value must be a valid JavaScript member expression.`,\n  [ErrorCodes.X_V_MODEL_ON_SCOPE_VARIABLE]: `v-model cannot be used on v-for or v-slot scope variables because they are not writable.`,\n  [ErrorCodes.X_V_MODEL_ON_PROPS]: `v-model cannot be used on a prop, because local prop bindings are not writable.\\nUse a v-bind binding combined with a v-on listener that emits update:x event instead.`,\n  [ErrorCodes.X_V_MODEL_ON_CONST]: `v-model cannot be used on a const binding because it is not writable.`,\n  [ErrorCodes.X_INVALID_EXPRESSION]: `Error parsing JavaScript expression: `,\n  [ErrorCodes.X_KEEP_ALIVE_INVALID_CHILDREN]: `<KeepAlive> expects exactly one child component.`,\n  [ErrorCodes.X_VNODE_HOOKS]: `@vnode-* hooks in templates are no longer supported. Use the vue: prefix instead. For example, @vnode-mounted should be changed to @vue:mounted. @vnode-* hooks support has been removed in 3.4.`,\n\n  // generic errors\n  [ErrorCodes.X_PREFIX_ID_NOT_SUPPORTED]: `\"prefixIdentifiers\" option is not supported in this build of compiler.`,\n  [ErrorCodes.X_MODULE_MODE_NOT_SUPPORTED]: `ES module mode is not supported in this build of compiler.`,\n  [ErrorCodes.X_CACHE_HANDLER_NOT_SUPPORTED]: `\"cacheHandlers\" option is only supported when the \"prefixIdentifiers\" option is enabled.`,\n  [ErrorCodes.X_SCOPE_ID_NOT_SUPPORTED]: `\"scopeId\" option is only supported in module mode.`,\n\n  // just to fulfill types\n  [ErrorCodes.__EXTEND_POINT__]: ``,\n}\n"
  },
  {
    "path": "packages/compiler-core/src/index.ts",
    "content": "export { baseCompile } from './compile'\n\n// Also expose lower level APIs & types\nexport {\n  type CompilerOptions,\n  type ParserOptions,\n  type TransformOptions,\n  type CodegenOptions,\n  type HoistTransform,\n  type BindingMetadata,\n  BindingTypes,\n} from './options'\nexport { baseParse } from './parser'\nexport {\n  transform,\n  type TransformContext,\n  createTransformContext,\n  traverseNode,\n  createStructuralDirectiveTransform,\n  type NodeTransform,\n  type StructuralDirectiveTransform,\n  type DirectiveTransform,\n} from './transform'\nexport {\n  generate,\n  type CodegenContext,\n  type CodegenResult,\n  type CodegenSourceMapGenerator,\n  type RawSourceMap,\n} from './codegen'\nexport {\n  ErrorCodes,\n  errorMessages,\n  createCompilerError,\n  type CoreCompilerError,\n  type CompilerError,\n} from './errors'\n\nexport * from './ast'\nexport * from './utils'\nexport * from './babelUtils'\nexport * from './runtimeHelpers'\n\nexport { getBaseTransformPreset, type TransformPreset } from './compile'\nexport { transformModel } from './transforms/vModel'\nexport { transformOn } from './transforms/vOn'\nexport { transformBind } from './transforms/vBind'\nexport { noopDirectiveTransform } from './transforms/noopDirectiveTransform'\nexport { processIf } from './transforms/vIf'\nexport { processFor, createForLoopParams } from './transforms/vFor'\nexport {\n  transformExpression,\n  processExpression,\n  stringifyExpression,\n} from './transforms/transformExpression'\nexport {\n  buildSlots,\n  type SlotFnBuilder,\n  trackVForSlotScopes,\n  trackSlotScopes,\n} from './transforms/vSlot'\nexport {\n  transformElement,\n  resolveComponentType,\n  buildProps,\n  buildDirectiveArgs,\n  type PropsExpression,\n} from './transforms/transformElement'\nexport { transformVBindShorthand } from './transforms/transformVBindShorthand'\nexport { processSlotOutlet } from './transforms/transformSlotOutlet'\nexport { getConstantType } from './transforms/cacheStatic'\nexport { generateCodeFrame } from '@vue/shared'\n\n// v2 compat only\nexport {\n  checkCompatEnabled,\n  warnDeprecation,\n  CompilerDeprecationTypes,\n} from './compat/compatConfig'\n"
  },
  {
    "path": "packages/compiler-core/src/options.ts",
    "content": "import type {\n  ElementNode,\n  Namespace,\n  Namespaces,\n  ParentNode,\n  TemplateChildNode,\n} from './ast'\nimport type { CompilerError } from './errors'\nimport type {\n  DirectiveTransform,\n  NodeTransform,\n  TransformContext,\n} from './transform'\nimport type { CompilerCompatOptions } from './compat/compatConfig'\nimport type { ParserPlugin } from '@babel/parser'\n\nexport interface ErrorHandlingOptions {\n  onWarn?: (warning: CompilerError) => void\n  onError?: (error: CompilerError) => void\n}\n\nexport interface ParserOptions\n  extends ErrorHandlingOptions, CompilerCompatOptions {\n  /**\n   * Base mode is platform agnostic and only parses HTML-like template syntax,\n   * treating all tags the same way. Specific tag parsing behavior can be\n   * configured by higher-level compilers.\n   *\n   * HTML mode adds additional logic for handling special parsing behavior in\n   * `<script>`, `<style>`,`<title>` and `<textarea>`.\n   * The logic is handled inside compiler-core for efficiency.\n   *\n   * SFC mode treats content of all root-level tags except `<template>` as plain\n   * text.\n   */\n  parseMode?: 'base' | 'html' | 'sfc'\n  /**\n   * Specify the root namespace to use when parsing a template.\n   * Defaults to `Namespaces.HTML` (0).\n   */\n  ns?: Namespaces\n  /**\n   * e.g. platform native elements, e.g. `<div>` for browsers\n   */\n  isNativeTag?: (tag: string) => boolean\n  /**\n   * e.g. native elements that can self-close, e.g. `<img>`, `<br>`, `<hr>`\n   */\n  isVoidTag?: (tag: string) => boolean\n  /**\n   * e.g. elements that should preserve whitespace inside, e.g. `<pre>`\n   */\n  isPreTag?: (tag: string) => boolean\n  /**\n   * Elements that should ignore the first newline token per parinsg spec\n   * e.g. `<textarea>` and `<pre>`\n   */\n  isIgnoreNewlineTag?: (tag: string) => boolean\n  /**\n   * Platform-specific built-in components e.g. `<Transition>`\n   */\n  isBuiltInComponent?: (tag: string) => symbol | void\n  /**\n   * Separate option for end users to extend the native elements list\n   */\n  isCustomElement?: (tag: string) => boolean | void\n  /**\n   * Get tag namespace\n   */\n  getNamespace?: (\n    tag: string,\n    parent: ElementNode | undefined,\n    rootNamespace: Namespace,\n  ) => Namespace\n  /**\n   * @default ['{{', '}}']\n   */\n  delimiters?: [string, string]\n  /**\n   * Whitespace handling strategy\n   * @default 'condense'\n   */\n  whitespace?: 'preserve' | 'condense'\n  /**\n   * Only used for DOM compilers that runs in the browser.\n   * In non-browser builds, this option is ignored.\n   */\n  decodeEntities?: (rawText: string, asAttr: boolean) => string\n  /**\n   * Whether to keep comments in the templates AST.\n   * This defaults to `true` in development and `false` in production builds.\n   */\n  comments?: boolean\n  /**\n   * Parse JavaScript expressions with Babel.\n   * @default false\n   */\n  prefixIdentifiers?: boolean\n  /**\n   * A list of parser plugins to enable for `@babel/parser`, which is used to\n   * parse expressions in bindings and interpolations.\n   * https://babeljs.io/docs/en/next/babel-parser#plugins\n   */\n  expressionPlugins?: ParserPlugin[]\n}\n\nexport type HoistTransform = (\n  children: TemplateChildNode[],\n  context: TransformContext,\n  parent: ParentNode,\n) => void\n\nexport enum BindingTypes {\n  /**\n   * returned from data()\n   */\n  DATA = 'data',\n  /**\n   * declared as a prop\n   */\n  PROPS = 'props',\n  /**\n   * a local alias of a `<script setup>` destructured prop.\n   * the original is stored in __propsAliases of the bindingMetadata object.\n   */\n  PROPS_ALIASED = 'props-aliased',\n  /**\n   * a let binding (may or may not be a ref)\n   */\n  SETUP_LET = 'setup-let',\n  /**\n   * a const binding that can never be a ref.\n   * these bindings don't need `unref()` calls when processed in inlined\n   * template expressions.\n   */\n  SETUP_CONST = 'setup-const',\n  /**\n   * a const binding that does not need `unref()`, but may be mutated.\n   */\n  SETUP_REACTIVE_CONST = 'setup-reactive-const',\n  /**\n   * a const binding that may be a ref.\n   */\n  SETUP_MAYBE_REF = 'setup-maybe-ref',\n  /**\n   * bindings that are guaranteed to be refs\n   */\n  SETUP_REF = 'setup-ref',\n  /**\n   * declared by other options, e.g. computed, inject\n   */\n  OPTIONS = 'options',\n  /**\n   * a literal constant, e.g. 'foo', 1, true\n   */\n  LITERAL_CONST = 'literal-const',\n}\n\nexport type BindingMetadata = {\n  [key: string]: BindingTypes | undefined\n} & {\n  __isScriptSetup?: boolean\n  __propsAliases?: Record<string, string>\n}\n\ninterface SharedTransformCodegenOptions {\n  /**\n   * Transform expressions like {{ foo }} to `_ctx.foo`.\n   * If this option is false, the generated code will be wrapped in a\n   * `with (this) { ... }` block.\n   * - This is force-enabled in module mode, since modules are by default strict\n   * and cannot use `with`\n   * @default mode === 'module'\n   */\n  prefixIdentifiers?: boolean\n  /**\n   * Control whether generate SSR-optimized render functions instead.\n   * The resulting function must be attached to the component via the\n   * `ssrRender` option instead of `render`.\n   *\n   * When compiler generates code for SSR's fallback branch, we need to set it to false:\n   *  - context.ssr = false\n   *\n   * see `subTransform` in `ssrTransformComponent.ts`\n   */\n  ssr?: boolean\n  /**\n   * Indicates whether the compiler generates code for SSR,\n   * it is always true when generating code for SSR,\n   * regardless of whether we are generating code for SSR's fallback branch,\n   * this means that when the compiler generates code for SSR's fallback branch:\n   *  - context.ssr = false\n   *  - context.inSSR = true\n   */\n  inSSR?: boolean\n  /**\n   * Optional binding metadata analyzed from script - used to optimize\n   * binding access when `prefixIdentifiers` is enabled.\n   */\n  bindingMetadata?: BindingMetadata\n  /**\n   * Compile the function for inlining inside setup().\n   * This allows the function to directly access setup() local bindings.\n   */\n  inline?: boolean\n  /**\n   * Indicates that transforms and codegen should try to output valid TS code\n   */\n  isTS?: boolean\n  /**\n   * Filename for source map generation.\n   * Also used for self-recursive reference in templates\n   * @default 'template.vue.html'\n   */\n  filename?: string\n}\n\nexport interface TransformOptions\n  extends\n    SharedTransformCodegenOptions,\n    ErrorHandlingOptions,\n    CompilerCompatOptions {\n  /**\n   * An array of node transforms to be applied to every AST node.\n   */\n  nodeTransforms?: NodeTransform[]\n  /**\n   * An object of { name: transform } to be applied to every directive attribute\n   * node found on element nodes.\n   */\n  directiveTransforms?: Record<string, DirectiveTransform | undefined>\n  /**\n   * An optional hook to transform a node being hoisted.\n   * used by compiler-dom to turn hoisted nodes into stringified HTML vnodes.\n   * @default null\n   */\n  transformHoist?: HoistTransform | null\n  /**\n   * If the pairing runtime provides additional built-in elements, use this to\n   * mark them as built-in so the compiler will generate component vnodes\n   * for them.\n   */\n  isBuiltInComponent?: (tag: string) => symbol | void\n  /**\n   * Used by some transforms that expects only native elements\n   */\n  isCustomElement?: (tag: string) => boolean | void\n  /**\n   * Transform expressions like {{ foo }} to `_ctx.foo`.\n   * If this option is false, the generated code will be wrapped in a\n   * `with (this) { ... }` block.\n   * - This is force-enabled in module mode, since modules are by default strict\n   * and cannot use `with`\n   * @default mode === 'module'\n   */\n  prefixIdentifiers?: boolean\n  /**\n   * Cache static VNodes and props objects to `_hoisted_x` constants\n   * @default false\n   */\n  hoistStatic?: boolean\n  /**\n   * Cache v-on handlers to avoid creating new inline functions on each render,\n   * also avoids the need for dynamically patching the handlers by wrapping it.\n   * e.g `@click=\"foo\"` by default is compiled to `{ onClick: foo }`. With this\n   * option it's compiled to:\n   * ```js\n   * { onClick: _cache[0] || (_cache[0] = e => _ctx.foo(e)) }\n   * ```\n   * - Requires \"prefixIdentifiers\" to be enabled because it relies on scope\n   * analysis to determine if a handler is safe to cache.\n   * @default false\n   */\n  cacheHandlers?: boolean\n  /**\n   * A list of parser plugins to enable for `@babel/parser`, which is used to\n   * parse expressions in bindings and interpolations.\n   * https://babeljs.io/docs/en/next/babel-parser#plugins\n   */\n  expressionPlugins?: ParserPlugin[]\n  /**\n   * SFC scoped styles ID\n   */\n  scopeId?: string | null\n  /**\n   * Indicates this SFC template has used :slotted in its styles\n   * Defaults to `true` for backwards compatibility - SFC tooling should set it\n   * to `false` if no `:slotted` usage is detected in `<style>`\n   */\n  slotted?: boolean\n  /**\n   * SFC `<style vars>` injection string\n   * Should already be an object expression, e.g. `{ 'xxxx-color': color }`\n   * needed to render inline CSS variables on component root\n   */\n  ssrCssVars?: string\n  /**\n   * Whether to compile the template assuming it needs to handle HMR.\n   * Some edge cases may need to generate different code for HMR to work\n   * correctly, e.g. #6938, #7138\n   */\n  hmr?: boolean\n}\n\nexport interface CodegenOptions extends SharedTransformCodegenOptions {\n  /**\n   * - `module` mode will generate ES module import statements for helpers\n   * and export the render function as the default export.\n   * - `function` mode will generate a single `const { helpers... } = Vue`\n   * statement and return the render function. It expects `Vue` to be globally\n   * available (or passed by wrapping the code with an IIFE). It is meant to be\n   * used with `new Function(code)()` to generate a render function at runtime.\n   * @default 'function'\n   */\n  mode?: 'module' | 'function'\n  /**\n   * Generate source map?\n   * @default false\n   */\n  sourceMap?: boolean\n  /**\n   * SFC scoped styles ID\n   */\n  scopeId?: string | null\n  /**\n   * Option to optimize helper import bindings via variable assignment\n   * (only used for webpack code-split)\n   * @default false\n   */\n  optimizeImports?: boolean\n  /**\n   * Customize where to import runtime helpers from.\n   * @default 'vue'\n   */\n  runtimeModuleName?: string\n  /**\n   * Customize where to import ssr runtime helpers from/**\n   * @default 'vue/server-renderer'\n   */\n  ssrRuntimeModuleName?: string\n  /**\n   * Customize the global variable name of `Vue` to get helpers from\n   * in function mode\n   * @default 'Vue'\n   */\n  runtimeGlobalName?: string\n}\n\nexport type CompilerOptions = ParserOptions & TransformOptions & CodegenOptions\n"
  },
  {
    "path": "packages/compiler-core/src/parser.ts",
    "content": "import {\n  type AttributeNode,\n  ConstantTypes,\n  type DirectiveNode,\n  type ElementNode,\n  ElementTypes,\n  type ForParseResult,\n  Namespaces,\n  NodeTypes,\n  type RootNode,\n  type SimpleExpressionNode,\n  type SourceLocation,\n  type TemplateChildNode,\n  createRoot,\n  createSimpleExpression,\n} from './ast'\nimport type { ParserOptions } from './options'\nimport Tokenizer, {\n  CharCodes,\n  ParseMode,\n  QuoteType,\n  Sequences,\n  State,\n  isWhitespace,\n  toCharCodes,\n} from './tokenizer'\nimport {\n  type CompilerCompatOptions,\n  CompilerDeprecationTypes,\n  checkCompatEnabled,\n  isCompatEnabled,\n  warnDeprecation,\n} from './compat/compatConfig'\nimport { NO, extend } from '@vue/shared'\nimport {\n  ErrorCodes,\n  createCompilerError,\n  defaultOnError,\n  defaultOnWarn,\n} from './errors'\nimport {\n  forAliasRE,\n  isAllWhitespace,\n  isCoreComponent,\n  isSimpleIdentifier,\n  isStaticArgOf,\n  isVPre,\n} from './utils'\nimport { decodeHTML } from 'entities/decode'\nimport {\n  type ParserOptions as BabelOptions,\n  parse,\n  parseExpression,\n} from '@babel/parser'\n\ntype OptionalOptions =\n  | 'decodeEntities'\n  | 'whitespace'\n  | 'isNativeTag'\n  | 'isBuiltInComponent'\n  | 'expressionPlugins'\n  | keyof CompilerCompatOptions\n\nexport type MergedParserOptions = Omit<\n  Required<ParserOptions>,\n  OptionalOptions\n> &\n  Pick<ParserOptions, OptionalOptions>\n\nexport const defaultParserOptions: MergedParserOptions = {\n  parseMode: 'base',\n  ns: Namespaces.HTML,\n  delimiters: [`{{`, `}}`],\n  getNamespace: () => Namespaces.HTML,\n  isVoidTag: NO,\n  isPreTag: NO,\n  isIgnoreNewlineTag: NO,\n  isCustomElement: NO,\n  onError: defaultOnError,\n  onWarn: defaultOnWarn,\n  comments: __DEV__,\n  prefixIdentifiers: false,\n}\n\nlet currentOptions: MergedParserOptions = defaultParserOptions\nlet currentRoot: RootNode | null = null\n\n// parser state\nlet currentInput = ''\nlet currentOpenTag: ElementNode | null = null\nlet currentProp: AttributeNode | DirectiveNode | null = null\nlet currentAttrValue = ''\nlet currentAttrStartIndex = -1\nlet currentAttrEndIndex = -1\nlet inPre = 0\nlet inVPre = false\nlet currentVPreBoundary: ElementNode | null = null\nconst stack: ElementNode[] = []\n\nconst tokenizer = new Tokenizer(stack, {\n  onerr: emitError,\n\n  ontext(start, end) {\n    onText(getSlice(start, end), start, end)\n  },\n\n  ontextentity(char, start, end) {\n    onText(char, start, end)\n  },\n\n  oninterpolation(start, end) {\n    if (inVPre) {\n      return onText(getSlice(start, end), start, end)\n    }\n    let innerStart = start + tokenizer.delimiterOpen.length\n    let innerEnd = end - tokenizer.delimiterClose.length\n    while (isWhitespace(currentInput.charCodeAt(innerStart))) {\n      innerStart++\n    }\n    while (isWhitespace(currentInput.charCodeAt(innerEnd - 1))) {\n      innerEnd--\n    }\n    let exp = getSlice(innerStart, innerEnd)\n    // decode entities for backwards compat\n    if (exp.includes('&')) {\n      if (__BROWSER__) {\n        exp = currentOptions.decodeEntities!(exp, false)\n      } else {\n        exp = decodeHTML(exp)\n      }\n    }\n    addNode({\n      type: NodeTypes.INTERPOLATION,\n      content: createExp(exp, false, getLoc(innerStart, innerEnd)),\n      loc: getLoc(start, end),\n    })\n  },\n\n  onopentagname(start, end) {\n    const name = getSlice(start, end)\n    currentOpenTag = {\n      type: NodeTypes.ELEMENT,\n      tag: name,\n      ns: currentOptions.getNamespace(name, stack[0], currentOptions.ns),\n      tagType: ElementTypes.ELEMENT, // will be refined on tag close\n      props: [],\n      children: [],\n      loc: getLoc(start - 1, end),\n      codegenNode: undefined,\n    }\n  },\n\n  onopentagend(end) {\n    endOpenTag(end)\n  },\n\n  onclosetag(start, end) {\n    const name = getSlice(start, end)\n    if (!currentOptions.isVoidTag(name)) {\n      let found = false\n      for (let i = 0; i < stack.length; i++) {\n        const e = stack[i]\n        if (e.tag.toLowerCase() === name.toLowerCase()) {\n          found = true\n          if (i > 0) {\n            emitError(ErrorCodes.X_MISSING_END_TAG, stack[0].loc.start.offset)\n          }\n          for (let j = 0; j <= i; j++) {\n            const el = stack.shift()!\n            onCloseTag(el, end, j < i)\n          }\n          break\n        }\n      }\n      if (!found) {\n        emitError(ErrorCodes.X_INVALID_END_TAG, backTrack(start, CharCodes.Lt))\n      }\n    }\n  },\n\n  onselfclosingtag(end) {\n    const name = currentOpenTag!.tag\n    currentOpenTag!.isSelfClosing = true\n    endOpenTag(end)\n    if (stack[0] && stack[0].tag === name) {\n      onCloseTag(stack.shift()!, end)\n    }\n  },\n\n  onattribname(start, end) {\n    // plain attribute\n    currentProp = {\n      type: NodeTypes.ATTRIBUTE,\n      name: getSlice(start, end),\n      nameLoc: getLoc(start, end),\n      value: undefined,\n      loc: getLoc(start),\n    }\n  },\n\n  ondirname(start, end) {\n    const raw = getSlice(start, end)\n    const name =\n      raw === '.' || raw === ':'\n        ? 'bind'\n        : raw === '@'\n          ? 'on'\n          : raw === '#'\n            ? 'slot'\n            : raw.slice(2)\n\n    if (!inVPre && name === '') {\n      emitError(ErrorCodes.X_MISSING_DIRECTIVE_NAME, start)\n    }\n\n    if (inVPre || name === '') {\n      currentProp = {\n        type: NodeTypes.ATTRIBUTE,\n        name: raw,\n        nameLoc: getLoc(start, end),\n        value: undefined,\n        loc: getLoc(start),\n      }\n    } else {\n      currentProp = {\n        type: NodeTypes.DIRECTIVE,\n        name,\n        rawName: raw,\n        exp: undefined,\n        arg: undefined,\n        modifiers: raw === '.' ? [createSimpleExpression('prop')] : [],\n        loc: getLoc(start),\n      }\n      if (name === 'pre') {\n        inVPre = tokenizer.inVPre = true\n        currentVPreBoundary = currentOpenTag\n        // convert dirs before this one to attributes\n        const props = currentOpenTag!.props\n        for (let i = 0; i < props.length; i++) {\n          if (props[i].type === NodeTypes.DIRECTIVE) {\n            props[i] = dirToAttr(props[i] as DirectiveNode)\n          }\n        }\n      }\n    }\n  },\n\n  ondirarg(start, end) {\n    if (start === end) return\n    const arg = getSlice(start, end)\n    if (inVPre && !isVPre(currentProp!)) {\n      ;(currentProp as AttributeNode).name += arg\n      setLocEnd((currentProp as AttributeNode).nameLoc, end)\n    } else {\n      const isStatic = arg[0] !== `[`\n      ;(currentProp as DirectiveNode).arg = createExp(\n        isStatic ? arg : arg.slice(1, -1),\n        isStatic,\n        getLoc(start, end),\n        isStatic ? ConstantTypes.CAN_STRINGIFY : ConstantTypes.NOT_CONSTANT,\n      )\n    }\n  },\n\n  ondirmodifier(start, end) {\n    const mod = getSlice(start, end)\n    if (inVPre && !isVPre(currentProp!)) {\n      ;(currentProp as AttributeNode).name += '.' + mod\n      setLocEnd((currentProp as AttributeNode).nameLoc, end)\n    } else if ((currentProp as DirectiveNode).name === 'slot') {\n      // slot has no modifiers, special case for edge cases like\n      // https://github.com/vuejs/language-tools/issues/2710\n      const arg = (currentProp as DirectiveNode).arg\n      if (arg) {\n        ;(arg as SimpleExpressionNode).content += '.' + mod\n        setLocEnd(arg.loc, end)\n      }\n    } else {\n      const exp = createSimpleExpression(mod, true, getLoc(start, end))\n      ;(currentProp as DirectiveNode).modifiers.push(exp)\n    }\n  },\n\n  onattribdata(start, end) {\n    currentAttrValue += getSlice(start, end)\n    if (currentAttrStartIndex < 0) currentAttrStartIndex = start\n    currentAttrEndIndex = end\n  },\n\n  onattribentity(char, start, end) {\n    currentAttrValue += char\n    if (currentAttrStartIndex < 0) currentAttrStartIndex = start\n    currentAttrEndIndex = end\n  },\n\n  onattribnameend(end) {\n    const start = currentProp!.loc.start.offset\n    const name = getSlice(start, end)\n    if (currentProp!.type === NodeTypes.DIRECTIVE) {\n      currentProp!.rawName = name\n    }\n    // check duplicate attrs\n    if (\n      currentOpenTag!.props.some(\n        p => (p.type === NodeTypes.DIRECTIVE ? p.rawName : p.name) === name,\n      )\n    ) {\n      emitError(ErrorCodes.DUPLICATE_ATTRIBUTE, start)\n    }\n  },\n\n  onattribend(quote, end) {\n    if (currentOpenTag && currentProp) {\n      // finalize end pos\n      setLocEnd(currentProp.loc, end)\n\n      if (quote !== QuoteType.NoValue) {\n        if (__BROWSER__ && currentAttrValue.includes('&')) {\n          currentAttrValue = currentOptions.decodeEntities!(\n            currentAttrValue,\n            true,\n          )\n        }\n\n        if (currentProp.type === NodeTypes.ATTRIBUTE) {\n          // assign value\n\n          // condense whitespaces in class\n          if (currentProp!.name === 'class') {\n            currentAttrValue = condense(currentAttrValue).trim()\n          }\n\n          if (quote === QuoteType.Unquoted && !currentAttrValue) {\n            emitError(ErrorCodes.MISSING_ATTRIBUTE_VALUE, end)\n          }\n\n          currentProp!.value = {\n            type: NodeTypes.TEXT,\n            content: currentAttrValue,\n            loc:\n              quote === QuoteType.Unquoted\n                ? getLoc(currentAttrStartIndex, currentAttrEndIndex)\n                : getLoc(currentAttrStartIndex - 1, currentAttrEndIndex + 1),\n          }\n          if (\n            tokenizer.inSFCRoot &&\n            currentOpenTag.tag === 'template' &&\n            currentProp.name === 'lang' &&\n            currentAttrValue &&\n            currentAttrValue !== 'html'\n          ) {\n            // SFC root template with preprocessor lang, force tokenizer to\n            // RCDATA mode\n            tokenizer.enterRCDATA(toCharCodes(`</template`), 0)\n          }\n        } else {\n          // directive\n          let expParseMode = ExpParseMode.Normal\n          if (!__BROWSER__) {\n            if (currentProp.name === 'for') {\n              expParseMode = ExpParseMode.Skip\n            } else if (currentProp.name === 'slot') {\n              expParseMode = ExpParseMode.Params\n            } else if (\n              currentProp.name === 'on' &&\n              currentAttrValue.includes(';')\n            ) {\n              expParseMode = ExpParseMode.Statements\n            }\n          }\n          currentProp.exp = createExp(\n            currentAttrValue,\n            false,\n            getLoc(currentAttrStartIndex, currentAttrEndIndex),\n            ConstantTypes.NOT_CONSTANT,\n            expParseMode,\n          )\n          if (currentProp.name === 'for') {\n            currentProp.forParseResult = parseForExpression(currentProp.exp)\n          }\n          // 2.x compat v-bind:foo.sync -> v-model:foo\n          let syncIndex = -1\n          if (\n            __COMPAT__ &&\n            currentProp.name === 'bind' &&\n            (syncIndex = currentProp.modifiers.findIndex(\n              mod => mod.content === 'sync',\n            )) > -1 &&\n            checkCompatEnabled(\n              CompilerDeprecationTypes.COMPILER_V_BIND_SYNC,\n              currentOptions,\n              currentProp.loc,\n              currentProp.arg!.loc.source,\n            )\n          ) {\n            currentProp.name = 'model'\n            currentProp.modifiers.splice(syncIndex, 1)\n          }\n        }\n      }\n      if (\n        currentProp.type !== NodeTypes.DIRECTIVE ||\n        currentProp.name !== 'pre'\n      ) {\n        currentOpenTag.props.push(currentProp)\n      }\n    }\n    currentAttrValue = ''\n    currentAttrStartIndex = currentAttrEndIndex = -1\n  },\n\n  oncomment(start, end) {\n    if (currentOptions.comments) {\n      addNode({\n        type: NodeTypes.COMMENT,\n        content: getSlice(start, end),\n        loc: getLoc(start - 4, end + 3),\n      })\n    }\n  },\n\n  onend() {\n    const end = currentInput.length\n    // EOF ERRORS\n    if ((__DEV__ || !__BROWSER__) && tokenizer.state !== State.Text) {\n      switch (tokenizer.state) {\n        case State.BeforeTagName:\n        case State.BeforeClosingTagName:\n          emitError(ErrorCodes.EOF_BEFORE_TAG_NAME, end)\n          break\n        case State.Interpolation:\n        case State.InterpolationClose:\n          emitError(\n            ErrorCodes.X_MISSING_INTERPOLATION_END,\n            tokenizer.sectionStart,\n          )\n          break\n        case State.InCommentLike:\n          if (tokenizer.currentSequence === Sequences.CdataEnd) {\n            emitError(ErrorCodes.EOF_IN_CDATA, end)\n          } else {\n            emitError(ErrorCodes.EOF_IN_COMMENT, end)\n          }\n          break\n        case State.InTagName:\n        case State.InSelfClosingTag:\n        case State.InClosingTagName:\n        case State.BeforeAttrName:\n        case State.InAttrName:\n        case State.InDirName:\n        case State.InDirArg:\n        case State.InDirDynamicArg:\n        case State.InDirModifier:\n        case State.AfterAttrName:\n        case State.BeforeAttrValue:\n        case State.InAttrValueDq: // \"\n        case State.InAttrValueSq: // '\n        case State.InAttrValueNq:\n          emitError(ErrorCodes.EOF_IN_TAG, end)\n          break\n        default:\n          // console.log(tokenizer.state)\n          break\n      }\n    }\n    for (let index = 0; index < stack.length; index++) {\n      onCloseTag(stack[index], end - 1)\n      emitError(ErrorCodes.X_MISSING_END_TAG, stack[index].loc.start.offset)\n    }\n  },\n\n  oncdata(start, end) {\n    if (stack[0].ns !== Namespaces.HTML) {\n      onText(getSlice(start, end), start, end)\n    } else {\n      emitError(ErrorCodes.CDATA_IN_HTML_CONTENT, start - 9)\n    }\n  },\n\n  onprocessinginstruction(start) {\n    // ignore as we do not have runtime handling for this, only check error\n    if ((stack[0] ? stack[0].ns : currentOptions.ns) === Namespaces.HTML) {\n      emitError(\n        ErrorCodes.UNEXPECTED_QUESTION_MARK_INSTEAD_OF_TAG_NAME,\n        start - 1,\n      )\n    }\n  },\n})\n\n// This regex doesn't cover the case if key or index aliases have destructuring,\n// but those do not make sense in the first place, so this works in practice.\nconst forIteratorRE = /,([^,\\}\\]]*)(?:,([^,\\}\\]]*))?$/\nconst stripParensRE = /^\\(|\\)$/g\n\nfunction parseForExpression(\n  input: SimpleExpressionNode,\n): ForParseResult | undefined {\n  const loc = input.loc\n  const exp = input.content\n  const inMatch = exp.match(forAliasRE)\n  if (!inMatch) return\n\n  const [, LHS, RHS] = inMatch\n\n  const createAliasExpression = (\n    content: string,\n    offset: number,\n    asParam = false,\n  ) => {\n    const start = loc.start.offset + offset\n    const end = start + content.length\n    return createExp(\n      content,\n      false,\n      getLoc(start, end),\n      ConstantTypes.NOT_CONSTANT,\n      asParam ? ExpParseMode.Params : ExpParseMode.Normal,\n    )\n  }\n\n  const result: ForParseResult = {\n    source: createAliasExpression(RHS.trim(), exp.indexOf(RHS, LHS.length)),\n    value: undefined,\n    key: undefined,\n    index: undefined,\n    finalized: false,\n  }\n\n  let valueContent = LHS.trim().replace(stripParensRE, '').trim()\n  const trimmedOffset = LHS.indexOf(valueContent)\n\n  const iteratorMatch = valueContent.match(forIteratorRE)\n  if (iteratorMatch) {\n    valueContent = valueContent.replace(forIteratorRE, '').trim()\n\n    const keyContent = iteratorMatch[1].trim()\n    let keyOffset: number | undefined\n    if (keyContent) {\n      keyOffset = exp.indexOf(keyContent, trimmedOffset + valueContent.length)\n      result.key = createAliasExpression(keyContent, keyOffset, true)\n    }\n\n    if (iteratorMatch[2]) {\n      const indexContent = iteratorMatch[2].trim()\n\n      if (indexContent) {\n        result.index = createAliasExpression(\n          indexContent,\n          exp.indexOf(\n            indexContent,\n            result.key\n              ? keyOffset! + keyContent.length\n              : trimmedOffset + valueContent.length,\n          ),\n          true,\n        )\n      }\n    }\n  }\n\n  if (valueContent) {\n    result.value = createAliasExpression(valueContent, trimmedOffset, true)\n  }\n\n  return result\n}\n\nfunction getSlice(start: number, end: number) {\n  return currentInput.slice(start, end)\n}\n\nfunction endOpenTag(end: number) {\n  if (tokenizer.inSFCRoot) {\n    // in SFC mode, generate locations for root-level tags' inner content.\n    currentOpenTag!.innerLoc = getLoc(end + 1, end + 1)\n  }\n  addNode(currentOpenTag!)\n  const { tag, ns } = currentOpenTag!\n  if (ns === Namespaces.HTML && currentOptions.isPreTag(tag)) {\n    inPre++\n  }\n  if (currentOptions.isVoidTag(tag)) {\n    onCloseTag(currentOpenTag!, end)\n  } else {\n    stack.unshift(currentOpenTag!)\n    if (ns === Namespaces.SVG || ns === Namespaces.MATH_ML) {\n      tokenizer.inXML = true\n    }\n  }\n  currentOpenTag = null\n}\n\nfunction onText(content: string, start: number, end: number) {\n  if (__BROWSER__) {\n    const tag = stack[0] && stack[0].tag\n    if (tag !== 'script' && tag !== 'style' && content.includes('&')) {\n      content = currentOptions.decodeEntities!(content, false)\n    }\n  }\n  const parent = stack[0] || currentRoot\n  const lastNode = parent.children[parent.children.length - 1]\n  if (lastNode && lastNode.type === NodeTypes.TEXT) {\n    // merge\n    lastNode.content += content\n    setLocEnd(lastNode.loc, end)\n  } else {\n    parent.children.push({\n      type: NodeTypes.TEXT,\n      content,\n      loc: getLoc(start, end),\n    })\n  }\n}\n\nfunction onCloseTag(el: ElementNode, end: number, isImplied = false) {\n  // attach end position\n  if (isImplied) {\n    // implied close, end should be backtracked to close\n    setLocEnd(el.loc, backTrack(end, CharCodes.Lt))\n  } else {\n    setLocEnd(el.loc, lookAhead(end, CharCodes.Gt) + 1)\n  }\n\n  if (tokenizer.inSFCRoot) {\n    // SFC root tag, resolve inner end\n    if (el.children.length) {\n      el.innerLoc!.end = extend({}, el.children[el.children.length - 1].loc.end)\n    } else {\n      el.innerLoc!.end = extend({}, el.innerLoc!.start)\n    }\n    el.innerLoc!.source = getSlice(\n      el.innerLoc!.start.offset,\n      el.innerLoc!.end.offset,\n    )\n  }\n\n  // refine element type\n  const { tag, ns, children } = el\n  if (!inVPre) {\n    if (tag === 'slot') {\n      el.tagType = ElementTypes.SLOT\n    } else if (isFragmentTemplate(el)) {\n      el.tagType = ElementTypes.TEMPLATE\n    } else if (isComponent(el)) {\n      el.tagType = ElementTypes.COMPONENT\n    }\n  }\n\n  // whitespace management\n  if (!tokenizer.inRCDATA) {\n    el.children = condenseWhitespace(children)\n  }\n\n  if (ns === Namespaces.HTML && currentOptions.isIgnoreNewlineTag(tag)) {\n    // remove leading newline for <textarea> and <pre> per html spec\n    // https://html.spec.whatwg.org/multipage/parsing.html#parsing-main-inbody\n    const first = children[0]\n    if (first && first.type === NodeTypes.TEXT) {\n      first.content = first.content.replace(/^\\r?\\n/, '')\n    }\n  }\n\n  if (ns === Namespaces.HTML && currentOptions.isPreTag(tag)) {\n    inPre--\n  }\n  if (currentVPreBoundary === el) {\n    inVPre = tokenizer.inVPre = false\n    currentVPreBoundary = null\n  }\n  if (\n    tokenizer.inXML &&\n    (stack[0] ? stack[0].ns : currentOptions.ns) === Namespaces.HTML\n  ) {\n    tokenizer.inXML = false\n  }\n\n  // 2.x compat / deprecation checks\n  if (__COMPAT__) {\n    const props = el.props\n    if (\n      __DEV__ &&\n      isCompatEnabled(\n        CompilerDeprecationTypes.COMPILER_V_IF_V_FOR_PRECEDENCE,\n        currentOptions,\n      )\n    ) {\n      let hasIf = false\n      let hasFor = false\n      for (let i = 0; i < props.length; i++) {\n        const p = props[i]\n        if (p.type === NodeTypes.DIRECTIVE) {\n          if (p.name === 'if') {\n            hasIf = true\n          } else if (p.name === 'for') {\n            hasFor = true\n          }\n        }\n        if (hasIf && hasFor) {\n          warnDeprecation(\n            CompilerDeprecationTypes.COMPILER_V_IF_V_FOR_PRECEDENCE,\n            currentOptions,\n            el.loc,\n          )\n          break\n        }\n      }\n    }\n\n    if (\n      !tokenizer.inSFCRoot &&\n      isCompatEnabled(\n        CompilerDeprecationTypes.COMPILER_NATIVE_TEMPLATE,\n        currentOptions,\n      ) &&\n      el.tag === 'template' &&\n      !isFragmentTemplate(el)\n    ) {\n      __DEV__ &&\n        warnDeprecation(\n          CompilerDeprecationTypes.COMPILER_NATIVE_TEMPLATE,\n          currentOptions,\n          el.loc,\n        )\n      // unwrap\n      const parent = stack[0] || currentRoot\n      const index = parent.children.indexOf(el)\n      parent.children.splice(index, 1, ...el.children)\n    }\n\n    const inlineTemplateProp = props.find(\n      p => p.type === NodeTypes.ATTRIBUTE && p.name === 'inline-template',\n    ) as AttributeNode\n    if (\n      inlineTemplateProp &&\n      checkCompatEnabled(\n        CompilerDeprecationTypes.COMPILER_INLINE_TEMPLATE,\n        currentOptions,\n        inlineTemplateProp.loc,\n      ) &&\n      el.children.length\n    ) {\n      inlineTemplateProp.value = {\n        type: NodeTypes.TEXT,\n        content: getSlice(\n          el.children[0].loc.start.offset,\n          el.children[el.children.length - 1].loc.end.offset,\n        ),\n        loc: inlineTemplateProp.loc,\n      }\n    }\n  }\n}\n\nfunction lookAhead(index: number, c: number) {\n  let i = index\n  while (currentInput.charCodeAt(i) !== c && i < currentInput.length - 1) i++\n  return i\n}\n\nfunction backTrack(index: number, c: number) {\n  let i = index\n  while (currentInput.charCodeAt(i) !== c && i >= 0) i--\n  return i\n}\n\nconst specialTemplateDir = new Set(['if', 'else', 'else-if', 'for', 'slot'])\nfunction isFragmentTemplate({ tag, props }: ElementNode): boolean {\n  if (tag === 'template') {\n    for (let i = 0; i < props.length; i++) {\n      if (\n        props[i].type === NodeTypes.DIRECTIVE &&\n        specialTemplateDir.has((props[i] as DirectiveNode).name)\n      ) {\n        return true\n      }\n    }\n  }\n  return false\n}\n\nfunction isComponent({ tag, props }: ElementNode): boolean {\n  if (currentOptions.isCustomElement(tag)) {\n    return false\n  }\n  if (\n    tag === 'component' ||\n    isUpperCase(tag.charCodeAt(0)) ||\n    isCoreComponent(tag) ||\n    (currentOptions.isBuiltInComponent &&\n      currentOptions.isBuiltInComponent(tag)) ||\n    (currentOptions.isNativeTag && !currentOptions.isNativeTag(tag))\n  ) {\n    return true\n  }\n  // at this point the tag should be a native tag, but check for potential \"is\"\n  // casting\n  for (let i = 0; i < props.length; i++) {\n    const p = props[i]\n    if (p.type === NodeTypes.ATTRIBUTE) {\n      if (p.name === 'is' && p.value) {\n        if (p.value.content.startsWith('vue:')) {\n          return true\n        } else if (\n          __COMPAT__ &&\n          checkCompatEnabled(\n            CompilerDeprecationTypes.COMPILER_IS_ON_ELEMENT,\n            currentOptions,\n            p.loc,\n          )\n        ) {\n          return true\n        }\n      }\n    } else if (\n      __COMPAT__ &&\n      // :is on plain element - only treat as component in compat mode\n      p.name === 'bind' &&\n      isStaticArgOf(p.arg, 'is') &&\n      checkCompatEnabled(\n        CompilerDeprecationTypes.COMPILER_IS_ON_ELEMENT,\n        currentOptions,\n        p.loc,\n      )\n    ) {\n      return true\n    }\n  }\n  return false\n}\n\nfunction isUpperCase(c: number) {\n  return c > 64 && c < 91\n}\n\nconst windowsNewlineRE = /\\r\\n/g\nfunction condenseWhitespace(nodes: TemplateChildNode[]): TemplateChildNode[] {\n  const shouldCondense = currentOptions.whitespace !== 'preserve'\n  let removedWhitespace = false\n  for (let i = 0; i < nodes.length; i++) {\n    const node = nodes[i]\n    if (node.type === NodeTypes.TEXT) {\n      if (!inPre) {\n        if (isAllWhitespace(node.content)) {\n          const prev = nodes[i - 1] && nodes[i - 1].type\n          const next = nodes[i + 1] && nodes[i + 1].type\n          // Remove if:\n          // - the whitespace is the first or last node, or:\n          // - (condense mode) the whitespace is between two comments, or:\n          // - (condense mode) the whitespace is between comment and element, or:\n          // - (condense mode) the whitespace is between two elements AND contains newline\n          if (\n            !prev ||\n            !next ||\n            (shouldCondense &&\n              ((prev === NodeTypes.COMMENT &&\n                (next === NodeTypes.COMMENT || next === NodeTypes.ELEMENT)) ||\n                (prev === NodeTypes.ELEMENT &&\n                  (next === NodeTypes.COMMENT ||\n                    (next === NodeTypes.ELEMENT &&\n                      hasNewlineChar(node.content))))))\n          ) {\n            removedWhitespace = true\n            nodes[i] = null as any\n          } else {\n            // Otherwise, the whitespace is condensed into a single space\n            node.content = ' '\n          }\n        } else if (shouldCondense) {\n          // in condense mode, consecutive whitespaces in text are condensed\n          // down to a single space.\n          node.content = condense(node.content)\n        }\n      } else {\n        // #6410 normalize windows newlines in <pre>:\n        // in SSR, browsers normalize server-rendered \\r\\n into a single \\n\n        // in the DOM\n        node.content = node.content.replace(windowsNewlineRE, '\\n')\n      }\n    }\n  }\n  return removedWhitespace ? nodes.filter(Boolean) : nodes\n}\n\nfunction hasNewlineChar(str: string) {\n  for (let i = 0; i < str.length; i++) {\n    const c = str.charCodeAt(i)\n    if (c === CharCodes.NewLine || c === CharCodes.CarriageReturn) {\n      return true\n    }\n  }\n  return false\n}\n\nfunction condense(str: string) {\n  let ret = ''\n  let prevCharIsWhitespace = false\n  for (let i = 0; i < str.length; i++) {\n    if (isWhitespace(str.charCodeAt(i))) {\n      if (!prevCharIsWhitespace) {\n        ret += ' '\n        prevCharIsWhitespace = true\n      }\n    } else {\n      ret += str[i]\n      prevCharIsWhitespace = false\n    }\n  }\n  return ret\n}\n\nfunction addNode(node: TemplateChildNode) {\n  ;(stack[0] || currentRoot).children.push(node)\n}\n\nfunction getLoc(start: number, end?: number): SourceLocation {\n  return {\n    start: tokenizer.getPos(start),\n    // @ts-expect-error allow late attachment\n    end: end == null ? end : tokenizer.getPos(end),\n    // @ts-expect-error allow late attachment\n    source: end == null ? end : getSlice(start, end),\n  }\n}\n\nexport function cloneLoc(loc: SourceLocation): SourceLocation {\n  return getLoc(loc.start.offset, loc.end.offset)\n}\n\nfunction setLocEnd(loc: SourceLocation, end: number) {\n  loc.end = tokenizer.getPos(end)\n  loc.source = getSlice(loc.start.offset, end)\n}\n\nfunction dirToAttr(dir: DirectiveNode): AttributeNode {\n  const attr: AttributeNode = {\n    type: NodeTypes.ATTRIBUTE,\n    name: dir.rawName!,\n    nameLoc: getLoc(\n      dir.loc.start.offset,\n      dir.loc.start.offset + dir.rawName!.length,\n    ),\n    value: undefined,\n    loc: dir.loc,\n  }\n  if (dir.exp) {\n    // account for quotes\n    const loc = dir.exp.loc\n    if (loc.end.offset < dir.loc.end.offset) {\n      loc.start.offset--\n      loc.start.column--\n      loc.end.offset++\n      loc.end.column++\n    }\n    attr.value = {\n      type: NodeTypes.TEXT,\n      content: (dir.exp as SimpleExpressionNode).content,\n      loc,\n    }\n  }\n  return attr\n}\n\nenum ExpParseMode {\n  Normal,\n  Params,\n  Statements,\n  Skip,\n}\n\nfunction createExp(\n  content: SimpleExpressionNode['content'],\n  isStatic: SimpleExpressionNode['isStatic'] = false,\n  loc: SourceLocation,\n  constType: ConstantTypes = ConstantTypes.NOT_CONSTANT,\n  parseMode = ExpParseMode.Normal,\n) {\n  const exp = createSimpleExpression(content, isStatic, loc, constType)\n  if (\n    !__BROWSER__ &&\n    !isStatic &&\n    currentOptions.prefixIdentifiers &&\n    parseMode !== ExpParseMode.Skip &&\n    content.trim()\n  ) {\n    if (isSimpleIdentifier(content)) {\n      exp.ast = null // fast path\n      return exp\n    }\n    try {\n      const plugins = currentOptions.expressionPlugins\n      const options: BabelOptions = {\n        plugins: plugins ? [...plugins, 'typescript'] : ['typescript'],\n      }\n      if (parseMode === ExpParseMode.Statements) {\n        // v-on with multi-inline-statements, pad 1 char\n        exp.ast = parse(` ${content} `, options).program\n      } else if (parseMode === ExpParseMode.Params) {\n        exp.ast = parseExpression(`(${content})=>{}`, options)\n      } else {\n        // normal exp, wrap with parens\n        exp.ast = parseExpression(`(${content})`, options)\n      }\n    } catch (e: any) {\n      exp.ast = false // indicate an error\n      emitError(ErrorCodes.X_INVALID_EXPRESSION, loc.start.offset, e.message)\n    }\n  }\n  return exp\n}\n\nfunction emitError(code: ErrorCodes, index: number, message?: string) {\n  currentOptions.onError(\n    createCompilerError(code, getLoc(index, index), undefined, message),\n  )\n}\n\nfunction reset() {\n  tokenizer.reset()\n  currentOpenTag = null\n  currentProp = null\n  currentAttrValue = ''\n  currentAttrStartIndex = -1\n  currentAttrEndIndex = -1\n  stack.length = 0\n}\n\nexport function baseParse(input: string, options?: ParserOptions): RootNode {\n  reset()\n  currentInput = input\n  currentOptions = extend({}, defaultParserOptions)\n\n  if (options) {\n    let key: keyof ParserOptions\n    for (key in options) {\n      if (options[key] != null) {\n        // @ts-expect-error\n        currentOptions[key] = options[key]\n      }\n    }\n  }\n\n  if (__DEV__) {\n    if (!__BROWSER__ && currentOptions.decodeEntities) {\n      console.warn(\n        `[@vue/compiler-core] decodeEntities option is passed but will be ` +\n          `ignored in non-browser builds.`,\n      )\n    } else if (__BROWSER__ && !__TEST__ && !currentOptions.decodeEntities) {\n      throw new Error(\n        `[@vue/compiler-core] decodeEntities option is required in browser builds.`,\n      )\n    }\n  }\n\n  tokenizer.mode =\n    currentOptions.parseMode === 'html'\n      ? ParseMode.HTML\n      : currentOptions.parseMode === 'sfc'\n        ? ParseMode.SFC\n        : ParseMode.BASE\n\n  tokenizer.inXML =\n    currentOptions.ns === Namespaces.SVG ||\n    currentOptions.ns === Namespaces.MATH_ML\n\n  const delimiters = options && options.delimiters\n  if (delimiters) {\n    tokenizer.delimiterOpen = toCharCodes(delimiters[0])\n    tokenizer.delimiterClose = toCharCodes(delimiters[1])\n  }\n\n  const root = (currentRoot = createRoot([], input))\n  tokenizer.parse(currentInput)\n  root.loc = getLoc(0, input.length)\n  root.children = condenseWhitespace(root.children)\n  currentRoot = null\n  return root\n}\n"
  },
  {
    "path": "packages/compiler-core/src/runtimeHelpers.ts",
    "content": "export const FRAGMENT: unique symbol = Symbol(__DEV__ ? `Fragment` : ``)\nexport const TELEPORT: unique symbol = Symbol(__DEV__ ? `Teleport` : ``)\nexport const SUSPENSE: unique symbol = Symbol(__DEV__ ? `Suspense` : ``)\nexport const KEEP_ALIVE: unique symbol = Symbol(__DEV__ ? `KeepAlive` : ``)\nexport const BASE_TRANSITION: unique symbol = Symbol(\n  __DEV__ ? `BaseTransition` : ``,\n)\nexport const OPEN_BLOCK: unique symbol = Symbol(__DEV__ ? `openBlock` : ``)\nexport const CREATE_BLOCK: unique symbol = Symbol(__DEV__ ? `createBlock` : ``)\nexport const CREATE_ELEMENT_BLOCK: unique symbol = Symbol(\n  __DEV__ ? `createElementBlock` : ``,\n)\nexport const CREATE_VNODE: unique symbol = Symbol(__DEV__ ? `createVNode` : ``)\nexport const CREATE_ELEMENT_VNODE: unique symbol = Symbol(\n  __DEV__ ? `createElementVNode` : ``,\n)\nexport const CREATE_COMMENT: unique symbol = Symbol(\n  __DEV__ ? `createCommentVNode` : ``,\n)\nexport const CREATE_TEXT: unique symbol = Symbol(\n  __DEV__ ? `createTextVNode` : ``,\n)\nexport const CREATE_STATIC: unique symbol = Symbol(\n  __DEV__ ? `createStaticVNode` : ``,\n)\nexport const RESOLVE_COMPONENT: unique symbol = Symbol(\n  __DEV__ ? `resolveComponent` : ``,\n)\nexport const RESOLVE_DYNAMIC_COMPONENT: unique symbol = Symbol(\n  __DEV__ ? `resolveDynamicComponent` : ``,\n)\nexport const RESOLVE_DIRECTIVE: unique symbol = Symbol(\n  __DEV__ ? `resolveDirective` : ``,\n)\nexport const RESOLVE_FILTER: unique symbol = Symbol(\n  __DEV__ ? `resolveFilter` : ``,\n)\nexport const WITH_DIRECTIVES: unique symbol = Symbol(\n  __DEV__ ? `withDirectives` : ``,\n)\nexport const RENDER_LIST: unique symbol = Symbol(__DEV__ ? `renderList` : ``)\nexport const RENDER_SLOT: unique symbol = Symbol(__DEV__ ? `renderSlot` : ``)\nexport const CREATE_SLOTS: unique symbol = Symbol(__DEV__ ? `createSlots` : ``)\nexport const TO_DISPLAY_STRING: unique symbol = Symbol(\n  __DEV__ ? `toDisplayString` : ``,\n)\nexport const MERGE_PROPS: unique symbol = Symbol(__DEV__ ? `mergeProps` : ``)\nexport const NORMALIZE_CLASS: unique symbol = Symbol(\n  __DEV__ ? `normalizeClass` : ``,\n)\nexport const NORMALIZE_STYLE: unique symbol = Symbol(\n  __DEV__ ? `normalizeStyle` : ``,\n)\nexport const NORMALIZE_PROPS: unique symbol = Symbol(\n  __DEV__ ? `normalizeProps` : ``,\n)\nexport const GUARD_REACTIVE_PROPS: unique symbol = Symbol(\n  __DEV__ ? `guardReactiveProps` : ``,\n)\nexport const TO_HANDLERS: unique symbol = Symbol(__DEV__ ? `toHandlers` : ``)\nexport const CAMELIZE: unique symbol = Symbol(__DEV__ ? `camelize` : ``)\nexport const CAPITALIZE: unique symbol = Symbol(__DEV__ ? `capitalize` : ``)\nexport const TO_HANDLER_KEY: unique symbol = Symbol(\n  __DEV__ ? `toHandlerKey` : ``,\n)\nexport const SET_BLOCK_TRACKING: unique symbol = Symbol(\n  __DEV__ ? `setBlockTracking` : ``,\n)\n/**\n * @deprecated no longer needed in 3.5+ because we no longer hoist element nodes\n * but kept for backwards compat\n */\nexport const PUSH_SCOPE_ID: unique symbol = Symbol(__DEV__ ? `pushScopeId` : ``)\n/**\n * @deprecated kept for backwards compat\n */\nexport const POP_SCOPE_ID: unique symbol = Symbol(__DEV__ ? `popScopeId` : ``)\nexport const WITH_CTX: unique symbol = Symbol(__DEV__ ? `withCtx` : ``)\nexport const UNREF: unique symbol = Symbol(__DEV__ ? `unref` : ``)\nexport const IS_REF: unique symbol = Symbol(__DEV__ ? `isRef` : ``)\nexport const WITH_MEMO: unique symbol = Symbol(__DEV__ ? `withMemo` : ``)\nexport const IS_MEMO_SAME: unique symbol = Symbol(__DEV__ ? `isMemoSame` : ``)\n\n// Name mapping for runtime helpers that need to be imported from 'vue' in\n// generated code. Make sure these are correctly exported in the runtime!\nexport const helperNameMap: Record<symbol, string> = {\n  [FRAGMENT]: `Fragment`,\n  [TELEPORT]: `Teleport`,\n  [SUSPENSE]: `Suspense`,\n  [KEEP_ALIVE]: `KeepAlive`,\n  [BASE_TRANSITION]: `BaseTransition`,\n  [OPEN_BLOCK]: `openBlock`,\n  [CREATE_BLOCK]: `createBlock`,\n  [CREATE_ELEMENT_BLOCK]: `createElementBlock`,\n  [CREATE_VNODE]: `createVNode`,\n  [CREATE_ELEMENT_VNODE]: `createElementVNode`,\n  [CREATE_COMMENT]: `createCommentVNode`,\n  [CREATE_TEXT]: `createTextVNode`,\n  [CREATE_STATIC]: `createStaticVNode`,\n  [RESOLVE_COMPONENT]: `resolveComponent`,\n  [RESOLVE_DYNAMIC_COMPONENT]: `resolveDynamicComponent`,\n  [RESOLVE_DIRECTIVE]: `resolveDirective`,\n  [RESOLVE_FILTER]: `resolveFilter`,\n  [WITH_DIRECTIVES]: `withDirectives`,\n  [RENDER_LIST]: `renderList`,\n  [RENDER_SLOT]: `renderSlot`,\n  [CREATE_SLOTS]: `createSlots`,\n  [TO_DISPLAY_STRING]: `toDisplayString`,\n  [MERGE_PROPS]: `mergeProps`,\n  [NORMALIZE_CLASS]: `normalizeClass`,\n  [NORMALIZE_STYLE]: `normalizeStyle`,\n  [NORMALIZE_PROPS]: `normalizeProps`,\n  [GUARD_REACTIVE_PROPS]: `guardReactiveProps`,\n  [TO_HANDLERS]: `toHandlers`,\n  [CAMELIZE]: `camelize`,\n  [CAPITALIZE]: `capitalize`,\n  [TO_HANDLER_KEY]: `toHandlerKey`,\n  [SET_BLOCK_TRACKING]: `setBlockTracking`,\n  [PUSH_SCOPE_ID]: `pushScopeId`,\n  [POP_SCOPE_ID]: `popScopeId`,\n  [WITH_CTX]: `withCtx`,\n  [UNREF]: `unref`,\n  [IS_REF]: `isRef`,\n  [WITH_MEMO]: `withMemo`,\n  [IS_MEMO_SAME]: `isMemoSame`,\n}\n\nexport function registerRuntimeHelpers(helpers: Record<symbol, string>): void {\n  Object.getOwnPropertySymbols(helpers).forEach(s => {\n    helperNameMap[s] = helpers[s]\n  })\n}\n"
  },
  {
    "path": "packages/compiler-core/src/tokenizer.ts",
    "content": "/**\n * This Tokenizer is adapted from htmlparser2 under the MIT License listed at\n * https://github.com/fb55/htmlparser2/blob/master/LICENSE\n\nCopyright 2010, 2011, Chris Winberry <chris@winberry.net>. All rights reserved.\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to\ndeal in the Software without restriction, including without limitation the\nrights to use, copy, modify, merge, publish, distribute, sublicense, and/or\nsell copies 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\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\nIN THE SOFTWARE.\n */\n\nimport { ErrorCodes } from './errors'\nimport type { ElementNode, Position } from './ast'\n\n/**\n * Note: entities is a non-browser-build-only dependency.\n * In the browser, we use an HTML element to do the decoding.\n * Make sure all imports from entities are only used in non-browser branches\n * so that it can be properly treeshaken.\n */\nimport {\n  DecodingMode,\n  EntityDecoder,\n  fromCodePoint,\n  htmlDecodeTree,\n} from 'entities/decode'\n\nexport enum ParseMode {\n  BASE,\n  HTML,\n  SFC,\n}\n\nexport enum CharCodes {\n  Tab = 0x9, // \"\\t\"\n  NewLine = 0xa, // \"\\n\"\n  FormFeed = 0xc, // \"\\f\"\n  CarriageReturn = 0xd, // \"\\r\"\n  Space = 0x20, // \" \"\n  ExclamationMark = 0x21, // \"!\"\n  Number = 0x23, // \"#\"\n  Amp = 0x26, // \"&\"\n  SingleQuote = 0x27, // \"'\"\n  DoubleQuote = 0x22, // '\"'\n  GraveAccent = 96, // \"`\"\n  Dash = 0x2d, // \"-\"\n  Slash = 0x2f, // \"/\"\n  Zero = 0x30, // \"0\"\n  Nine = 0x39, // \"9\"\n  Semi = 0x3b, // \";\"\n  Lt = 0x3c, // \"<\"\n  Eq = 0x3d, // \"=\"\n  Gt = 0x3e, // \">\"\n  Questionmark = 0x3f, // \"?\"\n  UpperA = 0x41, // \"A\"\n  LowerA = 0x61, // \"a\"\n  UpperF = 0x46, // \"F\"\n  LowerF = 0x66, // \"f\"\n  UpperZ = 0x5a, // \"Z\"\n  LowerZ = 0x7a, // \"z\"\n  LowerX = 0x78, // \"x\"\n  LowerV = 0x76, // \"v\"\n  Dot = 0x2e, // \".\"\n  Colon = 0x3a, // \":\"\n  At = 0x40, // \"@\"\n  LeftSquare = 91, // \"[\"\n  RightSquare = 93, // \"]\"\n}\n\nconst defaultDelimitersOpen = new Uint8Array([123, 123]) // \"{{\"\nconst defaultDelimitersClose = new Uint8Array([125, 125]) // \"}}\"\n\n/** All the states the tokenizer can be in. */\nexport enum State {\n  Text = 1,\n\n  // interpolation\n  InterpolationOpen,\n  Interpolation,\n  InterpolationClose,\n\n  // Tags\n  BeforeTagName, // After <\n  InTagName,\n  InSelfClosingTag,\n  BeforeClosingTagName,\n  InClosingTagName,\n  AfterClosingTagName,\n\n  // Attrs\n  BeforeAttrName,\n  InAttrName,\n  InDirName,\n  InDirArg,\n  InDirDynamicArg,\n  InDirModifier,\n  AfterAttrName,\n  BeforeAttrValue,\n  InAttrValueDq, // \"\n  InAttrValueSq, // '\n  InAttrValueNq,\n\n  // Declarations\n  BeforeDeclaration, // !\n  InDeclaration,\n\n  // Processing instructions\n  InProcessingInstruction, // ?\n\n  // Comments & CDATA\n  BeforeComment,\n  CDATASequence,\n  InSpecialComment,\n  InCommentLike,\n\n  // Special tags\n  BeforeSpecialS, // Decide if we deal with `<script` or `<style`\n  BeforeSpecialT, // Decide if we deal with `<title` or `<textarea`\n  SpecialStartSequence,\n  InRCDATA,\n\n  InEntity,\n\n  InSFCRootTagName,\n}\n\n/**\n * HTML only allows ASCII alpha characters (a-z and A-Z) at the beginning of a\n * tag name.\n */\nfunction isTagStartChar(c: number): boolean {\n  return (\n    (c >= CharCodes.LowerA && c <= CharCodes.LowerZ) ||\n    (c >= CharCodes.UpperA && c <= CharCodes.UpperZ)\n  )\n}\n\nexport function isWhitespace(c: number): boolean {\n  return (\n    c === CharCodes.Space ||\n    c === CharCodes.NewLine ||\n    c === CharCodes.Tab ||\n    c === CharCodes.FormFeed ||\n    c === CharCodes.CarriageReturn\n  )\n}\n\nfunction isEndOfTagSection(c: number): boolean {\n  return c === CharCodes.Slash || c === CharCodes.Gt || isWhitespace(c)\n}\n\nexport function toCharCodes(str: string): Uint8Array {\n  const ret = new Uint8Array(str.length)\n  for (let i = 0; i < str.length; i++) {\n    ret[i] = str.charCodeAt(i)\n  }\n  return ret\n}\n\nexport enum QuoteType {\n  NoValue = 0,\n  Unquoted = 1,\n  Single = 2,\n  Double = 3,\n}\n\nexport interface Callbacks {\n  ontext(start: number, endIndex: number): void\n  ontextentity(char: string, start: number, endIndex: number): void\n\n  oninterpolation(start: number, endIndex: number): void\n\n  onopentagname(start: number, endIndex: number): void\n  onopentagend(endIndex: number): void\n  onselfclosingtag(endIndex: number): void\n  onclosetag(start: number, endIndex: number): void\n\n  onattribdata(start: number, endIndex: number): void\n  onattribentity(char: string, start: number, end: number): void\n  onattribend(quote: QuoteType, endIndex: number): void\n  onattribname(start: number, endIndex: number): void\n  onattribnameend(endIndex: number): void\n\n  ondirname(start: number, endIndex: number): void\n  ondirarg(start: number, endIndex: number): void\n  ondirmodifier(start: number, endIndex: number): void\n\n  oncomment(start: number, endIndex: number): void\n  oncdata(start: number, endIndex: number): void\n\n  onprocessinginstruction(start: number, endIndex: number): void\n  // ondeclaration(start: number, endIndex: number): void\n  onend(): void\n  onerr(code: ErrorCodes, index: number): void\n}\n\n/**\n * Sequences used to match longer strings.\n *\n * We don't have `Script`, `Style`, or `Title` here. Instead, we re-use the *End\n * sequences with an increased offset.\n */\nexport const Sequences: {\n  Cdata: Uint8Array\n  CdataEnd: Uint8Array\n  CommentEnd: Uint8Array\n  ScriptEnd: Uint8Array\n  StyleEnd: Uint8Array\n  TitleEnd: Uint8Array\n  TextareaEnd: Uint8Array\n} = {\n  Cdata: new Uint8Array([0x43, 0x44, 0x41, 0x54, 0x41, 0x5b]), // CDATA[\n  CdataEnd: new Uint8Array([0x5d, 0x5d, 0x3e]), // ]]>\n  CommentEnd: new Uint8Array([0x2d, 0x2d, 0x3e]), // `-->`\n  ScriptEnd: new Uint8Array([0x3c, 0x2f, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74]), // `</script`\n  StyleEnd: new Uint8Array([0x3c, 0x2f, 0x73, 0x74, 0x79, 0x6c, 0x65]), // `</style`\n  TitleEnd: new Uint8Array([0x3c, 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65]), // `</title`\n  TextareaEnd: new Uint8Array([\n    0x3c, 0x2f, 116, 101, 120, 116, 97, 114, 101, 97,\n  ]), // `</textarea\n}\n\nexport default class Tokenizer {\n  /** The current state the tokenizer is in. */\n  public state: State = State.Text\n  /** The read buffer. */\n  private buffer = ''\n  /** The beginning of the section that is currently being read. */\n  public sectionStart = 0\n  /** The index within the buffer that we are currently looking at. */\n  private index = 0\n  /** The start of the last entity. */\n  private entityStart = 0\n  /** Some behavior, eg. when decoding entities, is done while we are in another state. This keeps track of the other state type. */\n  private baseState = State.Text\n  /** For special parsing behavior inside of script and style tags. */\n  public inRCDATA = false\n  /** For disabling RCDATA tags handling */\n  public inXML = false\n  /** For disabling interpolation parsing in v-pre */\n  public inVPre = false\n  /** Record newline positions for fast line / column calculation */\n  private newlines: number[] = []\n\n  private readonly entityDecoder?: EntityDecoder\n\n  public mode: ParseMode = ParseMode.BASE\n  public get inSFCRoot(): boolean {\n    return this.mode === ParseMode.SFC && this.stack.length === 0\n  }\n\n  constructor(\n    private readonly stack: ElementNode[],\n    private readonly cbs: Callbacks,\n  ) {\n    if (!__BROWSER__) {\n      this.entityDecoder = new EntityDecoder(htmlDecodeTree, (cp, consumed) =>\n        this.emitCodePoint(cp, consumed),\n      )\n    }\n  }\n\n  public reset(): void {\n    this.state = State.Text\n    this.mode = ParseMode.BASE\n    this.buffer = ''\n    this.sectionStart = 0\n    this.index = 0\n    this.baseState = State.Text\n    this.inRCDATA = false\n    this.currentSequence = undefined!\n    this.newlines.length = 0\n    this.delimiterOpen = defaultDelimitersOpen\n    this.delimiterClose = defaultDelimitersClose\n  }\n\n  /**\n   * Generate Position object with line / column information using recorded\n   * newline positions. We know the index is always going to be an already\n   * processed index, so all the newlines up to this index should have been\n   * recorded.\n   */\n  public getPos(index: number): Position {\n    let line = 1\n    let column = index + 1\n    const length = this.newlines.length\n    let j = -1\n    if (length > 100) {\n      let l = -1\n      let r = length\n      while (l + 1 < r) {\n        const m = (l + r) >>> 1\n        this.newlines[m] < index ? (l = m) : (r = m)\n      }\n      j = l\n    } else {\n      for (let i = length - 1; i >= 0; i--) {\n        if (index > this.newlines[i]) {\n          j = i\n          break\n        }\n      }\n    }\n\n    if (j >= 0) {\n      line = j + 2\n      column = index - this.newlines[j]\n    }\n\n    return {\n      column,\n      line,\n      offset: index,\n    }\n  }\n\n  private peek() {\n    return this.buffer.charCodeAt(this.index + 1)\n  }\n\n  private stateText(c: number): void {\n    if (c === CharCodes.Lt) {\n      if (this.index > this.sectionStart) {\n        this.cbs.ontext(this.sectionStart, this.index)\n      }\n      this.state = State.BeforeTagName\n      this.sectionStart = this.index\n    } else if (!__BROWSER__ && c === CharCodes.Amp) {\n      this.startEntity()\n    } else if (!this.inVPre && c === this.delimiterOpen[0]) {\n      this.state = State.InterpolationOpen\n      this.delimiterIndex = 0\n      this.stateInterpolationOpen(c)\n    }\n  }\n\n  public delimiterOpen: Uint8Array = defaultDelimitersOpen\n  public delimiterClose: Uint8Array = defaultDelimitersClose\n  private delimiterIndex = -1\n\n  private stateInterpolationOpen(c: number): void {\n    if (c === this.delimiterOpen[this.delimiterIndex]) {\n      if (this.delimiterIndex === this.delimiterOpen.length - 1) {\n        const start = this.index + 1 - this.delimiterOpen.length\n        if (start > this.sectionStart) {\n          this.cbs.ontext(this.sectionStart, start)\n        }\n        this.state = State.Interpolation\n        this.sectionStart = start\n      } else {\n        this.delimiterIndex++\n      }\n    } else if (this.inRCDATA) {\n      this.state = State.InRCDATA\n      this.stateInRCDATA(c)\n    } else {\n      this.state = State.Text\n      this.stateText(c)\n    }\n  }\n\n  private stateInterpolation(c: number): void {\n    if (c === this.delimiterClose[0]) {\n      this.state = State.InterpolationClose\n      this.delimiterIndex = 0\n      this.stateInterpolationClose(c)\n    }\n  }\n\n  private stateInterpolationClose(c: number) {\n    if (c === this.delimiterClose[this.delimiterIndex]) {\n      if (this.delimiterIndex === this.delimiterClose.length - 1) {\n        this.cbs.oninterpolation(this.sectionStart, this.index + 1)\n        if (this.inRCDATA) {\n          this.state = State.InRCDATA\n        } else {\n          this.state = State.Text\n        }\n        this.sectionStart = this.index + 1\n      } else {\n        this.delimiterIndex++\n      }\n    } else {\n      this.state = State.Interpolation\n      this.stateInterpolation(c)\n    }\n  }\n\n  public currentSequence: Uint8Array = undefined!\n  private sequenceIndex = 0\n  private stateSpecialStartSequence(c: number): void {\n    const isEnd = this.sequenceIndex === this.currentSequence.length\n    const isMatch = isEnd\n      ? // If we are at the end of the sequence, make sure the tag name has ended\n        isEndOfTagSection(c)\n      : // Otherwise, do a case-insensitive comparison\n        (c | 0x20) === this.currentSequence[this.sequenceIndex]\n\n    if (!isMatch) {\n      this.inRCDATA = false\n    } else if (!isEnd) {\n      this.sequenceIndex++\n      return\n    }\n\n    this.sequenceIndex = 0\n    this.state = State.InTagName\n    this.stateInTagName(c)\n  }\n\n  /** Look for an end tag. For <title> and <textarea>, also decode entities. */\n  private stateInRCDATA(c: number): void {\n    if (this.sequenceIndex === this.currentSequence.length) {\n      if (c === CharCodes.Gt || isWhitespace(c)) {\n        const endOfText = this.index - this.currentSequence.length\n\n        if (this.sectionStart < endOfText) {\n          // Spoof the index so that reported locations match up.\n          const actualIndex = this.index\n          this.index = endOfText\n          this.cbs.ontext(this.sectionStart, endOfText)\n          this.index = actualIndex\n        }\n\n        this.sectionStart = endOfText + 2 // Skip over the `</`\n        this.stateInClosingTagName(c)\n        this.inRCDATA = false\n        return // We are done; skip the rest of the function.\n      }\n\n      this.sequenceIndex = 0\n    }\n\n    if ((c | 0x20) === this.currentSequence[this.sequenceIndex]) {\n      this.sequenceIndex += 1\n    } else if (this.sequenceIndex === 0) {\n      if (\n        this.currentSequence === Sequences.TitleEnd ||\n        (this.currentSequence === Sequences.TextareaEnd && !this.inSFCRoot)\n      ) {\n        // We have to parse entities in <title> and <textarea> tags.\n        if (!__BROWSER__ && c === CharCodes.Amp) {\n          this.startEntity()\n        } else if (!this.inVPre && c === this.delimiterOpen[0]) {\n          // We also need to handle interpolation\n          this.state = State.InterpolationOpen\n          this.delimiterIndex = 0\n          this.stateInterpolationOpen(c)\n        }\n      } else if (this.fastForwardTo(CharCodes.Lt)) {\n        // Outside of <title> and <textarea> tags, we can fast-forward.\n        this.sequenceIndex = 1\n      }\n    } else {\n      // If we see a `<`, set the sequence index to 1; useful for eg. `<</script>`.\n      this.sequenceIndex = Number(c === CharCodes.Lt)\n    }\n  }\n\n  private stateCDATASequence(c: number): void {\n    if (c === Sequences.Cdata[this.sequenceIndex]) {\n      if (++this.sequenceIndex === Sequences.Cdata.length) {\n        this.state = State.InCommentLike\n        this.currentSequence = Sequences.CdataEnd\n        this.sequenceIndex = 0\n        this.sectionStart = this.index + 1\n      }\n    } else {\n      this.sequenceIndex = 0\n      this.state = State.InDeclaration\n      this.stateInDeclaration(c) // Reconsume the character\n    }\n  }\n\n  /**\n   * When we wait for one specific character, we can speed things up\n   * by skipping through the buffer until we find it.\n   *\n   * @returns Whether the character was found.\n   */\n  private fastForwardTo(c: number): boolean {\n    while (++this.index < this.buffer.length) {\n      const cc = this.buffer.charCodeAt(this.index)\n      if (cc === CharCodes.NewLine) {\n        this.newlines.push(this.index)\n      }\n      if (cc === c) {\n        return true\n      }\n    }\n\n    /*\n     * We increment the index at the end of the `parse` loop,\n     * so set it to `buffer.length - 1` here.\n     *\n     * TODO: Refactor `parse` to increment index before calling states.\n     */\n    this.index = this.buffer.length - 1\n\n    return false\n  }\n\n  /**\n   * Comments and CDATA end with `-->` and `]]>`.\n   *\n   * Their common qualities are:\n   * - Their end sequences have a distinct character they start with.\n   * - That character is then repeated, so we have to check multiple repeats.\n   * - All characters but the start character of the sequence can be skipped.\n   */\n  private stateInCommentLike(c: number): void {\n    if (c === this.currentSequence[this.sequenceIndex]) {\n      if (++this.sequenceIndex === this.currentSequence.length) {\n        if (this.currentSequence === Sequences.CdataEnd) {\n          this.cbs.oncdata(this.sectionStart, this.index - 2)\n        } else {\n          this.cbs.oncomment(this.sectionStart, this.index - 2)\n        }\n\n        this.sequenceIndex = 0\n        this.sectionStart = this.index + 1\n        this.state = State.Text\n      }\n    } else if (this.sequenceIndex === 0) {\n      // Fast-forward to the first character of the sequence\n      if (this.fastForwardTo(this.currentSequence[0])) {\n        this.sequenceIndex = 1\n      }\n    } else if (c !== this.currentSequence[this.sequenceIndex - 1]) {\n      // Allow long sequences, eg. --->, ]]]>\n      this.sequenceIndex = 0\n    }\n  }\n\n  private startSpecial(sequence: Uint8Array, offset: number) {\n    this.enterRCDATA(sequence, offset)\n    this.state = State.SpecialStartSequence\n  }\n\n  public enterRCDATA(sequence: Uint8Array, offset: number): void {\n    this.inRCDATA = true\n    this.currentSequence = sequence\n    this.sequenceIndex = offset\n  }\n\n  private stateBeforeTagName(c: number): void {\n    if (c === CharCodes.ExclamationMark) {\n      this.state = State.BeforeDeclaration\n      this.sectionStart = this.index + 1\n    } else if (c === CharCodes.Questionmark) {\n      this.state = State.InProcessingInstruction\n      this.sectionStart = this.index + 1\n    } else if (isTagStartChar(c)) {\n      this.sectionStart = this.index\n      if (this.mode === ParseMode.BASE) {\n        // no special tags in base mode\n        this.state = State.InTagName\n      } else if (this.inSFCRoot) {\n        // SFC mode + root level\n        // - everything except <template> is RAWTEXT\n        // - <template> with lang other than html is also RAWTEXT\n        this.state = State.InSFCRootTagName\n      } else if (!this.inXML) {\n        // HTML mode\n        // - <script>, <style> RAWTEXT\n        // - <title>, <textarea> RCDATA\n        if (c === 116 /* t */) {\n          this.state = State.BeforeSpecialT\n        } else {\n          this.state =\n            c === 115 /* s */ ? State.BeforeSpecialS : State.InTagName\n        }\n      } else {\n        this.state = State.InTagName\n      }\n    } else if (c === CharCodes.Slash) {\n      this.state = State.BeforeClosingTagName\n    } else {\n      this.state = State.Text\n      this.stateText(c)\n    }\n  }\n  private stateInTagName(c: number): void {\n    if (isEndOfTagSection(c)) {\n      this.handleTagName(c)\n    }\n  }\n  private stateInSFCRootTagName(c: number): void {\n    if (isEndOfTagSection(c)) {\n      const tag = this.buffer.slice(this.sectionStart, this.index)\n      if (tag !== 'template') {\n        this.enterRCDATA(toCharCodes(`</` + tag), 0)\n      }\n      this.handleTagName(c)\n    }\n  }\n  private handleTagName(c: number) {\n    this.cbs.onopentagname(this.sectionStart, this.index)\n    this.sectionStart = -1\n    this.state = State.BeforeAttrName\n    this.stateBeforeAttrName(c)\n  }\n  private stateBeforeClosingTagName(c: number): void {\n    if (isWhitespace(c)) {\n      // Ignore\n    } else if (c === CharCodes.Gt) {\n      if (__DEV__ || !__BROWSER__) {\n        this.cbs.onerr(ErrorCodes.MISSING_END_TAG_NAME, this.index)\n      }\n      this.state = State.Text\n      // Ignore\n      this.sectionStart = this.index + 1\n    } else {\n      this.state = isTagStartChar(c)\n        ? State.InClosingTagName\n        : State.InSpecialComment\n      this.sectionStart = this.index\n    }\n  }\n  private stateInClosingTagName(c: number): void {\n    if (c === CharCodes.Gt || isWhitespace(c)) {\n      this.cbs.onclosetag(this.sectionStart, this.index)\n      this.sectionStart = -1\n      this.state = State.AfterClosingTagName\n      this.stateAfterClosingTagName(c)\n    }\n  }\n  private stateAfterClosingTagName(c: number): void {\n    // Skip everything until \">\"\n    if (c === CharCodes.Gt) {\n      this.state = State.Text\n      this.sectionStart = this.index + 1\n    }\n  }\n  private stateBeforeAttrName(c: number): void {\n    if (c === CharCodes.Gt) {\n      this.cbs.onopentagend(this.index)\n      if (this.inRCDATA) {\n        this.state = State.InRCDATA\n      } else {\n        this.state = State.Text\n      }\n      this.sectionStart = this.index + 1\n    } else if (c === CharCodes.Slash) {\n      this.state = State.InSelfClosingTag\n      if ((__DEV__ || !__BROWSER__) && this.peek() !== CharCodes.Gt) {\n        this.cbs.onerr(ErrorCodes.UNEXPECTED_SOLIDUS_IN_TAG, this.index)\n      }\n    } else if (c === CharCodes.Lt && this.peek() === CharCodes.Slash) {\n      // special handling for </ appearing in open tag state\n      // this is different from standard HTML parsing but makes practical sense\n      // especially for parsing intermediate input state in IDEs.\n      this.cbs.onopentagend(this.index)\n      this.state = State.BeforeTagName\n      this.sectionStart = this.index\n    } else if (!isWhitespace(c)) {\n      if ((__DEV__ || !__BROWSER__) && c === CharCodes.Eq) {\n        this.cbs.onerr(\n          ErrorCodes.UNEXPECTED_EQUALS_SIGN_BEFORE_ATTRIBUTE_NAME,\n          this.index,\n        )\n      }\n      this.handleAttrStart(c)\n    }\n  }\n  private handleAttrStart(c: number) {\n    if (c === CharCodes.LowerV && this.peek() === CharCodes.Dash) {\n      this.state = State.InDirName\n      this.sectionStart = this.index\n    } else if (\n      c === CharCodes.Dot ||\n      c === CharCodes.Colon ||\n      c === CharCodes.At ||\n      c === CharCodes.Number\n    ) {\n      this.cbs.ondirname(this.index, this.index + 1)\n      this.state = State.InDirArg\n      this.sectionStart = this.index + 1\n    } else {\n      this.state = State.InAttrName\n      this.sectionStart = this.index\n    }\n  }\n  private stateInSelfClosingTag(c: number): void {\n    if (c === CharCodes.Gt) {\n      this.cbs.onselfclosingtag(this.index)\n      this.state = State.Text\n      this.sectionStart = this.index + 1\n      this.inRCDATA = false // Reset special state, in case of self-closing special tags\n    } else if (!isWhitespace(c)) {\n      this.state = State.BeforeAttrName\n      this.stateBeforeAttrName(c)\n    }\n  }\n  private stateInAttrName(c: number): void {\n    if (c === CharCodes.Eq || isEndOfTagSection(c)) {\n      this.cbs.onattribname(this.sectionStart, this.index)\n      this.handleAttrNameEnd(c)\n    } else if (\n      (__DEV__ || !__BROWSER__) &&\n      (c === CharCodes.DoubleQuote ||\n        c === CharCodes.SingleQuote ||\n        c === CharCodes.Lt)\n    ) {\n      this.cbs.onerr(\n        ErrorCodes.UNEXPECTED_CHARACTER_IN_ATTRIBUTE_NAME,\n        this.index,\n      )\n    }\n  }\n  private stateInDirName(c: number): void {\n    if (c === CharCodes.Eq || isEndOfTagSection(c)) {\n      this.cbs.ondirname(this.sectionStart, this.index)\n      this.handleAttrNameEnd(c)\n    } else if (c === CharCodes.Colon) {\n      this.cbs.ondirname(this.sectionStart, this.index)\n      this.state = State.InDirArg\n      this.sectionStart = this.index + 1\n    } else if (c === CharCodes.Dot) {\n      this.cbs.ondirname(this.sectionStart, this.index)\n      this.state = State.InDirModifier\n      this.sectionStart = this.index + 1\n    }\n  }\n  private stateInDirArg(c: number): void {\n    if (c === CharCodes.Eq || isEndOfTagSection(c)) {\n      this.cbs.ondirarg(this.sectionStart, this.index)\n      this.handleAttrNameEnd(c)\n    } else if (c === CharCodes.LeftSquare) {\n      this.state = State.InDirDynamicArg\n    } else if (c === CharCodes.Dot) {\n      this.cbs.ondirarg(this.sectionStart, this.index)\n      this.state = State.InDirModifier\n      this.sectionStart = this.index + 1\n    }\n  }\n  private stateInDynamicDirArg(c: number): void {\n    if (c === CharCodes.RightSquare) {\n      this.state = State.InDirArg\n    } else if (c === CharCodes.Eq || isEndOfTagSection(c)) {\n      this.cbs.ondirarg(this.sectionStart, this.index + 1)\n      this.handleAttrNameEnd(c)\n      if (__DEV__ || !__BROWSER__) {\n        this.cbs.onerr(\n          ErrorCodes.X_MISSING_DYNAMIC_DIRECTIVE_ARGUMENT_END,\n          this.index,\n        )\n      }\n    }\n  }\n  private stateInDirModifier(c: number): void {\n    if (c === CharCodes.Eq || isEndOfTagSection(c)) {\n      this.cbs.ondirmodifier(this.sectionStart, this.index)\n      this.handleAttrNameEnd(c)\n    } else if (c === CharCodes.Dot) {\n      this.cbs.ondirmodifier(this.sectionStart, this.index)\n      this.sectionStart = this.index + 1\n    }\n  }\n  private handleAttrNameEnd(c: number): void {\n    this.sectionStart = this.index\n    this.state = State.AfterAttrName\n    this.cbs.onattribnameend(this.index)\n    this.stateAfterAttrName(c)\n  }\n  private stateAfterAttrName(c: number): void {\n    if (c === CharCodes.Eq) {\n      this.state = State.BeforeAttrValue\n    } else if (c === CharCodes.Slash || c === CharCodes.Gt) {\n      this.cbs.onattribend(QuoteType.NoValue, this.sectionStart)\n      this.sectionStart = -1\n      this.state = State.BeforeAttrName\n      this.stateBeforeAttrName(c)\n    } else if (!isWhitespace(c)) {\n      this.cbs.onattribend(QuoteType.NoValue, this.sectionStart)\n      this.handleAttrStart(c)\n    }\n  }\n  private stateBeforeAttrValue(c: number): void {\n    if (c === CharCodes.DoubleQuote) {\n      this.state = State.InAttrValueDq\n      this.sectionStart = this.index + 1\n    } else if (c === CharCodes.SingleQuote) {\n      this.state = State.InAttrValueSq\n      this.sectionStart = this.index + 1\n    } else if (!isWhitespace(c)) {\n      this.sectionStart = this.index\n      this.state = State.InAttrValueNq\n      this.stateInAttrValueNoQuotes(c) // Reconsume token\n    }\n  }\n  private handleInAttrValue(c: number, quote: number) {\n    if (c === quote || (__BROWSER__ && this.fastForwardTo(quote))) {\n      this.cbs.onattribdata(this.sectionStart, this.index)\n      this.sectionStart = -1\n      this.cbs.onattribend(\n        quote === CharCodes.DoubleQuote ? QuoteType.Double : QuoteType.Single,\n        this.index + 1,\n      )\n      this.state = State.BeforeAttrName\n    } else if (!__BROWSER__ && c === CharCodes.Amp) {\n      this.startEntity()\n    }\n  }\n  private stateInAttrValueDoubleQuotes(c: number): void {\n    this.handleInAttrValue(c, CharCodes.DoubleQuote)\n  }\n  private stateInAttrValueSingleQuotes(c: number): void {\n    this.handleInAttrValue(c, CharCodes.SingleQuote)\n  }\n  private stateInAttrValueNoQuotes(c: number): void {\n    if (isWhitespace(c) || c === CharCodes.Gt) {\n      this.cbs.onattribdata(this.sectionStart, this.index)\n      this.sectionStart = -1\n      this.cbs.onattribend(QuoteType.Unquoted, this.index)\n      this.state = State.BeforeAttrName\n      this.stateBeforeAttrName(c)\n    } else if (\n      ((__DEV__ || !__BROWSER__) && c === CharCodes.DoubleQuote) ||\n      c === CharCodes.SingleQuote ||\n      c === CharCodes.Lt ||\n      c === CharCodes.Eq ||\n      c === CharCodes.GraveAccent\n    ) {\n      this.cbs.onerr(\n        ErrorCodes.UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_VALUE,\n        this.index,\n      )\n    } else if (!__BROWSER__ && c === CharCodes.Amp) {\n      this.startEntity()\n    }\n  }\n  private stateBeforeDeclaration(c: number): void {\n    if (c === CharCodes.LeftSquare) {\n      this.state = State.CDATASequence\n      this.sequenceIndex = 0\n    } else {\n      this.state =\n        c === CharCodes.Dash ? State.BeforeComment : State.InDeclaration\n    }\n  }\n  private stateInDeclaration(c: number): void {\n    if (c === CharCodes.Gt || this.fastForwardTo(CharCodes.Gt)) {\n      // this.cbs.ondeclaration(this.sectionStart, this.index)\n      this.state = State.Text\n      this.sectionStart = this.index + 1\n    }\n  }\n  private stateInProcessingInstruction(c: number): void {\n    if (c === CharCodes.Gt || this.fastForwardTo(CharCodes.Gt)) {\n      this.cbs.onprocessinginstruction(this.sectionStart, this.index)\n      this.state = State.Text\n      this.sectionStart = this.index + 1\n    }\n  }\n  private stateBeforeComment(c: number): void {\n    if (c === CharCodes.Dash) {\n      this.state = State.InCommentLike\n      this.currentSequence = Sequences.CommentEnd\n      // Allow short comments (eg. <!-->)\n      this.sequenceIndex = 2\n      this.sectionStart = this.index + 1\n    } else {\n      this.state = State.InDeclaration\n    }\n  }\n  private stateInSpecialComment(c: number): void {\n    if (c === CharCodes.Gt || this.fastForwardTo(CharCodes.Gt)) {\n      this.cbs.oncomment(this.sectionStart, this.index)\n      this.state = State.Text\n      this.sectionStart = this.index + 1\n    }\n  }\n  private stateBeforeSpecialS(c: number): void {\n    if (c === Sequences.ScriptEnd[3]) {\n      this.startSpecial(Sequences.ScriptEnd, 4)\n    } else if (c === Sequences.StyleEnd[3]) {\n      this.startSpecial(Sequences.StyleEnd, 4)\n    } else {\n      this.state = State.InTagName\n      this.stateInTagName(c) // Consume the token again\n    }\n  }\n  private stateBeforeSpecialT(c: number): void {\n    if (c === Sequences.TitleEnd[3]) {\n      this.startSpecial(Sequences.TitleEnd, 4)\n    } else if (c === Sequences.TextareaEnd[3]) {\n      this.startSpecial(Sequences.TextareaEnd, 4)\n    } else {\n      this.state = State.InTagName\n      this.stateInTagName(c) // Consume the token again\n    }\n  }\n\n  private startEntity() {\n    if (!__BROWSER__) {\n      this.baseState = this.state\n      this.state = State.InEntity\n      this.entityStart = this.index\n      this.entityDecoder!.startEntity(\n        this.baseState === State.Text || this.baseState === State.InRCDATA\n          ? DecodingMode.Legacy\n          : DecodingMode.Attribute,\n      )\n    }\n  }\n\n  private stateInEntity(): void {\n    if (!__BROWSER__) {\n      const length = this.entityDecoder!.write(this.buffer, this.index)\n\n      // If `length` is positive, we are done with the entity.\n      if (length >= 0) {\n        this.state = this.baseState\n\n        if (length === 0) {\n          this.index = this.entityStart\n        }\n      } else {\n        // Mark buffer as consumed.\n        this.index = this.buffer.length - 1\n      }\n    }\n  }\n\n  /**\n   * Iterates through the buffer, calling the function corresponding to the current state.\n   *\n   * States that are more likely to be hit are higher up, as a performance improvement.\n   */\n  public parse(input: string): void {\n    this.buffer = input\n    while (this.index < this.buffer.length) {\n      const c = this.buffer.charCodeAt(this.index)\n      if (c === CharCodes.NewLine && this.state !== State.InEntity) {\n        this.newlines.push(this.index)\n      }\n      switch (this.state) {\n        case State.Text: {\n          this.stateText(c)\n          break\n        }\n        case State.InterpolationOpen: {\n          this.stateInterpolationOpen(c)\n          break\n        }\n        case State.Interpolation: {\n          this.stateInterpolation(c)\n          break\n        }\n        case State.InterpolationClose: {\n          this.stateInterpolationClose(c)\n          break\n        }\n        case State.SpecialStartSequence: {\n          this.stateSpecialStartSequence(c)\n          break\n        }\n        case State.InRCDATA: {\n          this.stateInRCDATA(c)\n          break\n        }\n        case State.CDATASequence: {\n          this.stateCDATASequence(c)\n          break\n        }\n        case State.InAttrValueDq: {\n          this.stateInAttrValueDoubleQuotes(c)\n          break\n        }\n        case State.InAttrName: {\n          this.stateInAttrName(c)\n          break\n        }\n        case State.InDirName: {\n          this.stateInDirName(c)\n          break\n        }\n        case State.InDirArg: {\n          this.stateInDirArg(c)\n          break\n        }\n        case State.InDirDynamicArg: {\n          this.stateInDynamicDirArg(c)\n          break\n        }\n        case State.InDirModifier: {\n          this.stateInDirModifier(c)\n          break\n        }\n        case State.InCommentLike: {\n          this.stateInCommentLike(c)\n          break\n        }\n        case State.InSpecialComment: {\n          this.stateInSpecialComment(c)\n          break\n        }\n        case State.BeforeAttrName: {\n          this.stateBeforeAttrName(c)\n          break\n        }\n        case State.InTagName: {\n          this.stateInTagName(c)\n          break\n        }\n        case State.InSFCRootTagName: {\n          this.stateInSFCRootTagName(c)\n          break\n        }\n        case State.InClosingTagName: {\n          this.stateInClosingTagName(c)\n          break\n        }\n        case State.BeforeTagName: {\n          this.stateBeforeTagName(c)\n          break\n        }\n        case State.AfterAttrName: {\n          this.stateAfterAttrName(c)\n          break\n        }\n        case State.InAttrValueSq: {\n          this.stateInAttrValueSingleQuotes(c)\n          break\n        }\n        case State.BeforeAttrValue: {\n          this.stateBeforeAttrValue(c)\n          break\n        }\n        case State.BeforeClosingTagName: {\n          this.stateBeforeClosingTagName(c)\n          break\n        }\n        case State.AfterClosingTagName: {\n          this.stateAfterClosingTagName(c)\n          break\n        }\n        case State.BeforeSpecialS: {\n          this.stateBeforeSpecialS(c)\n          break\n        }\n        case State.BeforeSpecialT: {\n          this.stateBeforeSpecialT(c)\n          break\n        }\n        case State.InAttrValueNq: {\n          this.stateInAttrValueNoQuotes(c)\n          break\n        }\n        case State.InSelfClosingTag: {\n          this.stateInSelfClosingTag(c)\n          break\n        }\n        case State.InDeclaration: {\n          this.stateInDeclaration(c)\n          break\n        }\n        case State.BeforeDeclaration: {\n          this.stateBeforeDeclaration(c)\n          break\n        }\n        case State.BeforeComment: {\n          this.stateBeforeComment(c)\n          break\n        }\n        case State.InProcessingInstruction: {\n          this.stateInProcessingInstruction(c)\n          break\n        }\n        case State.InEntity: {\n          this.stateInEntity()\n          break\n        }\n      }\n      this.index++\n    }\n    this.cleanup()\n    this.finish()\n  }\n\n  /**\n   * Remove data that has already been consumed from the buffer.\n   */\n  private cleanup() {\n    // If we are inside of text or attributes, emit what we already have.\n    if (this.sectionStart !== this.index) {\n      if (\n        this.state === State.Text ||\n        (this.state === State.InRCDATA && this.sequenceIndex === 0)\n      ) {\n        this.cbs.ontext(this.sectionStart, this.index)\n        this.sectionStart = this.index\n      } else if (\n        this.state === State.InAttrValueDq ||\n        this.state === State.InAttrValueSq ||\n        this.state === State.InAttrValueNq\n      ) {\n        this.cbs.onattribdata(this.sectionStart, this.index)\n        this.sectionStart = this.index\n      }\n    }\n  }\n\n  private finish() {\n    if (!__BROWSER__ && this.state === State.InEntity) {\n      this.entityDecoder!.end()\n      this.state = this.baseState\n    }\n\n    this.handleTrailingData()\n\n    this.cbs.onend()\n  }\n\n  /** Handle any trailing data. */\n  private handleTrailingData() {\n    const endIndex = this.buffer.length\n\n    // If there is no remaining data, we are done.\n    if (this.sectionStart >= endIndex) {\n      return\n    }\n\n    if (this.state === State.InCommentLike) {\n      if (this.currentSequence === Sequences.CdataEnd) {\n        this.cbs.oncdata(this.sectionStart, endIndex)\n      } else {\n        this.cbs.oncomment(this.sectionStart, endIndex)\n      }\n    } else if (\n      this.state === State.InTagName ||\n      this.state === State.BeforeAttrName ||\n      this.state === State.BeforeAttrValue ||\n      this.state === State.AfterAttrName ||\n      this.state === State.InAttrName ||\n      this.state === State.InDirName ||\n      this.state === State.InDirArg ||\n      this.state === State.InDirDynamicArg ||\n      this.state === State.InDirModifier ||\n      this.state === State.InAttrValueSq ||\n      this.state === State.InAttrValueDq ||\n      this.state === State.InAttrValueNq ||\n      this.state === State.InClosingTagName\n    ) {\n      /*\n       * If we are currently in an opening or closing tag, us not calling the\n       * respective callback signals that the tag should be ignored.\n       */\n    } else {\n      this.cbs.ontext(this.sectionStart, endIndex)\n    }\n  }\n\n  private emitCodePoint(cp: number, consumed: number): void {\n    if (!__BROWSER__) {\n      if (this.baseState !== State.Text && this.baseState !== State.InRCDATA) {\n        if (this.sectionStart < this.entityStart) {\n          this.cbs.onattribdata(this.sectionStart, this.entityStart)\n        }\n        this.sectionStart = this.entityStart + consumed\n        this.index = this.sectionStart - 1\n\n        this.cbs.onattribentity(\n          fromCodePoint(cp),\n          this.entityStart,\n          this.sectionStart,\n        )\n      } else {\n        if (this.sectionStart < this.entityStart) {\n          this.cbs.ontext(this.sectionStart, this.entityStart)\n        }\n        this.sectionStart = this.entityStart + consumed\n        this.index = this.sectionStart - 1\n\n        this.cbs.ontextentity(\n          fromCodePoint(cp),\n          this.entityStart,\n          this.sectionStart,\n        )\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "packages/compiler-core/src/transform.ts",
    "content": "import type { TransformOptions } from './options'\nimport {\n  type ArrayExpression,\n  type CacheExpression,\n  ConstantTypes,\n  type DirectiveNode,\n  type ElementNode,\n  ElementTypes,\n  type ExpressionNode,\n  type JSChildNode,\n  NodeTypes,\n  type ParentNode,\n  type Property,\n  type RootNode,\n  type SimpleExpressionNode,\n  type TemplateChildNode,\n  type TemplateLiteral,\n  convertToBlock,\n  createCacheExpression,\n  createSimpleExpression,\n  createVNodeCall,\n} from './ast'\nimport {\n  EMPTY_OBJ,\n  NOOP,\n  PatchFlags,\n  camelize,\n  capitalize,\n  isArray,\n  isString,\n} from '@vue/shared'\nimport { defaultOnError, defaultOnWarn } from './errors'\nimport {\n  CREATE_COMMENT,\n  FRAGMENT,\n  TO_DISPLAY_STRING,\n  helperNameMap,\n} from './runtimeHelpers'\nimport { isVSlot } from './utils'\nimport { cacheStatic, getSingleElementRoot } from './transforms/cacheStatic'\nimport type { CompilerCompatOptions } from './compat/compatConfig'\n\n// There are two types of transforms:\n//\n// - NodeTransform:\n//   Transforms that operate directly on a ChildNode. NodeTransforms may mutate,\n//   replace or remove the node being processed.\nexport type NodeTransform = (\n  node: RootNode | TemplateChildNode,\n  context: TransformContext,\n) => void | (() => void) | (() => void)[]\n\n// - DirectiveTransform:\n//   Transforms that handles a single directive attribute on an element.\n//   It translates the raw directive into actual props for the VNode.\nexport type DirectiveTransform = (\n  dir: DirectiveNode,\n  node: ElementNode,\n  context: TransformContext,\n  // a platform specific compiler can import the base transform and augment\n  // it by passing in this optional argument.\n  augmentor?: (ret: DirectiveTransformResult) => DirectiveTransformResult,\n) => DirectiveTransformResult\n\nexport interface DirectiveTransformResult {\n  props: Property[]\n  needRuntime?: boolean | symbol\n  ssrTagParts?: TemplateLiteral['elements']\n}\n\n// A structural directive transform is technically also a NodeTransform;\n// Only v-if and v-for fall into this category.\nexport type StructuralDirectiveTransform = (\n  node: ElementNode,\n  dir: DirectiveNode,\n  context: TransformContext,\n) => void | (() => void)\n\nexport interface ImportItem {\n  exp: string | ExpressionNode\n  path: string\n}\n\nexport interface TransformContext\n  extends\n    Required<Omit<TransformOptions, keyof CompilerCompatOptions>>,\n    CompilerCompatOptions {\n  selfName: string | null\n  root: RootNode\n  helpers: Map<symbol, number>\n  components: Set<string>\n  directives: Set<string>\n  hoists: (JSChildNode | null)[]\n  imports: ImportItem[]\n  temps: number\n  cached: (CacheExpression | null)[]\n  identifiers: { [name: string]: number | undefined }\n  scopes: {\n    vFor: number\n    vSlot: number\n    vPre: number\n    vOnce: number\n  }\n  parent: ParentNode | null\n  // we could use a stack but in practice we've only ever needed two layers up\n  // so this is more efficient\n  grandParent: ParentNode | null\n  childIndex: number\n  currentNode: RootNode | TemplateChildNode | null\n  inVOnce: boolean\n  helper<T extends symbol>(name: T): T\n  removeHelper<T extends symbol>(name: T): void\n  helperString(name: symbol): string\n  replaceNode(node: TemplateChildNode): void\n  removeNode(node?: TemplateChildNode): void\n  onNodeRemoved(): void\n  addIdentifiers(exp: ExpressionNode | string): void\n  removeIdentifiers(exp: ExpressionNode | string): void\n  hoist(exp: string | JSChildNode | ArrayExpression): SimpleExpressionNode\n  cache(exp: JSChildNode, isVNode?: boolean, inVOnce?: boolean): CacheExpression\n  constantCache: WeakMap<TemplateChildNode, ConstantTypes>\n\n  // 2.x Compat only\n  filters?: Set<string>\n}\n\nexport function createTransformContext(\n  root: RootNode,\n  {\n    filename = '',\n    prefixIdentifiers = false,\n    hoistStatic = false,\n    hmr = false,\n    cacheHandlers = false,\n    nodeTransforms = [],\n    directiveTransforms = {},\n    transformHoist = null,\n    isBuiltInComponent = NOOP,\n    isCustomElement = NOOP,\n    expressionPlugins = [],\n    scopeId = null,\n    slotted = true,\n    ssr = false,\n    inSSR = false,\n    ssrCssVars = ``,\n    bindingMetadata = EMPTY_OBJ,\n    inline = false,\n    isTS = false,\n    onError = defaultOnError,\n    onWarn = defaultOnWarn,\n    compatConfig,\n  }: TransformOptions,\n): TransformContext {\n  const nameMatch = filename.replace(/\\?.*$/, '').match(/([^/\\\\]+)\\.\\w+$/)\n  const context: TransformContext = {\n    // options\n    filename,\n    selfName: nameMatch && capitalize(camelize(nameMatch[1])),\n    prefixIdentifiers,\n    hoistStatic,\n    hmr,\n    cacheHandlers,\n    nodeTransforms,\n    directiveTransforms,\n    transformHoist,\n    isBuiltInComponent,\n    isCustomElement,\n    expressionPlugins,\n    scopeId,\n    slotted,\n    ssr,\n    inSSR,\n    ssrCssVars,\n    bindingMetadata,\n    inline,\n    isTS,\n    onError,\n    onWarn,\n    compatConfig,\n\n    // state\n    root,\n    helpers: new Map(),\n    components: new Set(),\n    directives: new Set(),\n    hoists: [],\n    imports: [],\n    cached: [],\n    constantCache: new WeakMap(),\n    temps: 0,\n    identifiers: Object.create(null),\n    scopes: {\n      vFor: 0,\n      vSlot: 0,\n      vPre: 0,\n      vOnce: 0,\n    },\n    parent: null,\n    grandParent: null,\n    currentNode: root,\n    childIndex: 0,\n    inVOnce: false,\n\n    // methods\n    helper(name) {\n      const count = context.helpers.get(name) || 0\n      context.helpers.set(name, count + 1)\n      return name\n    },\n    removeHelper(name) {\n      const count = context.helpers.get(name)\n      if (count) {\n        const currentCount = count - 1\n        if (!currentCount) {\n          context.helpers.delete(name)\n        } else {\n          context.helpers.set(name, currentCount)\n        }\n      }\n    },\n    helperString(name) {\n      return `_${helperNameMap[context.helper(name)]}`\n    },\n    replaceNode(node) {\n      /* v8 ignore start */\n      if (__DEV__) {\n        if (!context.currentNode) {\n          throw new Error(`Node being replaced is already removed.`)\n        }\n        if (!context.parent) {\n          throw new Error(`Cannot replace root node.`)\n        }\n      }\n      /* v8 ignore stop */\n      context.parent!.children[context.childIndex] = context.currentNode = node\n    },\n    removeNode(node) {\n      /* v8 ignore next 3 */\n      if (__DEV__ && !context.parent) {\n        throw new Error(`Cannot remove root node.`)\n      }\n      const list = context.parent!.children\n      const removalIndex = node\n        ? list.indexOf(node)\n        : context.currentNode\n          ? context.childIndex\n          : -1\n      /* v8 ignore next 3 */\n      if (__DEV__ && removalIndex < 0) {\n        throw new Error(`node being removed is not a child of current parent`)\n      }\n      if (!node || node === context.currentNode) {\n        // current node removed\n        context.currentNode = null\n        context.onNodeRemoved()\n      } else {\n        // sibling node removed\n        if (context.childIndex > removalIndex) {\n          context.childIndex--\n          context.onNodeRemoved()\n        }\n      }\n      context.parent!.children.splice(removalIndex, 1)\n    },\n    onNodeRemoved: NOOP,\n    addIdentifiers(exp) {\n      // identifier tracking only happens in non-browser builds.\n      if (!__BROWSER__) {\n        if (isString(exp)) {\n          addId(exp)\n        } else if (exp.identifiers) {\n          exp.identifiers.forEach(addId)\n        } else if (exp.type === NodeTypes.SIMPLE_EXPRESSION) {\n          addId(exp.content)\n        }\n      }\n    },\n    removeIdentifiers(exp) {\n      if (!__BROWSER__) {\n        if (isString(exp)) {\n          removeId(exp)\n        } else if (exp.identifiers) {\n          exp.identifiers.forEach(removeId)\n        } else if (exp.type === NodeTypes.SIMPLE_EXPRESSION) {\n          removeId(exp.content)\n        }\n      }\n    },\n    hoist(exp) {\n      if (isString(exp)) exp = createSimpleExpression(exp)\n      context.hoists.push(exp)\n      const identifier = createSimpleExpression(\n        `_hoisted_${context.hoists.length}`,\n        false,\n        exp.loc,\n        ConstantTypes.CAN_CACHE,\n      )\n      identifier.hoisted = exp\n      return identifier\n    },\n    cache(exp, isVNode = false, inVOnce = false) {\n      const cacheExp = createCacheExpression(\n        context.cached.length,\n        exp,\n        isVNode,\n        inVOnce,\n      )\n      context.cached.push(cacheExp)\n      return cacheExp\n    },\n  }\n\n  if (__COMPAT__) {\n    context.filters = new Set()\n  }\n\n  function addId(id: string) {\n    const { identifiers } = context\n    if (identifiers[id] === undefined) {\n      identifiers[id] = 0\n    }\n    identifiers[id]!++\n  }\n\n  function removeId(id: string) {\n    context.identifiers[id]!--\n  }\n\n  return context\n}\n\nexport function transform(root: RootNode, options: TransformOptions): void {\n  const context = createTransformContext(root, options)\n  traverseNode(root, context)\n  if (options.hoistStatic) {\n    cacheStatic(root, context)\n  }\n  if (!options.ssr) {\n    createRootCodegen(root, context)\n  }\n  // finalize meta information\n  root.helpers = new Set([...context.helpers.keys()])\n  root.components = [...context.components]\n  root.directives = [...context.directives]\n  root.imports = context.imports\n  root.hoists = context.hoists\n  root.temps = context.temps\n  root.cached = context.cached\n  root.transformed = true\n\n  if (__COMPAT__) {\n    root.filters = [...context.filters!]\n  }\n}\n\nfunction createRootCodegen(root: RootNode, context: TransformContext) {\n  const { helper } = context\n  const { children } = root\n  if (children.length === 1) {\n    const singleElementRootChild = getSingleElementRoot(root)\n    // if the single child is an element, turn it into a block.\n    if (singleElementRootChild && singleElementRootChild.codegenNode) {\n      // single element root is never hoisted so codegenNode will never be\n      // SimpleExpressionNode\n      const codegenNode = singleElementRootChild.codegenNode\n      if (codegenNode.type === NodeTypes.VNODE_CALL) {\n        convertToBlock(codegenNode, context)\n      }\n      root.codegenNode = codegenNode\n    } else {\n      // - single <slot/>, IfNode, ForNode: already blocks.\n      // - single text node: always patched.\n      // root codegen falls through via genNode()\n      root.codegenNode = children[0]\n    }\n  } else if (children.length > 1) {\n    // root has multiple nodes - return a fragment block.\n    let patchFlag = PatchFlags.STABLE_FRAGMENT\n    // check if the fragment actually contains a single valid child with\n    // the rest being comments\n    if (\n      __DEV__ &&\n      children.filter(c => c.type !== NodeTypes.COMMENT).length === 1\n    ) {\n      patchFlag |= PatchFlags.DEV_ROOT_FRAGMENT\n    }\n    root.codegenNode = createVNodeCall(\n      context,\n      helper(FRAGMENT),\n      undefined,\n      root.children,\n      patchFlag,\n      undefined,\n      undefined,\n      true,\n      undefined,\n      false /* isComponent */,\n    )\n  } else {\n    // no children = noop. codegen will return null.\n  }\n}\n\nexport function traverseChildren(\n  parent: ParentNode,\n  context: TransformContext,\n): void {\n  let i = 0\n  const nodeRemoved = () => {\n    i--\n  }\n  for (; i < parent.children.length; i++) {\n    const child = parent.children[i]\n    if (isString(child)) continue\n    context.grandParent = context.parent\n    context.parent = parent\n    context.childIndex = i\n    context.onNodeRemoved = nodeRemoved\n    traverseNode(child, context)\n  }\n}\n\nexport function traverseNode(\n  node: RootNode | TemplateChildNode,\n  context: TransformContext,\n): void {\n  context.currentNode = node\n  // apply transform plugins\n  const { nodeTransforms } = context\n  const exitFns = []\n  for (let i = 0; i < nodeTransforms.length; i++) {\n    const onExit = nodeTransforms[i](node, context)\n    if (onExit) {\n      if (isArray(onExit)) {\n        exitFns.push(...onExit)\n      } else {\n        exitFns.push(onExit)\n      }\n    }\n    if (!context.currentNode) {\n      // node was removed\n      return\n    } else {\n      // node may have been replaced\n      node = context.currentNode\n    }\n  }\n\n  switch (node.type) {\n    case NodeTypes.COMMENT:\n      if (!context.ssr) {\n        // inject import for the Comment symbol, which is needed for creating\n        // comment nodes with `createVNode`\n        context.helper(CREATE_COMMENT)\n      }\n      break\n    case NodeTypes.INTERPOLATION:\n      // no need to traverse, but we need to inject toString helper\n      if (!context.ssr) {\n        context.helper(TO_DISPLAY_STRING)\n      }\n      break\n\n    // for container types, further traverse downwards\n    case NodeTypes.IF:\n      for (let i = 0; i < node.branches.length; i++) {\n        traverseNode(node.branches[i], context)\n      }\n      break\n    case NodeTypes.IF_BRANCH:\n    case NodeTypes.FOR:\n    case NodeTypes.ELEMENT:\n    case NodeTypes.ROOT:\n      traverseChildren(node, context)\n      break\n  }\n\n  // exit transforms\n  context.currentNode = node\n  let i = exitFns.length\n  while (i--) {\n    exitFns[i]()\n  }\n}\n\nexport function createStructuralDirectiveTransform(\n  name: string | RegExp,\n  fn: StructuralDirectiveTransform,\n): NodeTransform {\n  const matches = isString(name)\n    ? (n: string) => n === name\n    : (n: string) => name.test(n)\n\n  return (node, context) => {\n    if (node.type === NodeTypes.ELEMENT) {\n      const { props } = node\n      // structural directive transforms are not concerned with slots\n      // as they are handled separately in vSlot.ts\n      if (node.tagType === ElementTypes.TEMPLATE && props.some(isVSlot)) {\n        return\n      }\n      const exitFns = []\n      for (let i = 0; i < props.length; i++) {\n        const prop = props[i]\n        if (prop.type === NodeTypes.DIRECTIVE && matches(prop.name)) {\n          // structural directives are removed to avoid infinite recursion\n          // also we remove them *before* applying so that it can further\n          // traverse itself in case it moves the node around\n          props.splice(i, 1)\n          i--\n          const onExit = fn(node, prop, context)\n          if (onExit) exitFns.push(onExit)\n        }\n      }\n      return exitFns\n    }\n  }\n}\n"
  },
  {
    "path": "packages/compiler-core/src/transforms/cacheStatic.ts",
    "content": "import {\n  type CacheExpression,\n  type CallExpression,\n  type ComponentNode,\n  ConstantTypes,\n  ElementTypes,\n  type ExpressionNode,\n  type JSChildNode,\n  NodeTypes,\n  type ParentNode,\n  type PlainElementNode,\n  type RootNode,\n  type SimpleExpressionNode,\n  type SlotFunctionExpression,\n  type TemplateChildNode,\n  type TemplateNode,\n  type TextCallNode,\n  type VNodeCall,\n  createArrayExpression,\n  getVNodeBlockHelper,\n  getVNodeHelper,\n} from '../ast'\nimport type { TransformContext } from '../transform'\nimport {\n  PatchFlagNames,\n  PatchFlags,\n  isArray,\n  isString,\n  isSymbol,\n} from '@vue/shared'\nimport { findDir, isSlotOutlet } from '../utils'\nimport {\n  GUARD_REACTIVE_PROPS,\n  NORMALIZE_CLASS,\n  NORMALIZE_PROPS,\n  NORMALIZE_STYLE,\n  OPEN_BLOCK,\n} from '../runtimeHelpers'\n\nexport function cacheStatic(root: RootNode, context: TransformContext): void {\n  walk(\n    root,\n    undefined,\n    context,\n    // Root node is unfortunately non-hoistable due to potential parent\n    // fallthrough attributes.\n    !!getSingleElementRoot(root),\n  )\n}\n\nexport function getSingleElementRoot(\n  root: RootNode,\n): PlainElementNode | ComponentNode | TemplateNode | null {\n  const children = root.children.filter(x => x.type !== NodeTypes.COMMENT)\n  return children.length === 1 &&\n    children[0].type === NodeTypes.ELEMENT &&\n    !isSlotOutlet(children[0])\n    ? children[0]\n    : null\n}\n\nfunction walk(\n  node: ParentNode,\n  parent: ParentNode | undefined,\n  context: TransformContext,\n  doNotHoistNode: boolean = false,\n  inFor = false,\n) {\n  const { children } = node\n  const toCache: (PlainElementNode | TextCallNode)[] = []\n  for (let i = 0; i < children.length; i++) {\n    const child = children[i]\n    // only plain elements & text calls are eligible for caching.\n    if (\n      child.type === NodeTypes.ELEMENT &&\n      child.tagType === ElementTypes.ELEMENT\n    ) {\n      const constantType = doNotHoistNode\n        ? ConstantTypes.NOT_CONSTANT\n        : getConstantType(child, context)\n      if (constantType > ConstantTypes.NOT_CONSTANT) {\n        if (constantType >= ConstantTypes.CAN_CACHE) {\n          ;(child.codegenNode as VNodeCall).patchFlag = PatchFlags.CACHED\n          toCache.push(child)\n          continue\n        }\n      } else {\n        // node may contain dynamic children, but its props may be eligible for\n        // hoisting.\n        const codegenNode = child.codegenNode!\n        if (codegenNode.type === NodeTypes.VNODE_CALL) {\n          const flag = codegenNode.patchFlag\n          if (\n            (flag === undefined ||\n              flag === PatchFlags.NEED_PATCH ||\n              flag === PatchFlags.TEXT) &&\n            getGeneratedPropsConstantType(child, context) >=\n              ConstantTypes.CAN_CACHE\n          ) {\n            const props = getNodeProps(child)\n            if (props) {\n              codegenNode.props = context.hoist(props)\n            }\n          }\n          if (codegenNode.dynamicProps) {\n            codegenNode.dynamicProps = context.hoist(codegenNode.dynamicProps)\n          }\n        }\n      }\n    } else if (child.type === NodeTypes.TEXT_CALL) {\n      const constantType = doNotHoistNode\n        ? ConstantTypes.NOT_CONSTANT\n        : getConstantType(child, context)\n      if (constantType >= ConstantTypes.CAN_CACHE) {\n        if (\n          child.codegenNode.type === NodeTypes.JS_CALL_EXPRESSION &&\n          child.codegenNode.arguments.length > 0\n        ) {\n          child.codegenNode.arguments.push(\n            PatchFlags.CACHED +\n              (__DEV__ ? ` /* ${PatchFlagNames[PatchFlags.CACHED]} */` : ``),\n          )\n        }\n        toCache.push(child)\n        continue\n      }\n    }\n\n    // walk further\n    if (child.type === NodeTypes.ELEMENT) {\n      const isComponent = child.tagType === ElementTypes.COMPONENT\n      if (isComponent) {\n        context.scopes.vSlot++\n      }\n      walk(child, node, context, false, inFor)\n      if (isComponent) {\n        context.scopes.vSlot--\n      }\n    } else if (child.type === NodeTypes.FOR) {\n      // Do not hoist v-for single child because it has to be a block\n      walk(child, node, context, child.children.length === 1, true)\n    } else if (child.type === NodeTypes.IF) {\n      for (let i = 0; i < child.branches.length; i++) {\n        // Do not hoist v-if single child because it has to be a block\n        walk(\n          child.branches[i],\n          node,\n          context,\n          child.branches[i].children.length === 1,\n          inFor,\n        )\n      }\n    }\n  }\n\n  let cachedAsArray = false\n  if (toCache.length === children.length && node.type === NodeTypes.ELEMENT) {\n    if (\n      node.tagType === ElementTypes.ELEMENT &&\n      node.codegenNode &&\n      node.codegenNode.type === NodeTypes.VNODE_CALL &&\n      isArray(node.codegenNode.children)\n    ) {\n      // all children were hoisted - the entire children array is cacheable.\n      node.codegenNode.children = getCacheExpression(\n        createArrayExpression(node.codegenNode.children),\n      )\n      cachedAsArray = true\n    } else if (\n      node.tagType === ElementTypes.COMPONENT &&\n      node.codegenNode &&\n      node.codegenNode.type === NodeTypes.VNODE_CALL &&\n      node.codegenNode.children &&\n      !isArray(node.codegenNode.children) &&\n      node.codegenNode.children.type === NodeTypes.JS_OBJECT_EXPRESSION\n    ) {\n      // default slot\n      const slot = getSlotNode(node.codegenNode, 'default')\n      if (slot) {\n        slot.returns = getCacheExpression(\n          createArrayExpression(slot.returns as TemplateChildNode[]),\n        )\n        cachedAsArray = true\n      }\n    } else if (\n      node.tagType === ElementTypes.TEMPLATE &&\n      parent &&\n      parent.type === NodeTypes.ELEMENT &&\n      parent.tagType === ElementTypes.COMPONENT &&\n      parent.codegenNode &&\n      parent.codegenNode.type === NodeTypes.VNODE_CALL &&\n      parent.codegenNode.children &&\n      !isArray(parent.codegenNode.children) &&\n      parent.codegenNode.children.type === NodeTypes.JS_OBJECT_EXPRESSION\n    ) {\n      // named <template> slot\n      const slotName = findDir(node, 'slot', true)\n      const slot =\n        slotName &&\n        slotName.arg &&\n        getSlotNode(parent.codegenNode, slotName.arg)\n      if (slot) {\n        slot.returns = getCacheExpression(\n          createArrayExpression(slot.returns as TemplateChildNode[]),\n        )\n        cachedAsArray = true\n      }\n    }\n  }\n\n  if (!cachedAsArray) {\n    for (const child of toCache) {\n      child.codegenNode = context.cache(child.codegenNode!)\n    }\n  }\n\n  function getCacheExpression(value: JSChildNode): CacheExpression {\n    const exp = context.cache(value)\n    // #6978, #7138, #7114\n    // a cached children array inside v-for can caused HMR errors since\n    // it might be mutated when mounting the first item\n    // #13221\n    // fix memory leak in cached array:\n    // cached vnodes get replaced by cloned ones during mountChildren,\n    // which bind DOM elements. These DOM references persist after unmount,\n    // preventing garbage collection. Array spread avoids mutating cached\n    // array, preventing memory leaks.\n    exp.needArraySpread = true\n    return exp\n  }\n\n  function getSlotNode(\n    node: VNodeCall,\n    name: string | ExpressionNode,\n  ): SlotFunctionExpression | undefined {\n    if (\n      node.children &&\n      !isArray(node.children) &&\n      node.children.type === NodeTypes.JS_OBJECT_EXPRESSION\n    ) {\n      const slot = node.children.properties.find(\n        p => p.key === name || (p.key as SimpleExpressionNode).content === name,\n      )\n      return slot && slot.value\n    }\n  }\n\n  if (toCache.length && context.transformHoist) {\n    context.transformHoist(children, context, node)\n  }\n}\n\nexport function getConstantType(\n  node: TemplateChildNode | SimpleExpressionNode | CacheExpression,\n  context: TransformContext,\n): ConstantTypes {\n  const { constantCache } = context\n  switch (node.type) {\n    case NodeTypes.ELEMENT:\n      if (node.tagType !== ElementTypes.ELEMENT) {\n        return ConstantTypes.NOT_CONSTANT\n      }\n      const cached = constantCache.get(node)\n      if (cached !== undefined) {\n        return cached\n      }\n      const codegenNode = node.codegenNode!\n      if (codegenNode.type !== NodeTypes.VNODE_CALL) {\n        return ConstantTypes.NOT_CONSTANT\n      }\n      if (\n        codegenNode.isBlock &&\n        node.tag !== 'svg' &&\n        node.tag !== 'foreignObject' &&\n        node.tag !== 'math'\n      ) {\n        return ConstantTypes.NOT_CONSTANT\n      }\n      if (codegenNode.patchFlag === undefined) {\n        let returnType = ConstantTypes.CAN_STRINGIFY\n\n        // Element itself has no patch flag. However we still need to check:\n\n        // 1. Even for a node with no patch flag, it is possible for it to contain\n        // non-hoistable expressions that refers to scope variables, e.g. compiler\n        // injected keys or cached event handlers. Therefore we need to always\n        // check the codegenNode's props to be sure.\n        const generatedPropsType = getGeneratedPropsConstantType(node, context)\n        if (generatedPropsType === ConstantTypes.NOT_CONSTANT) {\n          constantCache.set(node, ConstantTypes.NOT_CONSTANT)\n          return ConstantTypes.NOT_CONSTANT\n        }\n        if (generatedPropsType < returnType) {\n          returnType = generatedPropsType\n        }\n\n        // 2. its children.\n        for (let i = 0; i < node.children.length; i++) {\n          const childType = getConstantType(node.children[i], context)\n          if (childType === ConstantTypes.NOT_CONSTANT) {\n            constantCache.set(node, ConstantTypes.NOT_CONSTANT)\n            return ConstantTypes.NOT_CONSTANT\n          }\n          if (childType < returnType) {\n            returnType = childType\n          }\n        }\n\n        // 3. if the type is not already CAN_SKIP_PATCH which is the lowest non-0\n        // type, check if any of the props can cause the type to be lowered\n        // we can skip can_patch because it's guaranteed by the absence of a\n        // patchFlag.\n        if (returnType > ConstantTypes.CAN_SKIP_PATCH) {\n          for (let i = 0; i < node.props.length; i++) {\n            const p = node.props[i]\n            if (p.type === NodeTypes.DIRECTIVE && p.name === 'bind' && p.exp) {\n              const expType = getConstantType(p.exp, context)\n              if (expType === ConstantTypes.NOT_CONSTANT) {\n                constantCache.set(node, ConstantTypes.NOT_CONSTANT)\n                return ConstantTypes.NOT_CONSTANT\n              }\n              if (expType < returnType) {\n                returnType = expType\n              }\n            }\n          }\n        }\n\n        // only svg/foreignObject could be block here, however if they are\n        // static then they don't need to be blocks since there will be no\n        // nested updates.\n        if (codegenNode.isBlock) {\n          // except set custom directives.\n          for (let i = 0; i < node.props.length; i++) {\n            const p = node.props[i]\n            if (p.type === NodeTypes.DIRECTIVE) {\n              constantCache.set(node, ConstantTypes.NOT_CONSTANT)\n              return ConstantTypes.NOT_CONSTANT\n            }\n          }\n\n          context.removeHelper(OPEN_BLOCK)\n          context.removeHelper(\n            getVNodeBlockHelper(context.inSSR, codegenNode.isComponent),\n          )\n          codegenNode.isBlock = false\n          context.helper(getVNodeHelper(context.inSSR, codegenNode.isComponent))\n        }\n\n        constantCache.set(node, returnType)\n        return returnType\n      } else {\n        constantCache.set(node, ConstantTypes.NOT_CONSTANT)\n        return ConstantTypes.NOT_CONSTANT\n      }\n    case NodeTypes.TEXT:\n    case NodeTypes.COMMENT:\n      return ConstantTypes.CAN_STRINGIFY\n    case NodeTypes.IF:\n    case NodeTypes.FOR:\n    case NodeTypes.IF_BRANCH:\n      return ConstantTypes.NOT_CONSTANT\n    case NodeTypes.INTERPOLATION:\n    case NodeTypes.TEXT_CALL:\n      return getConstantType(node.content, context)\n    case NodeTypes.SIMPLE_EXPRESSION:\n      return node.constType\n    case NodeTypes.COMPOUND_EXPRESSION:\n      let returnType = ConstantTypes.CAN_STRINGIFY\n      for (let i = 0; i < node.children.length; i++) {\n        const child = node.children[i]\n        if (isString(child) || isSymbol(child)) {\n          continue\n        }\n        const childType = getConstantType(child, context)\n        if (childType === ConstantTypes.NOT_CONSTANT) {\n          return ConstantTypes.NOT_CONSTANT\n        } else if (childType < returnType) {\n          returnType = childType\n        }\n      }\n      return returnType\n    case NodeTypes.JS_CACHE_EXPRESSION:\n      return ConstantTypes.CAN_CACHE\n    default:\n      if (__DEV__) {\n        const exhaustiveCheck: never = node\n        exhaustiveCheck\n      }\n      return ConstantTypes.NOT_CONSTANT\n  }\n}\n\nconst allowHoistedHelperSet = new Set([\n  NORMALIZE_CLASS,\n  NORMALIZE_STYLE,\n  NORMALIZE_PROPS,\n  GUARD_REACTIVE_PROPS,\n])\n\nfunction getConstantTypeOfHelperCall(\n  value: CallExpression,\n  context: TransformContext,\n): ConstantTypes {\n  if (\n    value.type === NodeTypes.JS_CALL_EXPRESSION &&\n    !isString(value.callee) &&\n    allowHoistedHelperSet.has(value.callee)\n  ) {\n    const arg = value.arguments[0] as JSChildNode\n    if (arg.type === NodeTypes.SIMPLE_EXPRESSION) {\n      return getConstantType(arg, context)\n    } else if (arg.type === NodeTypes.JS_CALL_EXPRESSION) {\n      // in the case of nested helper call, e.g. `normalizeProps(guardReactiveProps(exp))`\n      return getConstantTypeOfHelperCall(arg, context)\n    }\n  }\n  return ConstantTypes.NOT_CONSTANT\n}\n\nfunction getGeneratedPropsConstantType(\n  node: PlainElementNode,\n  context: TransformContext,\n): ConstantTypes {\n  let returnType = ConstantTypes.CAN_STRINGIFY\n  const props = getNodeProps(node)\n  if (props && props.type === NodeTypes.JS_OBJECT_EXPRESSION) {\n    const { properties } = props\n    for (let i = 0; i < properties.length; i++) {\n      const { key, value } = properties[i]\n      const keyType = getConstantType(key, context)\n      if (keyType === ConstantTypes.NOT_CONSTANT) {\n        return keyType\n      }\n      if (keyType < returnType) {\n        returnType = keyType\n      }\n      let valueType: ConstantTypes\n      if (value.type === NodeTypes.SIMPLE_EXPRESSION) {\n        valueType = getConstantType(value, context)\n      } else if (value.type === NodeTypes.JS_CALL_EXPRESSION) {\n        // some helper calls can be hoisted,\n        // such as the `normalizeProps` generated by the compiler for pre-normalize class,\n        // in this case we need to respect the ConstantType of the helper's arguments\n        valueType = getConstantTypeOfHelperCall(value, context)\n      } else {\n        valueType = ConstantTypes.NOT_CONSTANT\n      }\n      if (valueType === ConstantTypes.NOT_CONSTANT) {\n        return valueType\n      }\n      if (valueType < returnType) {\n        returnType = valueType\n      }\n    }\n  }\n  return returnType\n}\n\nfunction getNodeProps(node: PlainElementNode) {\n  const codegenNode = node.codegenNode!\n  if (codegenNode.type === NodeTypes.VNODE_CALL) {\n    return codegenNode.props\n  }\n}\n"
  },
  {
    "path": "packages/compiler-core/src/transforms/noopDirectiveTransform.ts",
    "content": "import type { DirectiveTransform } from '../transform'\n\nexport const noopDirectiveTransform: DirectiveTransform = () => ({ props: [] })\n"
  },
  {
    "path": "packages/compiler-core/src/transforms/transformElement.ts",
    "content": "import type { NodeTransform, TransformContext } from '../transform'\nimport {\n  type ArrayExpression,\n  type CallExpression,\n  type ComponentNode,\n  ConstantTypes,\n  type DirectiveArguments,\n  type DirectiveNode,\n  type ElementNode,\n  ElementTypes,\n  type ExpressionNode,\n  type JSChildNode,\n  NodeTypes,\n  type ObjectExpression,\n  type Property,\n  type TemplateTextChildNode,\n  type VNodeCall,\n  createArrayExpression,\n  createCallExpression,\n  createObjectExpression,\n  createObjectProperty,\n  createSimpleExpression,\n  createVNodeCall,\n} from '../ast'\nimport {\n  PatchFlags,\n  camelize,\n  capitalize,\n  isBuiltInDirective,\n  isObject,\n  isOn,\n  isReservedProp,\n  isSymbol,\n} from '@vue/shared'\nimport { ErrorCodes, createCompilerError } from '../errors'\nimport {\n  GUARD_REACTIVE_PROPS,\n  KEEP_ALIVE,\n  MERGE_PROPS,\n  NORMALIZE_CLASS,\n  NORMALIZE_PROPS,\n  NORMALIZE_STYLE,\n  RESOLVE_COMPONENT,\n  RESOLVE_DIRECTIVE,\n  RESOLVE_DYNAMIC_COMPONENT,\n  SUSPENSE,\n  TELEPORT,\n  TO_HANDLERS,\n  UNREF,\n} from '../runtimeHelpers'\nimport {\n  findProp,\n  isCoreComponent,\n  isStaticArgOf,\n  isStaticExp,\n  toValidAssetId,\n} from '../utils'\nimport { buildSlots } from './vSlot'\nimport { getConstantType } from './cacheStatic'\nimport { BindingTypes } from '../options'\nimport {\n  CompilerDeprecationTypes,\n  checkCompatEnabled,\n  isCompatEnabled,\n} from '../compat/compatConfig'\nimport { processExpression } from './transformExpression'\n\n// some directive transforms (e.g. v-model) may return a symbol for runtime\n// import, which should be used instead of a resolveDirective call.\nconst directiveImportMap = new WeakMap<DirectiveNode, symbol>()\n\n// generate a JavaScript AST for this element's codegen\nexport const transformElement: NodeTransform = (node, context) => {\n  // perform the work on exit, after all child expressions have been\n  // processed and merged.\n  return function postTransformElement() {\n    node = context.currentNode!\n\n    if (\n      !(\n        node.type === NodeTypes.ELEMENT &&\n        (node.tagType === ElementTypes.ELEMENT ||\n          node.tagType === ElementTypes.COMPONENT)\n      )\n    ) {\n      return\n    }\n\n    const { tag, props } = node\n    const isComponent = node.tagType === ElementTypes.COMPONENT\n\n    // The goal of the transform is to create a codegenNode implementing the\n    // VNodeCall interface.\n    let vnodeTag = isComponent\n      ? resolveComponentType(node as ComponentNode, context)\n      : `\"${tag}\"`\n\n    const isDynamicComponent =\n      isObject(vnodeTag) && vnodeTag.callee === RESOLVE_DYNAMIC_COMPONENT\n\n    let vnodeProps: VNodeCall['props']\n    let vnodeChildren: VNodeCall['children']\n    let patchFlag: VNodeCall['patchFlag'] | 0 = 0\n    let vnodeDynamicProps: VNodeCall['dynamicProps']\n    let dynamicPropNames: string[] | undefined\n    let vnodeDirectives: VNodeCall['directives']\n\n    let shouldUseBlock =\n      // dynamic component may resolve to plain elements\n      isDynamicComponent ||\n      vnodeTag === TELEPORT ||\n      vnodeTag === SUSPENSE ||\n      (!isComponent &&\n        // <svg> and <foreignObject> must be forced into blocks so that block\n        // updates inside get proper isSVG flag at runtime. (#639, #643)\n        // This is technically web-specific, but splitting the logic out of core\n        // leads to too much unnecessary complexity.\n        (tag === 'svg' || tag === 'foreignObject' || tag === 'math'))\n\n    // props\n    if (props.length > 0) {\n      const propsBuildResult = buildProps(\n        node,\n        context,\n        undefined,\n        isComponent,\n        isDynamicComponent,\n      )\n      vnodeProps = propsBuildResult.props\n      patchFlag = propsBuildResult.patchFlag\n      dynamicPropNames = propsBuildResult.dynamicPropNames\n      const directives = propsBuildResult.directives\n      vnodeDirectives =\n        directives && directives.length\n          ? (createArrayExpression(\n              directives.map(dir => buildDirectiveArgs(dir, context)),\n            ) as DirectiveArguments)\n          : undefined\n\n      if (propsBuildResult.shouldUseBlock) {\n        shouldUseBlock = true\n      }\n    }\n\n    // children\n    if (node.children.length > 0) {\n      if (vnodeTag === KEEP_ALIVE) {\n        // Although a built-in component, we compile KeepAlive with raw children\n        // instead of slot functions so that it can be used inside Transition\n        // or other Transition-wrapping HOCs.\n        // To ensure correct updates with block optimizations, we need to:\n        // 1. Force keep-alive into a block. This avoids its children being\n        //    collected by a parent block.\n        shouldUseBlock = true\n        // 2. Force keep-alive to always be updated, since it uses raw children.\n        patchFlag |= PatchFlags.DYNAMIC_SLOTS\n        if (__DEV__ && node.children.length > 1) {\n          context.onError(\n            createCompilerError(ErrorCodes.X_KEEP_ALIVE_INVALID_CHILDREN, {\n              start: node.children[0].loc.start,\n              end: node.children[node.children.length - 1].loc.end,\n              source: '',\n            }),\n          )\n        }\n      }\n\n      const shouldBuildAsSlots =\n        isComponent &&\n        // Teleport is not a real component and has dedicated runtime handling\n        vnodeTag !== TELEPORT &&\n        // explained above.\n        vnodeTag !== KEEP_ALIVE\n\n      if (shouldBuildAsSlots) {\n        const { slots, hasDynamicSlots } = buildSlots(node, context)\n        vnodeChildren = slots\n        if (hasDynamicSlots) {\n          patchFlag |= PatchFlags.DYNAMIC_SLOTS\n        }\n      } else if (node.children.length === 1 && vnodeTag !== TELEPORT) {\n        const child = node.children[0]\n        const type = child.type\n        // check for dynamic text children\n        const hasDynamicTextChild =\n          type === NodeTypes.INTERPOLATION ||\n          type === NodeTypes.COMPOUND_EXPRESSION\n        if (\n          hasDynamicTextChild &&\n          getConstantType(child, context) === ConstantTypes.NOT_CONSTANT\n        ) {\n          patchFlag |= PatchFlags.TEXT\n        }\n        // pass directly if the only child is a text node\n        // (plain / interpolation / expression)\n        if (hasDynamicTextChild || type === NodeTypes.TEXT) {\n          vnodeChildren = child as TemplateTextChildNode\n        } else {\n          vnodeChildren = node.children\n        }\n      } else {\n        vnodeChildren = node.children\n      }\n    }\n\n    // patchFlag & dynamicPropNames\n    if (dynamicPropNames && dynamicPropNames.length) {\n      vnodeDynamicProps = stringifyDynamicPropNames(dynamicPropNames)\n    }\n\n    node.codegenNode = createVNodeCall(\n      context,\n      vnodeTag,\n      vnodeProps,\n      vnodeChildren,\n      patchFlag === 0 ? undefined : patchFlag,\n      vnodeDynamicProps,\n      vnodeDirectives,\n      !!shouldUseBlock,\n      false /* disableTracking */,\n      isComponent,\n      node.loc,\n    )\n  }\n}\n\nexport function resolveComponentType(\n  node: ComponentNode,\n  context: TransformContext,\n  ssr = false,\n): string | symbol | CallExpression {\n  let { tag } = node\n\n  // 1. dynamic component\n  const isExplicitDynamic = isComponentTag(tag)\n  const isProp = findProp(node, 'is', false, true /* allow empty */)\n  if (isProp) {\n    if (\n      isExplicitDynamic ||\n      (__COMPAT__ &&\n        isCompatEnabled(\n          CompilerDeprecationTypes.COMPILER_IS_ON_ELEMENT,\n          context,\n        ))\n    ) {\n      let exp: ExpressionNode | undefined\n      if (isProp.type === NodeTypes.ATTRIBUTE) {\n        exp = isProp.value && createSimpleExpression(isProp.value.content, true)\n      } else {\n        exp = isProp.exp\n        if (!exp) {\n          // #10469 handle :is shorthand\n          exp = createSimpleExpression(`is`, false, isProp.arg!.loc)\n          if (!__BROWSER__) {\n            exp = isProp.exp = processExpression(exp, context)\n          }\n        }\n      }\n      if (exp) {\n        return createCallExpression(context.helper(RESOLVE_DYNAMIC_COMPONENT), [\n          exp,\n        ])\n      }\n    } else if (\n      isProp.type === NodeTypes.ATTRIBUTE &&\n      isProp.value!.content.startsWith('vue:')\n    ) {\n      // <button is=\"vue:xxx\">\n      // if not <component>, only is value that starts with \"vue:\" will be\n      // treated as component by the parse phase and reach here, unless it's\n      // compat mode where all is values are considered components\n      tag = isProp.value!.content.slice(4)\n    }\n  }\n\n  // 2. built-in components (Teleport, Transition, KeepAlive, Suspense...)\n  const builtIn = isCoreComponent(tag) || context.isBuiltInComponent(tag)\n  if (builtIn) {\n    // built-ins are simply fallthroughs / have special handling during ssr\n    // so we don't need to import their runtime equivalents\n    if (!ssr) context.helper(builtIn)\n    return builtIn\n  }\n\n  // 3. user component (from setup bindings)\n  // this is skipped in browser build since browser builds do not perform\n  // binding analysis.\n  if (!__BROWSER__) {\n    const fromSetup = resolveSetupReference(tag, context)\n    if (fromSetup) {\n      return fromSetup\n    }\n    const dotIndex = tag.indexOf('.')\n    if (dotIndex > 0) {\n      const ns = resolveSetupReference(tag.slice(0, dotIndex), context)\n      if (ns) {\n        return ns + tag.slice(dotIndex)\n      }\n    }\n  }\n\n  // 4. Self referencing component (inferred from filename)\n  if (\n    !__BROWSER__ &&\n    context.selfName &&\n    capitalize(camelize(tag)) === context.selfName\n  ) {\n    context.helper(RESOLVE_COMPONENT)\n    // codegen.ts has special check for __self postfix when generating\n    // component imports, which will pass additional `maybeSelfReference` flag\n    // to `resolveComponent`.\n    context.components.add(tag + `__self`)\n    return toValidAssetId(tag, `component`)\n  }\n\n  // 5. user component (resolve)\n  context.helper(RESOLVE_COMPONENT)\n  context.components.add(tag)\n  return toValidAssetId(tag, `component`)\n}\n\nfunction resolveSetupReference(name: string, context: TransformContext) {\n  const bindings = context.bindingMetadata\n  if (!bindings || bindings.__isScriptSetup === false) {\n    return\n  }\n\n  const camelName = camelize(name)\n  const PascalName = capitalize(camelName)\n  const checkType = (type: BindingTypes) => {\n    if (bindings[name] === type) {\n      return name\n    }\n    if (bindings[camelName] === type) {\n      return camelName\n    }\n    if (bindings[PascalName] === type) {\n      return PascalName\n    }\n  }\n\n  const fromConst =\n    checkType(BindingTypes.SETUP_CONST) ||\n    checkType(BindingTypes.SETUP_REACTIVE_CONST) ||\n    checkType(BindingTypes.LITERAL_CONST)\n  if (fromConst) {\n    return context.inline\n      ? // in inline mode, const setup bindings (e.g. imports) can be used as-is\n        fromConst\n      : `$setup[${JSON.stringify(fromConst)}]`\n  }\n\n  const fromMaybeRef =\n    checkType(BindingTypes.SETUP_LET) ||\n    checkType(BindingTypes.SETUP_REF) ||\n    checkType(BindingTypes.SETUP_MAYBE_REF)\n  if (fromMaybeRef) {\n    return context.inline\n      ? // setup scope bindings that may be refs need to be unrefed\n        `${context.helperString(UNREF)}(${fromMaybeRef})`\n      : `$setup[${JSON.stringify(fromMaybeRef)}]`\n  }\n\n  const fromProps = checkType(BindingTypes.PROPS)\n  if (fromProps) {\n    return `${context.helperString(UNREF)}(${\n      context.inline ? '__props' : '$props'\n    }[${JSON.stringify(fromProps)}])`\n  }\n}\n\nexport type PropsExpression = ObjectExpression | CallExpression | ExpressionNode\n\nexport function buildProps(\n  node: ElementNode,\n  context: TransformContext,\n  props: ElementNode['props'] | undefined = node.props,\n  isComponent: boolean,\n  isDynamicComponent: boolean,\n  ssr = false,\n): {\n  props: PropsExpression | undefined\n  directives: DirectiveNode[]\n  patchFlag: number\n  dynamicPropNames: string[]\n  shouldUseBlock: boolean\n} {\n  const { tag, loc: elementLoc, children } = node\n  let properties: ObjectExpression['properties'] = []\n  const mergeArgs: PropsExpression[] = []\n  const runtimeDirectives: DirectiveNode[] = []\n  const hasChildren = children.length > 0\n  let shouldUseBlock = false\n\n  // patchFlag analysis\n  let patchFlag = 0\n  let hasRef = false\n  let hasClassBinding = false\n  let hasStyleBinding = false\n  let hasHydrationEventBinding = false\n  let hasDynamicKeys = false\n  let hasVnodeHook = false\n  const dynamicPropNames: string[] = []\n\n  const pushMergeArg = (arg?: PropsExpression) => {\n    if (properties.length) {\n      mergeArgs.push(\n        createObjectExpression(dedupeProperties(properties), elementLoc),\n      )\n      properties = []\n    }\n    if (arg) mergeArgs.push(arg)\n  }\n\n  // mark template ref on v-for\n  const pushRefVForMarker = () => {\n    if (context.scopes.vFor > 0) {\n      properties.push(\n        createObjectProperty(\n          createSimpleExpression('ref_for', true),\n          createSimpleExpression('true'),\n        ),\n      )\n    }\n  }\n\n  const analyzePatchFlag = ({ key, value }: Property) => {\n    if (isStaticExp(key)) {\n      const name = key.content\n      const isEventHandler = isOn(name)\n      if (\n        isEventHandler &&\n        (!isComponent || isDynamicComponent) &&\n        // omit the flag for click handlers because hydration gives click\n        // dedicated fast path.\n        name.toLowerCase() !== 'onclick' &&\n        // omit v-model handlers\n        name !== 'onUpdate:modelValue' &&\n        // omit onVnodeXXX hooks\n        !isReservedProp(name)\n      ) {\n        hasHydrationEventBinding = true\n      }\n\n      if (isEventHandler && isReservedProp(name)) {\n        hasVnodeHook = true\n      }\n\n      if (isEventHandler && value.type === NodeTypes.JS_CALL_EXPRESSION) {\n        // handler wrapped with internal helper e.g. withModifiers(fn)\n        // extract the actual expression\n        value = value.arguments[0] as JSChildNode\n      }\n\n      if (\n        value.type === NodeTypes.JS_CACHE_EXPRESSION ||\n        ((value.type === NodeTypes.SIMPLE_EXPRESSION ||\n          value.type === NodeTypes.COMPOUND_EXPRESSION) &&\n          getConstantType(value, context) > 0)\n      ) {\n        // skip if the prop is a cached handler or has constant value\n        return\n      }\n\n      if (name === 'ref') {\n        hasRef = true\n      } else if (name === 'class') {\n        hasClassBinding = true\n      } else if (name === 'style') {\n        hasStyleBinding = true\n      } else if (name !== 'key' && !dynamicPropNames.includes(name)) {\n        dynamicPropNames.push(name)\n      }\n\n      // treat the dynamic class and style binding of the component as dynamic props\n      if (\n        isComponent &&\n        (name === 'class' || name === 'style') &&\n        !dynamicPropNames.includes(name)\n      ) {\n        dynamicPropNames.push(name)\n      }\n    } else {\n      hasDynamicKeys = true\n    }\n  }\n\n  for (let i = 0; i < props.length; i++) {\n    // static attribute\n    const prop = props[i]\n    if (prop.type === NodeTypes.ATTRIBUTE) {\n      const { loc, name, nameLoc, value } = prop\n      let isStatic = true\n      if (name === 'ref') {\n        hasRef = true\n        pushRefVForMarker()\n        // in inline mode there is no setupState object, so we can't use string\n        // keys to set the ref. Instead, we need to transform it to pass the\n        // actual ref instead.\n        if (!__BROWSER__ && value && context.inline) {\n          const binding = context.bindingMetadata[value.content]\n          if (\n            binding === BindingTypes.SETUP_LET ||\n            binding === BindingTypes.SETUP_REF ||\n            binding === BindingTypes.SETUP_MAYBE_REF\n          ) {\n            isStatic = false\n            properties.push(\n              createObjectProperty(\n                createSimpleExpression('ref_key', true),\n                createSimpleExpression(value.content, true, value.loc),\n              ),\n            )\n          }\n        }\n      }\n      // skip is on <component>, or is=\"vue:xxx\"\n      if (\n        name === 'is' &&\n        (isComponentTag(tag) ||\n          (value && value.content.startsWith('vue:')) ||\n          (__COMPAT__ &&\n            isCompatEnabled(\n              CompilerDeprecationTypes.COMPILER_IS_ON_ELEMENT,\n              context,\n            )))\n      ) {\n        continue\n      }\n      properties.push(\n        createObjectProperty(\n          createSimpleExpression(name, true, nameLoc),\n          createSimpleExpression(\n            value ? value.content : '',\n            isStatic,\n            value ? value.loc : loc,\n          ),\n        ),\n      )\n    } else {\n      // directives\n      const { name, arg, exp, loc, modifiers } = prop\n      const isVBind = name === 'bind'\n      const isVOn = name === 'on'\n\n      // skip v-slot - it is handled by its dedicated transform.\n      if (name === 'slot') {\n        if (!isComponent) {\n          context.onError(\n            createCompilerError(ErrorCodes.X_V_SLOT_MISPLACED, loc),\n          )\n        }\n        continue\n      }\n      // skip v-once/v-memo - they are handled by dedicated transforms.\n      if (name === 'once' || name === 'memo') {\n        continue\n      }\n      // skip v-is and :is on <component>\n      if (\n        name === 'is' ||\n        (isVBind &&\n          isStaticArgOf(arg, 'is') &&\n          (isComponentTag(tag) ||\n            (__COMPAT__ &&\n              isCompatEnabled(\n                CompilerDeprecationTypes.COMPILER_IS_ON_ELEMENT,\n                context,\n              ))))\n      ) {\n        continue\n      }\n      // skip v-on in SSR compilation\n      if (isVOn && ssr) {\n        continue\n      }\n\n      if (\n        // #938: elements with dynamic keys should be forced into blocks\n        (isVBind && isStaticArgOf(arg, 'key')) ||\n        // inline before-update hooks need to force block so that it is invoked\n        // before children\n        (isVOn && hasChildren && isStaticArgOf(arg, 'vue:before-update'))\n      ) {\n        shouldUseBlock = true\n      }\n\n      if (isVBind && isStaticArgOf(arg, 'ref')) {\n        pushRefVForMarker()\n      }\n\n      // special case for v-bind and v-on with no argument\n      if (!arg && (isVBind || isVOn)) {\n        hasDynamicKeys = true\n        if (exp) {\n          if (isVBind) {\n            if (__COMPAT__) {\n              // have to merge early for compat build check\n              pushMergeArg()\n              // 2.x v-bind object order compat\n              if (__DEV__) {\n                const hasOverridableKeys = mergeArgs.some(arg => {\n                  if (arg.type === NodeTypes.JS_OBJECT_EXPRESSION) {\n                    return arg.properties.some(({ key }) => {\n                      if (\n                        key.type !== NodeTypes.SIMPLE_EXPRESSION ||\n                        !key.isStatic\n                      ) {\n                        return true\n                      }\n                      return (\n                        key.content !== 'class' &&\n                        key.content !== 'style' &&\n                        !isOn(key.content)\n                      )\n                    })\n                  } else {\n                    // dynamic expression\n                    return true\n                  }\n                })\n                if (hasOverridableKeys) {\n                  checkCompatEnabled(\n                    CompilerDeprecationTypes.COMPILER_V_BIND_OBJECT_ORDER,\n                    context,\n                    loc,\n                  )\n                }\n              }\n\n              if (\n                isCompatEnabled(\n                  CompilerDeprecationTypes.COMPILER_V_BIND_OBJECT_ORDER,\n                  context,\n                )\n              ) {\n                mergeArgs.unshift(exp)\n                continue\n              }\n            }\n\n            // #10696 in case a v-bind object contains ref\n            pushRefVForMarker()\n            pushMergeArg()\n            mergeArgs.push(exp)\n          } else {\n            // v-on=\"obj\" -> toHandlers(obj)\n            pushMergeArg({\n              type: NodeTypes.JS_CALL_EXPRESSION,\n              loc,\n              callee: context.helper(TO_HANDLERS),\n              arguments: isComponent ? [exp] : [exp, `true`],\n            })\n          }\n        } else {\n          context.onError(\n            createCompilerError(\n              isVBind\n                ? ErrorCodes.X_V_BIND_NO_EXPRESSION\n                : ErrorCodes.X_V_ON_NO_EXPRESSION,\n              loc,\n            ),\n          )\n        }\n        continue\n      }\n\n      // force hydration for v-bind with .prop modifier\n      if (isVBind && modifiers.some(mod => mod.content === 'prop')) {\n        patchFlag |= PatchFlags.NEED_HYDRATION\n      }\n\n      const directiveTransform = context.directiveTransforms[name]\n      if (directiveTransform) {\n        // has built-in directive transform.\n        const { props, needRuntime } = directiveTransform(prop, node, context)\n        !ssr && props.forEach(analyzePatchFlag)\n        if (isVOn && arg && !isStaticExp(arg)) {\n          pushMergeArg(createObjectExpression(props, elementLoc))\n        } else {\n          properties.push(...props)\n        }\n        if (needRuntime) {\n          runtimeDirectives.push(prop)\n          if (isSymbol(needRuntime)) {\n            directiveImportMap.set(prop, needRuntime)\n          }\n        }\n      } else if (!isBuiltInDirective(name)) {\n        // no built-in transform, this is a user custom directive.\n        runtimeDirectives.push(prop)\n        // custom dirs may use beforeUpdate so they need to force blocks\n        // to ensure before-update gets called before children update\n        if (hasChildren) {\n          shouldUseBlock = true\n        }\n      }\n    }\n  }\n\n  let propsExpression: PropsExpression | undefined = undefined\n\n  // has v-bind=\"object\" or v-on=\"object\", wrap with mergeProps\n  if (mergeArgs.length) {\n    // close up any not-yet-merged props\n    pushMergeArg()\n    if (mergeArgs.length > 1) {\n      propsExpression = createCallExpression(\n        context.helper(MERGE_PROPS),\n        mergeArgs,\n        elementLoc,\n      )\n    } else {\n      // single v-bind with nothing else - no need for a mergeProps call\n      propsExpression = mergeArgs[0]\n    }\n  } else if (properties.length) {\n    propsExpression = createObjectExpression(\n      dedupeProperties(properties),\n      elementLoc,\n    )\n  }\n\n  // patchFlag analysis\n  if (hasDynamicKeys) {\n    patchFlag |= PatchFlags.FULL_PROPS\n  } else {\n    if (hasClassBinding && !isComponent) {\n      patchFlag |= PatchFlags.CLASS\n    }\n    if (hasStyleBinding && !isComponent) {\n      patchFlag |= PatchFlags.STYLE\n    }\n    if (dynamicPropNames.length) {\n      patchFlag |= PatchFlags.PROPS\n    }\n    if (hasHydrationEventBinding) {\n      patchFlag |= PatchFlags.NEED_HYDRATION\n    }\n  }\n  if (\n    !shouldUseBlock &&\n    (patchFlag === 0 || patchFlag === PatchFlags.NEED_HYDRATION) &&\n    (hasRef || hasVnodeHook || runtimeDirectives.length > 0)\n  ) {\n    patchFlag |= PatchFlags.NEED_PATCH\n  }\n\n  // pre-normalize props, SSR is skipped for now\n  if (!context.inSSR && propsExpression) {\n    switch (propsExpression.type) {\n      case NodeTypes.JS_OBJECT_EXPRESSION:\n        // means that there is no v-bind,\n        // but still need to deal with dynamic key binding\n        let classKeyIndex = -1\n        let styleKeyIndex = -1\n        let hasDynamicKey = false\n\n        for (let i = 0; i < propsExpression.properties.length; i++) {\n          const key = propsExpression.properties[i].key\n          if (isStaticExp(key)) {\n            if (key.content === 'class') {\n              classKeyIndex = i\n            } else if (key.content === 'style') {\n              styleKeyIndex = i\n            }\n          } else if (!key.isHandlerKey) {\n            hasDynamicKey = true\n          }\n        }\n\n        const classProp = propsExpression.properties[classKeyIndex]\n        const styleProp = propsExpression.properties[styleKeyIndex]\n\n        // no dynamic key\n        if (!hasDynamicKey) {\n          if (classProp && !isStaticExp(classProp.value)) {\n            classProp.value = createCallExpression(\n              context.helper(NORMALIZE_CLASS),\n              [classProp.value],\n            )\n          }\n          if (\n            styleProp &&\n            // the static style is compiled into an object,\n            // so use `hasStyleBinding` to ensure that it is a dynamic style binding\n            (hasStyleBinding ||\n              (styleProp.value.type === NodeTypes.SIMPLE_EXPRESSION &&\n                styleProp.value.content.trim()[0] === `[`) ||\n              // v-bind:style and style both exist,\n              // v-bind:style with static literal object\n              styleProp.value.type === NodeTypes.JS_ARRAY_EXPRESSION)\n          ) {\n            styleProp.value = createCallExpression(\n              context.helper(NORMALIZE_STYLE),\n              [styleProp.value],\n            )\n          }\n        } else {\n          // dynamic key binding, wrap with `normalizeProps`\n          propsExpression = createCallExpression(\n            context.helper(NORMALIZE_PROPS),\n            [propsExpression],\n          )\n        }\n        break\n      case NodeTypes.JS_CALL_EXPRESSION:\n        // mergeProps call, do nothing\n        break\n      default:\n        // single v-bind\n        propsExpression = createCallExpression(\n          context.helper(NORMALIZE_PROPS),\n          [\n            createCallExpression(context.helper(GUARD_REACTIVE_PROPS), [\n              propsExpression,\n            ]),\n          ],\n        )\n        break\n    }\n  }\n\n  return {\n    props: propsExpression,\n    directives: runtimeDirectives,\n    patchFlag,\n    dynamicPropNames,\n    shouldUseBlock,\n  }\n}\n\n// Dedupe props in an object literal.\n// Literal duplicated attributes would have been warned during the parse phase,\n// however, it's possible to encounter duplicated `onXXX` handlers with different\n// modifiers. We also need to merge static and dynamic class / style attributes.\n// - onXXX handlers / style: merge into array\n// - class: merge into single expression with concatenation\nfunction dedupeProperties(properties: Property[]): Property[] {\n  const knownProps: Map<string, Property> = new Map()\n  const deduped: Property[] = []\n  for (let i = 0; i < properties.length; i++) {\n    const prop = properties[i]\n    // dynamic keys are always allowed\n    if (prop.key.type === NodeTypes.COMPOUND_EXPRESSION || !prop.key.isStatic) {\n      deduped.push(prop)\n      continue\n    }\n    const name = prop.key.content\n    const existing = knownProps.get(name)\n    if (existing) {\n      if (name === 'style' || name === 'class' || isOn(name)) {\n        mergeAsArray(existing, prop)\n      }\n      // unexpected duplicate, should have emitted error during parse\n    } else {\n      knownProps.set(name, prop)\n      deduped.push(prop)\n    }\n  }\n  return deduped\n}\n\nfunction mergeAsArray(existing: Property, incoming: Property) {\n  if (existing.value.type === NodeTypes.JS_ARRAY_EXPRESSION) {\n    existing.value.elements.push(incoming.value)\n  } else {\n    existing.value = createArrayExpression(\n      [existing.value, incoming.value],\n      existing.loc,\n    )\n  }\n}\n\nexport function buildDirectiveArgs(\n  dir: DirectiveNode,\n  context: TransformContext,\n): ArrayExpression {\n  const dirArgs: ArrayExpression['elements'] = []\n  const runtime = directiveImportMap.get(dir)\n  if (runtime) {\n    // built-in directive with runtime\n    dirArgs.push(context.helperString(runtime))\n  } else {\n    // user directive.\n    // see if we have directives exposed via <script setup>\n    const fromSetup =\n      !__BROWSER__ && resolveSetupReference('v-' + dir.name, context)\n    if (fromSetup) {\n      dirArgs.push(fromSetup)\n    } else {\n      // inject statement for resolving directive\n      context.helper(RESOLVE_DIRECTIVE)\n      context.directives.add(dir.name)\n      dirArgs.push(toValidAssetId(dir.name, `directive`))\n    }\n  }\n  const { loc } = dir\n  if (dir.exp) dirArgs.push(dir.exp)\n  if (dir.arg) {\n    if (!dir.exp) {\n      dirArgs.push(`void 0`)\n    }\n    dirArgs.push(dir.arg)\n  }\n  if (Object.keys(dir.modifiers).length) {\n    if (!dir.arg) {\n      if (!dir.exp) {\n        dirArgs.push(`void 0`)\n      }\n      dirArgs.push(`void 0`)\n    }\n    const trueExpression = createSimpleExpression(`true`, false, loc)\n    dirArgs.push(\n      createObjectExpression(\n        dir.modifiers.map(modifier =>\n          createObjectProperty(modifier, trueExpression),\n        ),\n        loc,\n      ),\n    )\n  }\n  return createArrayExpression(dirArgs, dir.loc)\n}\n\nfunction stringifyDynamicPropNames(props: string[]): string {\n  let propsNamesString = `[`\n  for (let i = 0, l = props.length; i < l; i++) {\n    propsNamesString += JSON.stringify(props[i])\n    if (i < l - 1) propsNamesString += ', '\n  }\n  return propsNamesString + `]`\n}\n\nfunction isComponentTag(tag: string) {\n  return tag === 'component' || tag === 'Component'\n}\n"
  },
  {
    "path": "packages/compiler-core/src/transforms/transformExpression.ts",
    "content": "// - Parse expressions in templates into compound expressions so that each\n//   identifier gets more accurate source-map locations.\n//\n// - Prefix identifiers with `_ctx.` or `$xxx` (for known binding types) so that\n//   they are accessed from the right source\n//\n// - This transform is only applied in non-browser builds because it relies on\n//   an additional JavaScript parser. In the browser, there is no source-map\n//   support and the code is wrapped in `with (this) { ... }`.\nimport type { NodeTransform, TransformContext } from '../transform'\nimport {\n  type CompoundExpressionNode,\n  ConstantTypes,\n  type ExpressionNode,\n  NodeTypes,\n  type SimpleExpressionNode,\n  createCompoundExpression,\n  createSimpleExpression,\n} from '../ast'\nimport {\n  isInDestructureAssignment,\n  isInNewExpression,\n  isStaticProperty,\n  isStaticPropertyKey,\n  walkIdentifiers,\n} from '../babelUtils'\nimport { advancePositionWithClone, findDir, isSimpleIdentifier } from '../utils'\nimport {\n  genPropsAccessExp,\n  hasOwn,\n  isGloballyAllowed,\n  isString,\n  makeMap,\n} from '@vue/shared'\nimport { ErrorCodes, createCompilerError } from '../errors'\nimport type {\n  AssignmentExpression,\n  Identifier,\n  Node,\n  UpdateExpression,\n} from '@babel/types'\nimport { validateBrowserExpression } from '../validateExpression'\nimport { parseExpression } from '@babel/parser'\nimport { IS_REF, UNREF } from '../runtimeHelpers'\nimport { BindingTypes } from '../options'\n\nconst isLiteralWhitelisted = /*@__PURE__*/ makeMap('true,false,null,this')\n\nexport const transformExpression: NodeTransform = (node, context) => {\n  if (node.type === NodeTypes.INTERPOLATION) {\n    node.content = processExpression(\n      node.content as SimpleExpressionNode,\n      context,\n    )\n  } else if (node.type === NodeTypes.ELEMENT) {\n    // handle directives on element\n    const memo = findDir(node, 'memo')\n    for (let i = 0; i < node.props.length; i++) {\n      const dir = node.props[i]\n      // do not process for v-on & v-for since they are special handled\n      if (dir.type === NodeTypes.DIRECTIVE && dir.name !== 'for') {\n        const exp = dir.exp\n        const arg = dir.arg\n        // do not process exp if this is v-on:arg - we need special handling\n        // for wrapping inline statements.\n        if (\n          exp &&\n          exp.type === NodeTypes.SIMPLE_EXPRESSION &&\n          !(dir.name === 'on' && arg) &&\n          // key has been processed in transformFor(vMemo + vFor)\n          !(\n            memo &&\n            arg &&\n            arg.type === NodeTypes.SIMPLE_EXPRESSION &&\n            arg.content === 'key'\n          )\n        ) {\n          dir.exp = processExpression(\n            exp,\n            context,\n            // slot args must be processed as function params\n            dir.name === 'slot',\n          )\n        }\n        if (arg && arg.type === NodeTypes.SIMPLE_EXPRESSION && !arg.isStatic) {\n          dir.arg = processExpression(arg, context)\n        }\n      }\n    }\n  }\n}\n\ninterface PrefixMeta {\n  prefix?: string\n  isConstant: boolean\n  start: number\n  end: number\n  scopeIds?: Set<string>\n}\n\n// Important: since this function uses Node.js only dependencies, it should\n// always be used with a leading !__BROWSER__ check so that it can be\n// tree-shaken from the browser build.\nexport function processExpression(\n  node: SimpleExpressionNode,\n  context: TransformContext,\n  // some expressions like v-slot props & v-for aliases should be parsed as\n  // function params\n  asParams = false,\n  // v-on handler values may contain multiple statements\n  asRawStatements = false,\n  localVars: Record<string, number> = Object.create(context.identifiers),\n): ExpressionNode {\n  if (__BROWSER__) {\n    if (__DEV__) {\n      // simple in-browser validation (same logic in 2.x)\n      validateBrowserExpression(node, context, asParams, asRawStatements)\n    }\n    return node\n  }\n\n  if (!context.prefixIdentifiers || !node.content.trim()) {\n    return node\n  }\n\n  const { inline, bindingMetadata } = context\n  const rewriteIdentifier = (\n    raw: string,\n    parent?: Node | null,\n    id?: Identifier,\n  ) => {\n    const type = hasOwn(bindingMetadata, raw) && bindingMetadata[raw]\n    if (inline) {\n      // x = y\n      const isAssignmentLVal =\n        parent && parent.type === 'AssignmentExpression' && parent.left === id\n      // x++\n      const isUpdateArg =\n        parent && parent.type === 'UpdateExpression' && parent.argument === id\n      // ({ x } = y)\n      const isDestructureAssignment =\n        parent && isInDestructureAssignment(parent, parentStack)\n      const isNewExpression = parent && isInNewExpression(parentStack)\n      const wrapWithUnref = (raw: string) => {\n        const wrapped = `${context.helperString(UNREF)}(${raw})`\n        return isNewExpression ? `(${wrapped})` : wrapped\n      }\n\n      if (\n        isConst(type) ||\n        type === BindingTypes.SETUP_REACTIVE_CONST ||\n        localVars[raw]\n      ) {\n        return raw\n      } else if (type === BindingTypes.SETUP_REF) {\n        return `${raw}.value`\n      } else if (type === BindingTypes.SETUP_MAYBE_REF) {\n        // const binding that may or may not be ref\n        // if it's not a ref, then assignments don't make sense -\n        // so we ignore the non-ref assignment case and generate code\n        // that assumes the value to be a ref for more efficiency\n        return isAssignmentLVal || isUpdateArg || isDestructureAssignment\n          ? `${raw}.value`\n          : wrapWithUnref(raw)\n      } else if (type === BindingTypes.SETUP_LET) {\n        if (isAssignmentLVal) {\n          // let binding.\n          // this is a bit more tricky as we need to cover the case where\n          // let is a local non-ref value, and we need to replicate the\n          // right hand side value.\n          // x = y --> isRef(x) ? x.value = y : x = y\n          const { right: rVal, operator } = parent as AssignmentExpression\n          const rExp = rawExp.slice(rVal.start! - 1, rVal.end! - 1)\n          const rExpString = stringifyExpression(\n            processExpression(\n              createSimpleExpression(rExp, false),\n              context,\n              false,\n              false,\n              knownIds,\n            ),\n          )\n          return `${context.helperString(IS_REF)}(${raw})${\n            context.isTS ? ` //@ts-ignore\\n` : ``\n          } ? ${raw}.value ${operator} ${rExpString} : ${raw}`\n        } else if (isUpdateArg) {\n          // make id replace parent in the code range so the raw update operator\n          // is removed\n          id!.start = parent!.start\n          id!.end = parent!.end\n          const { prefix: isPrefix, operator } = parent as UpdateExpression\n          const prefix = isPrefix ? operator : ``\n          const postfix = isPrefix ? `` : operator\n          // let binding.\n          // x++ --> isRef(a) ? a.value++ : a++\n          return `${context.helperString(IS_REF)}(${raw})${\n            context.isTS ? ` //@ts-ignore\\n` : ``\n          } ? ${prefix}${raw}.value${postfix} : ${prefix}${raw}${postfix}`\n        } else if (isDestructureAssignment) {\n          // TODO\n          // let binding in a destructure assignment - it's very tricky to\n          // handle both possible cases here without altering the original\n          // structure of the code, so we just assume it's not a ref here\n          // for now\n          return raw\n        } else {\n          return wrapWithUnref(raw)\n        }\n      } else if (type === BindingTypes.PROPS) {\n        // use __props which is generated by compileScript so in ts mode\n        // it gets correct type\n        return genPropsAccessExp(raw)\n      } else if (type === BindingTypes.PROPS_ALIASED) {\n        // prop with a different local alias (from defineProps() destructure)\n        return genPropsAccessExp(bindingMetadata.__propsAliases![raw])\n      }\n    } else {\n      if (\n        (type && type.startsWith('setup')) ||\n        type === BindingTypes.LITERAL_CONST\n      ) {\n        // setup bindings in non-inline mode\n        return `$setup.${raw}`\n      } else if (type === BindingTypes.PROPS_ALIASED) {\n        return `$props['${bindingMetadata.__propsAliases![raw]}']`\n      } else if (type) {\n        return `$${type}.${raw}`\n      }\n    }\n\n    // fallback to ctx\n    return `_ctx.${raw}`\n  }\n\n  // fast path if expression is a simple identifier.\n  const rawExp = node.content\n\n  let ast = node.ast\n\n  if (ast === false) {\n    // ast being false means it has caused an error already during parse phase\n    return node\n  }\n\n  if (ast === null || (!ast && isSimpleIdentifier(rawExp))) {\n    const isScopeVarReference = context.identifiers[rawExp]\n    const isAllowedGlobal = isGloballyAllowed(rawExp)\n    const isLiteral = isLiteralWhitelisted(rawExp)\n    if (\n      !asParams &&\n      !isScopeVarReference &&\n      !isLiteral &&\n      (!isAllowedGlobal || bindingMetadata[rawExp])\n    ) {\n      // const bindings exposed from setup can be skipped for patching but\n      // cannot be hoisted to module scope\n      if (isConst(bindingMetadata[rawExp])) {\n        node.constType = ConstantTypes.CAN_SKIP_PATCH\n      }\n      node.content = rewriteIdentifier(rawExp)\n    } else if (!isScopeVarReference) {\n      if (isLiteral) {\n        node.constType = ConstantTypes.CAN_STRINGIFY\n      } else {\n        node.constType = ConstantTypes.CAN_CACHE\n      }\n    }\n    return node\n  }\n\n  if (!ast) {\n    // exp needs to be parsed differently:\n    // 1. Multiple inline statements (v-on, with presence of `;`): parse as raw\n    //    exp, but make sure to pad with spaces for consistent ranges\n    // 2. Expressions: wrap with parens (for e.g. object expressions)\n    // 3. Function arguments (v-for, v-slot): place in a function argument position\n    const source = asRawStatements\n      ? ` ${rawExp} `\n      : `(${rawExp})${asParams ? `=>{}` : ``}`\n    try {\n      ast = parseExpression(source, {\n        sourceType: 'module',\n        plugins: context.expressionPlugins,\n      })\n    } catch (e: any) {\n      context.onError(\n        createCompilerError(\n          ErrorCodes.X_INVALID_EXPRESSION,\n          node.loc,\n          undefined,\n          e.message,\n        ),\n      )\n      return node\n    }\n  }\n\n  type QualifiedId = Identifier & PrefixMeta\n  const ids: QualifiedId[] = []\n  const parentStack: Node[] = []\n  const knownIds: Record<string, number> = Object.create(context.identifiers)\n\n  walkIdentifiers(\n    ast,\n    (node, parent, _, isReferenced, isLocal) => {\n      if (isStaticPropertyKey(node, parent!)) {\n        return\n      }\n      // v2 wrapped filter call\n      if (__COMPAT__ && node.name.startsWith('_filter_')) {\n        return\n      }\n\n      const needPrefix = isReferenced && canPrefix(node)\n      if (needPrefix && !isLocal) {\n        if (isStaticProperty(parent!) && parent.shorthand) {\n          // property shorthand like { foo }, we need to add the key since\n          // we rewrite the value\n          ;(node as QualifiedId).prefix = `${node.name}: `\n        }\n        node.name = rewriteIdentifier(node.name, parent, node)\n        ids.push(node as QualifiedId)\n      } else {\n        // The identifier is considered constant unless it's pointing to a\n        // local scope variable (a v-for alias, or a v-slot prop)\n        if (\n          !(needPrefix && isLocal) &&\n          (!parent ||\n            (parent.type !== 'CallExpression' &&\n              parent.type !== 'NewExpression' &&\n              parent.type !== 'MemberExpression'))\n        ) {\n          ;(node as QualifiedId).isConstant = true\n        }\n        // also generate sub-expressions for other identifiers for better\n        // source map support. (except for property keys which are static)\n        ids.push(node as QualifiedId)\n      }\n    },\n    true, // invoke on ALL identifiers\n    parentStack,\n    knownIds,\n  )\n\n  // We break up the compound expression into an array of strings and sub\n  // expressions (for identifiers that have been prefixed). In codegen, if\n  // an ExpressionNode has the `.children` property, it will be used instead of\n  // `.content`.\n  const children: CompoundExpressionNode['children'] = []\n  ids.sort((a, b) => a.start - b.start)\n  ids.forEach((id, i) => {\n    // range is offset by -1 due to the wrapping parens when parsed\n    const start = id.start - 1\n    const end = id.end - 1\n    const last = ids[i - 1]\n    const leadingText = rawExp.slice(last ? last.end - 1 : 0, start)\n    if (leadingText.length || id.prefix) {\n      children.push(leadingText + (id.prefix || ``))\n    }\n    const source = rawExp.slice(start, end)\n    children.push(\n      createSimpleExpression(\n        id.name,\n        false,\n        {\n          start: advancePositionWithClone(node.loc.start, source, start),\n          end: advancePositionWithClone(node.loc.start, source, end),\n          source,\n        },\n        id.isConstant\n          ? ConstantTypes.CAN_STRINGIFY\n          : ConstantTypes.NOT_CONSTANT,\n      ),\n    )\n    if (i === ids.length - 1 && end < rawExp.length) {\n      children.push(rawExp.slice(end))\n    }\n  })\n\n  let ret\n  if (children.length) {\n    ret = createCompoundExpression(children, node.loc)\n    ret.ast = ast\n  } else {\n    ret = node\n    ret.constType = ConstantTypes.CAN_STRINGIFY\n  }\n  ret.identifiers = Object.keys(knownIds)\n  return ret\n}\n\nfunction canPrefix(id: Identifier) {\n  // skip whitelisted globals\n  if (isGloballyAllowed(id.name)) {\n    return false\n  }\n  // special case for webpack compilation\n  if (id.name === 'require') {\n    return false\n  }\n  return true\n}\n\nexport function stringifyExpression(exp: ExpressionNode | string): string {\n  if (isString(exp)) {\n    return exp\n  } else if (exp.type === NodeTypes.SIMPLE_EXPRESSION) {\n    return exp.content\n  } else {\n    return (exp.children as (ExpressionNode | string)[])\n      .map(stringifyExpression)\n      .join('')\n  }\n}\n\nfunction isConst(type: unknown) {\n  return (\n    type === BindingTypes.SETUP_CONST || type === BindingTypes.LITERAL_CONST\n  )\n}\n"
  },
  {
    "path": "packages/compiler-core/src/transforms/transformSlotOutlet.ts",
    "content": "import type { NodeTransform, TransformContext } from '../transform'\nimport {\n  type CallExpression,\n  type ExpressionNode,\n  NodeTypes,\n  type SlotOutletNode,\n  createCallExpression,\n  createFunctionExpression,\n  createSimpleExpression,\n} from '../ast'\nimport { isSlotOutlet, isStaticArgOf, isStaticExp } from '../utils'\nimport { type PropsExpression, buildProps } from './transformElement'\nimport { ErrorCodes, createCompilerError } from '../errors'\nimport { RENDER_SLOT } from '../runtimeHelpers'\nimport { camelize } from '@vue/shared'\nimport { processExpression } from './transformExpression'\n\nexport const transformSlotOutlet: NodeTransform = (node, context) => {\n  if (isSlotOutlet(node)) {\n    const { children, loc } = node\n    const { slotName, slotProps } = processSlotOutlet(node, context)\n\n    const slotArgs: CallExpression['arguments'] = [\n      context.prefixIdentifiers ? `_ctx.$slots` : `$slots`,\n      slotName,\n      '{}',\n      'undefined',\n      'true',\n    ]\n    let expectedLen = 2\n\n    if (slotProps) {\n      slotArgs[2] = slotProps\n      expectedLen = 3\n    }\n\n    if (children.length) {\n      slotArgs[3] = createFunctionExpression([], children, false, false, loc)\n      expectedLen = 4\n    }\n\n    if (context.scopeId && !context.slotted) {\n      expectedLen = 5\n    }\n    slotArgs.splice(expectedLen) // remove unused arguments\n\n    node.codegenNode = createCallExpression(\n      context.helper(RENDER_SLOT),\n      slotArgs,\n      loc,\n    )\n  }\n}\n\ninterface SlotOutletProcessResult {\n  slotName: string | ExpressionNode\n  slotProps: PropsExpression | undefined\n}\n\nexport function processSlotOutlet(\n  node: SlotOutletNode,\n  context: TransformContext,\n): SlotOutletProcessResult {\n  let slotName: string | ExpressionNode = `\"default\"`\n  let slotProps: PropsExpression | undefined = undefined\n\n  const nonNameProps = []\n  for (let i = 0; i < node.props.length; i++) {\n    const p = node.props[i]\n    if (p.type === NodeTypes.ATTRIBUTE) {\n      if (p.value) {\n        if (p.name === 'name') {\n          slotName = JSON.stringify(p.value.content)\n        } else {\n          p.name = camelize(p.name)\n          nonNameProps.push(p)\n        }\n      }\n    } else {\n      if (p.name === 'bind' && isStaticArgOf(p.arg, 'name')) {\n        if (p.exp) {\n          slotName = p.exp\n        } else if (p.arg && p.arg.type === NodeTypes.SIMPLE_EXPRESSION) {\n          const name = camelize(p.arg.content)\n          slotName = p.exp = createSimpleExpression(name, false, p.arg.loc)\n          if (!__BROWSER__) {\n            slotName = p.exp = processExpression(p.exp, context)\n          }\n        }\n      } else {\n        if (p.name === 'bind' && p.arg && isStaticExp(p.arg)) {\n          p.arg.content = camelize(p.arg.content)\n        }\n        nonNameProps.push(p)\n      }\n    }\n  }\n\n  if (nonNameProps.length > 0) {\n    const { props, directives } = buildProps(\n      node,\n      context,\n      nonNameProps,\n      false,\n      false,\n    )\n    slotProps = props\n\n    if (directives.length) {\n      context.onError(\n        createCompilerError(\n          ErrorCodes.X_V_SLOT_UNEXPECTED_DIRECTIVE_ON_SLOT_OUTLET,\n          directives[0].loc,\n        ),\n      )\n    }\n  }\n\n  return {\n    slotName,\n    slotProps,\n  }\n}\n"
  },
  {
    "path": "packages/compiler-core/src/transforms/transformText.ts",
    "content": "import type { NodeTransform } from '../transform'\nimport {\n  type CallExpression,\n  type CompoundExpressionNode,\n  ConstantTypes,\n  ElementTypes,\n  NodeTypes,\n  createCallExpression,\n  createCompoundExpression,\n} from '../ast'\nimport { isText } from '../utils'\nimport { CREATE_TEXT } from '../runtimeHelpers'\nimport { PatchFlagNames, PatchFlags } from '@vue/shared'\nimport { getConstantType } from './cacheStatic'\n\n// Merge adjacent text nodes and expressions into a single expression\n// e.g. <div>abc {{ d }} {{ e }}</div> should have a single expression node as child.\nexport const transformText: NodeTransform = (node, context) => {\n  if (\n    node.type === NodeTypes.ROOT ||\n    node.type === NodeTypes.ELEMENT ||\n    node.type === NodeTypes.FOR ||\n    node.type === NodeTypes.IF_BRANCH\n  ) {\n    // perform the transform on node exit so that all expressions have already\n    // been processed.\n    return () => {\n      const children = node.children\n      let currentContainer: CompoundExpressionNode | undefined = undefined\n      let hasText = false\n\n      for (let i = 0; i < children.length; i++) {\n        const child = children[i]\n        if (isText(child)) {\n          hasText = true\n          for (let j = i + 1; j < children.length; j++) {\n            const next = children[j]\n            if (isText(next)) {\n              if (!currentContainer) {\n                currentContainer = children[i] = createCompoundExpression(\n                  [child],\n                  child.loc,\n                )\n              }\n              // merge adjacent text node into current\n              currentContainer.children.push(` + `, next)\n              children.splice(j, 1)\n              j--\n            } else {\n              currentContainer = undefined\n              break\n            }\n          }\n        }\n      }\n\n      if (\n        !hasText ||\n        // if this is a plain element with a single text child, leave it\n        // as-is since the runtime has dedicated fast path for this by directly\n        // setting textContent of the element.\n        // for component root it's always normalized anyway.\n        (children.length === 1 &&\n          (node.type === NodeTypes.ROOT ||\n            (node.type === NodeTypes.ELEMENT &&\n              node.tagType === ElementTypes.ELEMENT &&\n              // #3756\n              // custom directives can potentially add DOM elements arbitrarily,\n              // we need to avoid setting textContent of the element at runtime\n              // to avoid accidentally overwriting the DOM elements added\n              // by the user through custom directives.\n              !node.props.find(\n                p =>\n                  p.type === NodeTypes.DIRECTIVE &&\n                  !context.directiveTransforms[p.name],\n              ) &&\n              // in compat mode, <template> tags with no special directives\n              // will be rendered as a fragment so its children must be\n              // converted into vnodes.\n              !(__COMPAT__ && node.tag === 'template'))))\n      ) {\n        return\n      }\n\n      // pre-convert text nodes into createTextVNode(text) calls to avoid\n      // runtime normalization.\n      for (let i = 0; i < children.length; i++) {\n        const child = children[i]\n        if (isText(child) || child.type === NodeTypes.COMPOUND_EXPRESSION) {\n          const callArgs: CallExpression['arguments'] = []\n          // createTextVNode defaults to single whitespace, so if it is a\n          // single space the code could be an empty call to save bytes.\n          if (child.type !== NodeTypes.TEXT || child.content !== ' ') {\n            callArgs.push(child)\n          }\n          // mark dynamic text with flag so it gets patched inside a block\n          if (\n            !context.ssr &&\n            getConstantType(child, context) === ConstantTypes.NOT_CONSTANT\n          ) {\n            callArgs.push(\n              PatchFlags.TEXT +\n                (__DEV__ ? ` /* ${PatchFlagNames[PatchFlags.TEXT]} */` : ``),\n            )\n          }\n          children[i] = {\n            type: NodeTypes.TEXT_CALL,\n            content: child,\n            loc: child.loc,\n            codegenNode: createCallExpression(\n              context.helper(CREATE_TEXT),\n              callArgs,\n            ),\n          }\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "packages/compiler-core/src/transforms/transformVBindShorthand.ts",
    "content": "import { camelize } from '@vue/shared'\nimport {\n  NodeTypes,\n  type SimpleExpressionNode,\n  createSimpleExpression,\n} from '../ast'\nimport type { NodeTransform } from '../transform'\nimport { ErrorCodes, createCompilerError } from '../errors'\nimport { validFirstIdentCharRE } from '../utils'\n\nexport const transformVBindShorthand: NodeTransform = (node, context) => {\n  if (node.type === NodeTypes.ELEMENT) {\n    for (const prop of node.props) {\n      // same-name shorthand - :arg is expanded to :arg=\"arg\"\n      if (\n        prop.type === NodeTypes.DIRECTIVE &&\n        prop.name === 'bind' &&\n        (!prop.exp ||\n          // #13930 :foo in in-DOM templates will be parsed into :foo=\"\" by browser\n          (__BROWSER__ &&\n            prop.exp.type === NodeTypes.SIMPLE_EXPRESSION &&\n            !prop.exp.content.trim())) &&\n        prop.arg\n      ) {\n        const arg = prop.arg\n        if (arg.type !== NodeTypes.SIMPLE_EXPRESSION || !arg.isStatic) {\n          // only simple expression is allowed for same-name shorthand\n          context.onError(\n            createCompilerError(\n              ErrorCodes.X_V_BIND_INVALID_SAME_NAME_ARGUMENT,\n              arg.loc,\n            ),\n          )\n          prop.exp = createSimpleExpression('', true, arg.loc)\n        } else {\n          const propName = camelize((arg as SimpleExpressionNode).content)\n          if (\n            validFirstIdentCharRE.test(propName[0]) ||\n            // allow hyphen first char for https://github.com/vuejs/language-tools/pull/3424\n            propName[0] === '-'\n          ) {\n            prop.exp = createSimpleExpression(propName, false, arg.loc)\n          }\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "packages/compiler-core/src/transforms/vBind.ts",
    "content": "import type { DirectiveTransform } from '../transform'\nimport {\n  type ExpressionNode,\n  NodeTypes,\n  createObjectProperty,\n  createSimpleExpression,\n} from '../ast'\nimport { ErrorCodes, createCompilerError } from '../errors'\nimport { camelize } from '@vue/shared'\nimport { CAMELIZE } from '../runtimeHelpers'\n\n// v-bind without arg is handled directly in ./transformElement.ts due to its affecting\n// codegen for the entire props object. This transform here is only for v-bind\n// *with* args.\nexport const transformBind: DirectiveTransform = (dir, _node, context) => {\n  const { modifiers, loc } = dir\n  const arg = dir.arg!\n\n  let { exp } = dir\n\n  // handle empty expression\n  if (exp && exp.type === NodeTypes.SIMPLE_EXPRESSION && !exp.content.trim()) {\n    if (!__BROWSER__) {\n      // #10280 only error against empty expression in non-browser build\n      // because :foo in in-DOM templates will be parsed into :foo=\"\" by the\n      // browser\n      context.onError(\n        createCompilerError(ErrorCodes.X_V_BIND_NO_EXPRESSION, loc),\n      )\n      return {\n        props: [\n          createObjectProperty(arg, createSimpleExpression('', true, loc)),\n        ],\n      }\n    } else {\n      exp = undefined\n    }\n  }\n\n  if (arg.type !== NodeTypes.SIMPLE_EXPRESSION) {\n    arg.children.unshift(`(`)\n    arg.children.push(`) || \"\"`)\n  } else if (!arg.isStatic) {\n    arg.content = arg.content ? `${arg.content} || \"\"` : `\"\"`\n  }\n\n  // .sync is replaced by v-model:arg\n  if (modifiers.some(mod => mod.content === 'camel')) {\n    if (arg.type === NodeTypes.SIMPLE_EXPRESSION) {\n      if (arg.isStatic) {\n        arg.content = camelize(arg.content)\n      } else {\n        arg.content = `${context.helperString(CAMELIZE)}(${arg.content})`\n      }\n    } else {\n      arg.children.unshift(`${context.helperString(CAMELIZE)}(`)\n      arg.children.push(`)`)\n    }\n  }\n\n  if (!context.inSSR) {\n    if (modifiers.some(mod => mod.content === 'prop')) {\n      injectPrefix(arg, '.')\n    }\n    if (modifiers.some(mod => mod.content === 'attr')) {\n      injectPrefix(arg, '^')\n    }\n  }\n\n  return {\n    props: [createObjectProperty(arg, exp!)],\n  }\n}\n\nconst injectPrefix = (arg: ExpressionNode, prefix: string) => {\n  if (arg.type === NodeTypes.SIMPLE_EXPRESSION) {\n    if (arg.isStatic) {\n      arg.content = prefix + arg.content\n    } else {\n      arg.content = `\\`${prefix}\\${${arg.content}}\\``\n    }\n  } else {\n    arg.children.unshift(`'${prefix}' + (`)\n    arg.children.push(`)`)\n  }\n}\n"
  },
  {
    "path": "packages/compiler-core/src/transforms/vFor.ts",
    "content": "import {\n  type NodeTransform,\n  type TransformContext,\n  createStructuralDirectiveTransform,\n} from '../transform'\nimport {\n  type BlockCodegenNode,\n  ConstantTypes,\n  type DirectiveNode,\n  type ElementNode,\n  type ExpressionNode,\n  type ForCodegenNode,\n  type ForIteratorExpression,\n  type ForNode,\n  type ForParseResult,\n  type ForRenderListExpression,\n  NodeTypes,\n  type PlainElementNode,\n  type RenderSlotCall,\n  type SimpleExpressionNode,\n  type SlotOutletNode,\n  type VNodeCall,\n  createBlockStatement,\n  createCallExpression,\n  createCompoundExpression,\n  createFunctionExpression,\n  createObjectExpression,\n  createObjectProperty,\n  createSimpleExpression,\n  createVNodeCall,\n  getVNodeBlockHelper,\n  getVNodeHelper,\n} from '../ast'\nimport { ErrorCodes, createCompilerError } from '../errors'\nimport {\n  findDir,\n  findProp,\n  injectProp,\n  isSlotOutlet,\n  isTemplateNode,\n} from '../utils'\nimport {\n  FRAGMENT,\n  IS_MEMO_SAME,\n  OPEN_BLOCK,\n  RENDER_LIST,\n} from '../runtimeHelpers'\nimport { processExpression } from './transformExpression'\nimport { validateBrowserExpression } from '../validateExpression'\nimport { PatchFlags } from '@vue/shared'\n\nexport const transformFor: NodeTransform = createStructuralDirectiveTransform(\n  'for',\n  (node, dir, context) => {\n    const { helper, removeHelper } = context\n    return processFor(node, dir, context, forNode => {\n      // create the loop render function expression now, and add the\n      // iterator on exit after all children have been traversed\n      const renderExp = createCallExpression(helper(RENDER_LIST), [\n        forNode.source,\n      ]) as ForRenderListExpression\n      const isTemplate = isTemplateNode(node)\n      const memo = findDir(node, 'memo')\n      const keyProp = findProp(node, `key`, false, true)\n      const isDirKey = keyProp && keyProp.type === NodeTypes.DIRECTIVE\n      let keyExp =\n        keyProp &&\n        (keyProp.type === NodeTypes.ATTRIBUTE\n          ? keyProp.value\n            ? createSimpleExpression(keyProp.value.content, true)\n            : undefined\n          : keyProp.exp)\n\n      if (memo && keyExp && isDirKey) {\n        if (!__BROWSER__) {\n          keyProp.exp = keyExp = processExpression(\n            keyExp as SimpleExpressionNode,\n            context,\n          )\n        }\n      }\n      const keyProperty =\n        keyProp && keyExp ? createObjectProperty(`key`, keyExp) : null\n\n      if (!__BROWSER__ && isTemplate) {\n        // #2085 / #5288 process :key and v-memo expressions need to be\n        // processed on `<template v-for>`. In this case the node is discarded\n        // and never traversed so its binding expressions won't be processed\n        // by the normal transforms.\n        if (memo) {\n          memo.exp = processExpression(\n            memo.exp! as SimpleExpressionNode,\n            context,\n          )\n        }\n        if (keyProperty && keyProp!.type !== NodeTypes.ATTRIBUTE) {\n          keyProperty.value = processExpression(\n            keyProperty.value as SimpleExpressionNode,\n            context,\n          )\n        }\n      }\n\n      const isStableFragment =\n        forNode.source.type === NodeTypes.SIMPLE_EXPRESSION &&\n        forNode.source.constType > ConstantTypes.NOT_CONSTANT\n      const fragmentFlag = isStableFragment\n        ? PatchFlags.STABLE_FRAGMENT\n        : keyProp\n          ? PatchFlags.KEYED_FRAGMENT\n          : PatchFlags.UNKEYED_FRAGMENT\n\n      forNode.codegenNode = createVNodeCall(\n        context,\n        helper(FRAGMENT),\n        undefined,\n        renderExp,\n        fragmentFlag,\n        undefined,\n        undefined,\n        true /* isBlock */,\n        !isStableFragment /* disableTracking */,\n        false /* isComponent */,\n        node.loc,\n      ) as ForCodegenNode\n\n      return () => {\n        // finish the codegen now that all children have been traversed\n        let childBlock: BlockCodegenNode\n        const { children } = forNode\n\n        // check <template v-for> key placement\n        if ((__DEV__ || !__BROWSER__) && isTemplate) {\n          node.children.some(c => {\n            if (c.type === NodeTypes.ELEMENT) {\n              const key = findProp(c, 'key')\n              if (key) {\n                context.onError(\n                  createCompilerError(\n                    ErrorCodes.X_V_FOR_TEMPLATE_KEY_PLACEMENT,\n                    key.loc,\n                  ),\n                )\n                return true\n              }\n            }\n          })\n        }\n\n        const needFragmentWrapper =\n          children.length !== 1 || children[0].type !== NodeTypes.ELEMENT\n        const slotOutlet = isSlotOutlet(node)\n          ? node\n          : isTemplate &&\n              node.children.length === 1 &&\n              isSlotOutlet(node.children[0])\n            ? (node.children[0] as SlotOutletNode) // api-extractor somehow fails to infer this\n            : null\n\n        if (slotOutlet) {\n          // <slot v-for=\"...\"> or <template v-for=\"...\"><slot/></template>\n          childBlock = slotOutlet.codegenNode as RenderSlotCall\n          if (isTemplate && keyProperty) {\n            // <template v-for=\"...\" :key=\"...\"><slot/></template>\n            // we need to inject the key to the renderSlot() call.\n            // the props for renderSlot is passed as the 3rd argument.\n            injectProp(childBlock, keyProperty, context)\n          }\n        } else if (needFragmentWrapper) {\n          // <template v-for=\"...\"> with text or multi-elements\n          // should generate a fragment block for each loop\n          childBlock = createVNodeCall(\n            context,\n            helper(FRAGMENT),\n            keyProperty ? createObjectExpression([keyProperty]) : undefined,\n            node.children,\n            PatchFlags.STABLE_FRAGMENT,\n            undefined,\n            undefined,\n            true,\n            undefined,\n            false /* isComponent */,\n          )\n        } else {\n          // Normal element v-for. Directly use the child's codegenNode\n          // but mark it as a block.\n          childBlock = (children[0] as PlainElementNode)\n            .codegenNode as VNodeCall\n          if (isTemplate && keyProperty) {\n            injectProp(childBlock, keyProperty, context)\n          }\n          if (childBlock.isBlock !== !isStableFragment) {\n            if (childBlock.isBlock) {\n              // switch from block to vnode\n              removeHelper(OPEN_BLOCK)\n              removeHelper(\n                getVNodeBlockHelper(context.inSSR, childBlock.isComponent),\n              )\n            } else {\n              // switch from vnode to block\n              removeHelper(\n                getVNodeHelper(context.inSSR, childBlock.isComponent),\n              )\n            }\n          }\n          childBlock.isBlock = !isStableFragment\n          if (childBlock.isBlock) {\n            helper(OPEN_BLOCK)\n            helper(getVNodeBlockHelper(context.inSSR, childBlock.isComponent))\n          } else {\n            helper(getVNodeHelper(context.inSSR, childBlock.isComponent))\n          }\n        }\n\n        if (memo) {\n          const loop = createFunctionExpression(\n            createForLoopParams(forNode.parseResult, [\n              createSimpleExpression(`_cached`),\n            ]),\n          )\n          loop.body = createBlockStatement([\n            createCompoundExpression([`const _memo = (`, memo.exp!, `)`]),\n            createCompoundExpression([\n              `if (_cached`,\n              ...(keyExp ? [` && _cached.key === `, keyExp] : []),\n              ` && ${context.helperString(\n                IS_MEMO_SAME,\n              )}(_cached, _memo)) return _cached`,\n            ]),\n            createCompoundExpression([`const _item = `, childBlock as any]),\n            createSimpleExpression(`_item.memo = _memo`),\n            createSimpleExpression(`return _item`),\n          ])\n          renderExp.arguments.push(\n            loop as ForIteratorExpression,\n            createSimpleExpression(`_cache`),\n            createSimpleExpression(String(context.cached.length)),\n          )\n          // increment cache count\n          context.cached.push(null)\n        } else {\n          renderExp.arguments.push(\n            createFunctionExpression(\n              createForLoopParams(forNode.parseResult),\n              childBlock,\n              true /* force newline */,\n            ) as ForIteratorExpression,\n          )\n        }\n      }\n    })\n  },\n)\n\n// target-agnostic transform used for both Client and SSR\nexport function processFor(\n  node: ElementNode,\n  dir: DirectiveNode,\n  context: TransformContext,\n  processCodegen?: (forNode: ForNode) => (() => void) | undefined,\n): (() => void) | undefined {\n  if (!dir.exp) {\n    context.onError(\n      createCompilerError(ErrorCodes.X_V_FOR_NO_EXPRESSION, dir.loc),\n    )\n    return\n  }\n\n  const parseResult = dir.forParseResult\n\n  if (!parseResult) {\n    context.onError(\n      createCompilerError(ErrorCodes.X_V_FOR_MALFORMED_EXPRESSION, dir.loc),\n    )\n    return\n  }\n\n  finalizeForParseResult(parseResult, context)\n\n  const { addIdentifiers, removeIdentifiers, scopes } = context\n  const { source, value, key, index } = parseResult\n\n  const forNode: ForNode = {\n    type: NodeTypes.FOR,\n    loc: dir.loc,\n    source,\n    valueAlias: value,\n    keyAlias: key,\n    objectIndexAlias: index,\n    parseResult,\n    children: isTemplateNode(node) ? node.children : [node],\n  }\n\n  context.replaceNode(forNode)\n\n  // bookkeeping\n  scopes.vFor++\n  if (!__BROWSER__ && context.prefixIdentifiers) {\n    // scope management\n    // inject identifiers to context\n    value && addIdentifiers(value)\n    key && addIdentifiers(key)\n    index && addIdentifiers(index)\n  }\n\n  const onExit = processCodegen && processCodegen(forNode)\n\n  return (): void => {\n    scopes.vFor--\n    if (!__BROWSER__ && context.prefixIdentifiers) {\n      value && removeIdentifiers(value)\n      key && removeIdentifiers(key)\n      index && removeIdentifiers(index)\n    }\n    if (onExit) onExit()\n  }\n}\n\nexport function finalizeForParseResult(\n  result: ForParseResult,\n  context: TransformContext,\n): void {\n  if (result.finalized) return\n\n  if (!__BROWSER__ && context.prefixIdentifiers) {\n    result.source = processExpression(\n      result.source as SimpleExpressionNode,\n      context,\n    )\n    if (result.key) {\n      result.key = processExpression(\n        result.key as SimpleExpressionNode,\n        context,\n        true,\n      )\n    }\n    if (result.index) {\n      result.index = processExpression(\n        result.index as SimpleExpressionNode,\n        context,\n        true,\n      )\n    }\n    if (result.value) {\n      result.value = processExpression(\n        result.value as SimpleExpressionNode,\n        context,\n        true,\n      )\n    }\n  }\n  if (__DEV__ && __BROWSER__) {\n    validateBrowserExpression(result.source as SimpleExpressionNode, context)\n    if (result.key) {\n      validateBrowserExpression(\n        result.key as SimpleExpressionNode,\n        context,\n        true,\n      )\n    }\n    if (result.index) {\n      validateBrowserExpression(\n        result.index as SimpleExpressionNode,\n        context,\n        true,\n      )\n    }\n    if (result.value) {\n      validateBrowserExpression(\n        result.value as SimpleExpressionNode,\n        context,\n        true,\n      )\n    }\n  }\n  result.finalized = true\n}\n\nexport function createForLoopParams(\n  { value, key, index }: ForParseResult,\n  memoArgs: ExpressionNode[] = [],\n): ExpressionNode[] {\n  return createParamsList([value, key, index, ...memoArgs])\n}\n\nfunction createParamsList(\n  args: (ExpressionNode | undefined)[],\n): ExpressionNode[] {\n  let i = args.length\n  while (i--) {\n    if (args[i]) break\n  }\n  return args\n    .slice(0, i + 1)\n    .map((arg, i) => arg || createSimpleExpression(`_`.repeat(i + 1), false))\n}\n"
  },
  {
    "path": "packages/compiler-core/src/transforms/vIf.ts",
    "content": "import {\n  type NodeTransform,\n  type TransformContext,\n  createStructuralDirectiveTransform,\n  traverseNode,\n} from '../transform'\nimport {\n  type AttributeNode,\n  type BlockCodegenNode,\n  type CacheExpression,\n  ConstantTypes,\n  type DirectiveNode,\n  type ElementNode,\n  ElementTypes,\n  type IfBranchNode,\n  type IfConditionalExpression,\n  type IfNode,\n  type MemoExpression,\n  NodeTypes,\n  type SimpleExpressionNode,\n  convertToBlock,\n  createCallExpression,\n  createConditionalExpression,\n  createObjectExpression,\n  createObjectProperty,\n  createSimpleExpression,\n  createVNodeCall,\n  locStub,\n} from '../ast'\nimport { ErrorCodes, createCompilerError } from '../errors'\nimport { processExpression } from './transformExpression'\nimport { validateBrowserExpression } from '../validateExpression'\nimport { cloneLoc } from '../parser'\nimport { CREATE_COMMENT, FRAGMENT } from '../runtimeHelpers'\nimport {\n  findDir,\n  findProp,\n  getMemoedVNodeCall,\n  injectProp,\n  isCommentOrWhitespace,\n} from '../utils'\nimport { PatchFlags } from '@vue/shared'\n\nexport const transformIf: NodeTransform = createStructuralDirectiveTransform(\n  /^(?:if|else|else-if)$/,\n  (node, dir, context) => {\n    return processIf(node, dir, context, (ifNode, branch, isRoot) => {\n      // #1587: We need to dynamically increment the key based on the current\n      // node's sibling nodes, since chained v-if/else branches are\n      // rendered at the same depth\n      const siblings = context.parent!.children\n      let i = siblings.indexOf(ifNode)\n      let key = 0\n      while (i-- >= 0) {\n        const sibling = siblings[i]\n        if (sibling && sibling.type === NodeTypes.IF) {\n          key += sibling.branches.length\n        }\n      }\n\n      // Exit callback. Complete the codegenNode when all children have been\n      // transformed.\n      return () => {\n        if (isRoot) {\n          ifNode.codegenNode = createCodegenNodeForBranch(\n            branch,\n            key,\n            context,\n          ) as IfConditionalExpression\n        } else {\n          // attach this branch's codegen node to the v-if root.\n          const parentCondition = getParentCondition(ifNode.codegenNode!)\n          parentCondition.alternate = createCodegenNodeForBranch(\n            branch,\n            key + ifNode.branches.length - 1,\n            context,\n          )\n        }\n      }\n    })\n  },\n)\n\n// target-agnostic transform used for both Client and SSR\nexport function processIf(\n  node: ElementNode,\n  dir: DirectiveNode,\n  context: TransformContext,\n  processCodegen?: (\n    node: IfNode,\n    branch: IfBranchNode,\n    isRoot: boolean,\n  ) => (() => void) | undefined,\n): (() => void) | undefined {\n  if (\n    dir.name !== 'else' &&\n    (!dir.exp || !(dir.exp as SimpleExpressionNode).content.trim())\n  ) {\n    const loc = dir.exp ? dir.exp.loc : node.loc\n    context.onError(\n      createCompilerError(ErrorCodes.X_V_IF_NO_EXPRESSION, dir.loc),\n    )\n    dir.exp = createSimpleExpression(`true`, false, loc)\n  }\n\n  if (!__BROWSER__ && context.prefixIdentifiers && dir.exp) {\n    // dir.exp can only be simple expression because vIf transform is applied\n    // before expression transform.\n    dir.exp = processExpression(dir.exp as SimpleExpressionNode, context)\n  }\n\n  if (__DEV__ && __BROWSER__ && dir.exp) {\n    validateBrowserExpression(dir.exp as SimpleExpressionNode, context)\n  }\n\n  if (dir.name === 'if') {\n    const branch = createIfBranch(node, dir)\n    const ifNode: IfNode = {\n      type: NodeTypes.IF,\n      loc: cloneLoc(node.loc),\n      branches: [branch],\n    }\n    context.replaceNode(ifNode)\n    if (processCodegen) {\n      return processCodegen(ifNode, branch, true)\n    }\n  } else {\n    // locate the adjacent v-if\n    const siblings = context.parent!.children\n    const comments = []\n    let i = siblings.indexOf(node)\n    while (i-- >= -1) {\n      const sibling = siblings[i]\n      if (sibling && isCommentOrWhitespace(sibling)) {\n        context.removeNode(sibling)\n        if (__DEV__ && sibling.type === NodeTypes.COMMENT) {\n          comments.unshift(sibling)\n        }\n        continue\n      }\n\n      if (sibling && sibling.type === NodeTypes.IF) {\n        // Check if v-else was followed by v-else-if or there are two adjacent v-else\n        if (\n          (dir.name === 'else-if' || dir.name === 'else') &&\n          sibling.branches[sibling.branches.length - 1].condition === undefined\n        ) {\n          context.onError(\n            createCompilerError(ErrorCodes.X_V_ELSE_NO_ADJACENT_IF, node.loc),\n          )\n        }\n\n        // move the node to the if node's branches\n        context.removeNode()\n        const branch = createIfBranch(node, dir)\n        if (\n          __DEV__ &&\n          comments.length &&\n          // #3619 ignore comments if the v-if is direct child of <transition>\n          !(\n            context.parent &&\n            context.parent.type === NodeTypes.ELEMENT &&\n            (context.parent.tag === 'transition' ||\n              context.parent.tag === 'Transition')\n          )\n        ) {\n          branch.children = [...comments, ...branch.children]\n        }\n\n        // check if user is forcing same key on different branches\n        if (__DEV__ || !__BROWSER__) {\n          const key = branch.userKey\n          if (key) {\n            sibling.branches.forEach(({ userKey }) => {\n              if (isSameKey(userKey, key)) {\n                context.onError(\n                  createCompilerError(\n                    ErrorCodes.X_V_IF_SAME_KEY,\n                    branch.userKey!.loc,\n                  ),\n                )\n              }\n            })\n          }\n        }\n\n        sibling.branches.push(branch)\n        const onExit = processCodegen && processCodegen(sibling, branch, false)\n        // since the branch was removed, it will not be traversed.\n        // make sure to traverse here.\n        traverseNode(branch, context)\n        // call on exit\n        if (onExit) onExit()\n        // make sure to reset currentNode after traversal to indicate this\n        // node has been removed.\n        context.currentNode = null\n      } else {\n        context.onError(\n          createCompilerError(ErrorCodes.X_V_ELSE_NO_ADJACENT_IF, node.loc),\n        )\n      }\n      break\n    }\n  }\n}\n\nfunction createIfBranch(node: ElementNode, dir: DirectiveNode): IfBranchNode {\n  const isTemplateIf = node.tagType === ElementTypes.TEMPLATE\n  return {\n    type: NodeTypes.IF_BRANCH,\n    loc: node.loc,\n    condition: dir.name === 'else' ? undefined : dir.exp,\n    children: isTemplateIf && !findDir(node, 'for') ? node.children : [node],\n    userKey: findProp(node, `key`),\n    isTemplateIf,\n  }\n}\n\nfunction createCodegenNodeForBranch(\n  branch: IfBranchNode,\n  keyIndex: number,\n  context: TransformContext,\n): IfConditionalExpression | BlockCodegenNode | MemoExpression {\n  if (branch.condition) {\n    return createConditionalExpression(\n      branch.condition,\n      createChildrenCodegenNode(branch, keyIndex, context),\n      // make sure to pass in asBlock: true so that the comment node call\n      // closes the current block.\n      createCallExpression(context.helper(CREATE_COMMENT), [\n        __DEV__ ? '\"v-if\"' : '\"\"',\n        'true',\n      ]),\n    ) as IfConditionalExpression\n  } else {\n    return createChildrenCodegenNode(branch, keyIndex, context)\n  }\n}\n\nfunction createChildrenCodegenNode(\n  branch: IfBranchNode,\n  keyIndex: number,\n  context: TransformContext,\n): BlockCodegenNode | MemoExpression {\n  const { helper } = context\n  const keyProperty = createObjectProperty(\n    `key`,\n    createSimpleExpression(\n      `${keyIndex}`,\n      false,\n      locStub,\n      ConstantTypes.CAN_CACHE,\n    ),\n  )\n  const { children } = branch\n  const firstChild = children[0]\n  const needFragmentWrapper =\n    children.length !== 1 || firstChild.type !== NodeTypes.ELEMENT\n  if (needFragmentWrapper) {\n    if (children.length === 1 && firstChild.type === NodeTypes.FOR) {\n      // optimize away nested fragments when child is a ForNode\n      const vnodeCall = firstChild.codegenNode!\n      injectProp(vnodeCall, keyProperty, context)\n      return vnodeCall\n    } else {\n      let patchFlag = PatchFlags.STABLE_FRAGMENT\n      // check if the fragment actually contains a single valid child with\n      // the rest being comments\n      if (\n        __DEV__ &&\n        !branch.isTemplateIf &&\n        children.filter(c => c.type !== NodeTypes.COMMENT).length === 1\n      ) {\n        patchFlag |= PatchFlags.DEV_ROOT_FRAGMENT\n      }\n\n      return createVNodeCall(\n        context,\n        helper(FRAGMENT),\n        createObjectExpression([keyProperty]),\n        children,\n        patchFlag,\n        undefined,\n        undefined,\n        true,\n        false,\n        false /* isComponent */,\n        branch.loc,\n      )\n    }\n  } else {\n    const ret = (firstChild as ElementNode).codegenNode as\n      | BlockCodegenNode\n      | MemoExpression\n    const vnodeCall = getMemoedVNodeCall(ret)\n    // Change createVNode to createBlock.\n    if (vnodeCall.type === NodeTypes.VNODE_CALL) {\n      convertToBlock(vnodeCall, context)\n    }\n    // inject branch key\n    injectProp(vnodeCall, keyProperty, context)\n    return ret\n  }\n}\n\nfunction isSameKey(\n  a: AttributeNode | DirectiveNode | undefined,\n  b: AttributeNode | DirectiveNode,\n): boolean {\n  if (!a || a.type !== b.type) {\n    return false\n  }\n  if (a.type === NodeTypes.ATTRIBUTE) {\n    if (a.value!.content !== (b as AttributeNode).value!.content) {\n      return false\n    }\n  } else {\n    // directive\n    const exp = a.exp!\n    const branchExp = (b as DirectiveNode).exp!\n    if (exp.type !== branchExp.type) {\n      return false\n    }\n    if (\n      exp.type !== NodeTypes.SIMPLE_EXPRESSION ||\n      exp.isStatic !== (branchExp as SimpleExpressionNode).isStatic ||\n      exp.content !== (branchExp as SimpleExpressionNode).content\n    ) {\n      return false\n    }\n  }\n  return true\n}\n\nfunction getParentCondition(\n  node: IfConditionalExpression | CacheExpression,\n): IfConditionalExpression {\n  while (true) {\n    if (node.type === NodeTypes.JS_CONDITIONAL_EXPRESSION) {\n      if (node.alternate.type === NodeTypes.JS_CONDITIONAL_EXPRESSION) {\n        node = node.alternate\n      } else {\n        return node\n      }\n    } else if (node.type === NodeTypes.JS_CACHE_EXPRESSION) {\n      node = node.value as IfConditionalExpression\n    }\n  }\n}\n"
  },
  {
    "path": "packages/compiler-core/src/transforms/vMemo.ts",
    "content": "import type { NodeTransform } from '../transform'\nimport { findDir } from '../utils'\nimport {\n  ElementTypes,\n  type MemoExpression,\n  NodeTypes,\n  type PlainElementNode,\n  convertToBlock,\n  createCallExpression,\n  createFunctionExpression,\n} from '../ast'\nimport { WITH_MEMO } from '../runtimeHelpers'\n\nconst seen = new WeakSet()\n\nexport const transformMemo: NodeTransform = (node, context) => {\n  if (node.type === NodeTypes.ELEMENT) {\n    const dir = findDir(node, 'memo')\n    if (!dir || seen.has(node) || context.inSSR) {\n      return\n    }\n    seen.add(node)\n    return () => {\n      const codegenNode =\n        node.codegenNode ||\n        (context.currentNode as PlainElementNode).codegenNode\n      if (codegenNode && codegenNode.type === NodeTypes.VNODE_CALL) {\n        // non-component sub tree should be turned into a block\n        if (node.tagType !== ElementTypes.COMPONENT) {\n          convertToBlock(codegenNode, context)\n        }\n        node.codegenNode = createCallExpression(context.helper(WITH_MEMO), [\n          dir.exp!,\n          createFunctionExpression(undefined, codegenNode),\n          `_cache`,\n          String(context.cached.length),\n        ]) as MemoExpression\n        // increment cache count\n        context.cached.push(null)\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "packages/compiler-core/src/transforms/vModel.ts",
    "content": "import type { DirectiveTransform } from '../transform'\nimport {\n  ConstantTypes,\n  ElementTypes,\n  type ExpressionNode,\n  NodeTypes,\n  type Property,\n  createCompoundExpression,\n  createObjectProperty,\n  createSimpleExpression,\n} from '../ast'\nimport { ErrorCodes, createCompilerError } from '../errors'\nimport {\n  hasScopeRef,\n  isMemberExpression,\n  isSimpleIdentifier,\n  isStaticExp,\n} from '../utils'\nimport { IS_REF } from '../runtimeHelpers'\nimport { BindingTypes } from '../options'\nimport { camelize } from '@vue/shared'\n\nexport const transformModel: DirectiveTransform = (dir, node, context) => {\n  const { exp, arg } = dir\n  if (!exp) {\n    context.onError(\n      createCompilerError(ErrorCodes.X_V_MODEL_NO_EXPRESSION, dir.loc),\n    )\n    return createTransformProps()\n  }\n\n  // we assume v-model directives are always parsed\n  // (not artificially created by a transform)\n  const rawExp = exp.loc.source.trim()\n  const expString =\n    exp.type === NodeTypes.SIMPLE_EXPRESSION ? exp.content : rawExp\n\n  // im SFC <script setup> inline mode, the exp may have been transformed into\n  // _unref(exp)\n  const bindingType = context.bindingMetadata[rawExp]\n\n  // check props\n  if (\n    bindingType === BindingTypes.PROPS ||\n    bindingType === BindingTypes.PROPS_ALIASED\n  ) {\n    context.onError(createCompilerError(ErrorCodes.X_V_MODEL_ON_PROPS, exp.loc))\n    return createTransformProps()\n  }\n\n  // const bindings are not writable.\n  if (\n    bindingType === BindingTypes.LITERAL_CONST ||\n    bindingType === BindingTypes.SETUP_CONST\n  ) {\n    context.onError(createCompilerError(ErrorCodes.X_V_MODEL_ON_CONST, exp.loc))\n    return createTransformProps()\n  }\n\n  const maybeRef =\n    !__BROWSER__ &&\n    context.inline &&\n    (bindingType === BindingTypes.SETUP_LET ||\n      bindingType === BindingTypes.SETUP_REF ||\n      bindingType === BindingTypes.SETUP_MAYBE_REF)\n\n  if (!expString.trim() || (!isMemberExpression(exp, context) && !maybeRef)) {\n    context.onError(\n      createCompilerError(ErrorCodes.X_V_MODEL_MALFORMED_EXPRESSION, exp.loc),\n    )\n    return createTransformProps()\n  }\n\n  if (\n    !__BROWSER__ &&\n    context.prefixIdentifiers &&\n    isSimpleIdentifier(expString) &&\n    context.identifiers[expString]\n  ) {\n    context.onError(\n      createCompilerError(ErrorCodes.X_V_MODEL_ON_SCOPE_VARIABLE, exp.loc),\n    )\n    return createTransformProps()\n  }\n\n  const propName = arg ? arg : createSimpleExpression('modelValue', true)\n  const eventName = arg\n    ? isStaticExp(arg)\n      ? `onUpdate:${camelize(arg.content)}`\n      : createCompoundExpression(['\"onUpdate:\" + ', arg])\n    : `onUpdate:modelValue`\n\n  let assignmentExp: ExpressionNode\n  const eventArg = context.isTS ? `($event: any)` : `$event`\n  if (maybeRef) {\n    if (bindingType === BindingTypes.SETUP_REF) {\n      // v-model used on known ref.\n      assignmentExp = createCompoundExpression([\n        `${eventArg} => ((`,\n        createSimpleExpression(rawExp, false, exp.loc),\n        `).value = $event)`,\n      ])\n    } else {\n      // v-model used on a potentially ref binding in <script setup> inline mode.\n      // the assignment needs to check whether the binding is actually a ref.\n      const altAssignment =\n        bindingType === BindingTypes.SETUP_LET ? `${rawExp} = $event` : `null`\n      assignmentExp = createCompoundExpression([\n        `${eventArg} => (${context.helperString(IS_REF)}(${rawExp}) ? (`,\n        createSimpleExpression(rawExp, false, exp.loc),\n        `).value = $event : ${altAssignment})`,\n      ])\n    }\n  } else {\n    assignmentExp = createCompoundExpression([\n      `${eventArg} => ((`,\n      exp,\n      `) = $event)`,\n    ])\n  }\n\n  const props = [\n    // modelValue: foo\n    createObjectProperty(propName, dir.exp!),\n    // \"onUpdate:modelValue\": $event => (foo = $event)\n    createObjectProperty(eventName, assignmentExp),\n  ]\n\n  // cache v-model handler if applicable (when it doesn't refer any scope vars)\n  if (\n    !__BROWSER__ &&\n    context.prefixIdentifiers &&\n    !context.inVOnce &&\n    context.cacheHandlers &&\n    !hasScopeRef(exp, context.identifiers)\n  ) {\n    props[1].value = context.cache(props[1].value)\n  }\n\n  // modelModifiers: { foo: true, \"bar-baz\": true }\n  if (dir.modifiers.length && node.tagType === ElementTypes.COMPONENT) {\n    const modifiers = dir.modifiers\n      .map(m => m.content)\n      .map(m => (isSimpleIdentifier(m) ? m : JSON.stringify(m)) + `: true`)\n      .join(`, `)\n    const modifiersKey = arg\n      ? isStaticExp(arg)\n        ? `${arg.content}Modifiers`\n        : createCompoundExpression([arg, ' + \"Modifiers\"'])\n      : `modelModifiers`\n    props.push(\n      createObjectProperty(\n        modifiersKey,\n        createSimpleExpression(\n          `{ ${modifiers} }`,\n          false,\n          dir.loc,\n          ConstantTypes.CAN_CACHE,\n        ),\n      ),\n    )\n  }\n\n  return createTransformProps(props)\n}\n\nfunction createTransformProps(props: Property[] = []) {\n  return { props }\n}\n"
  },
  {
    "path": "packages/compiler-core/src/transforms/vOn.ts",
    "content": "import type { DirectiveTransform, DirectiveTransformResult } from '../transform'\nimport {\n  type DirectiveNode,\n  ElementTypes,\n  type ExpressionNode,\n  NodeTypes,\n  type SimpleExpressionNode,\n  createCompoundExpression,\n  createObjectProperty,\n  createSimpleExpression,\n} from '../ast'\nimport { camelize, toHandlerKey } from '@vue/shared'\nimport { ErrorCodes, createCompilerError } from '../errors'\nimport { processExpression } from './transformExpression'\nimport { validateBrowserExpression } from '../validateExpression'\nimport { hasScopeRef, isFnExpression, isMemberExpression } from '../utils'\nimport { TO_HANDLER_KEY } from '../runtimeHelpers'\n\nexport interface VOnDirectiveNode extends DirectiveNode {\n  // v-on without arg is handled directly in ./transformElement.ts due to its affecting\n  // codegen for the entire props object. This transform here is only for v-on\n  // *with* args.\n  arg: ExpressionNode\n  // exp is guaranteed to be a simple expression here because v-on w/ arg is\n  // skipped by transformExpression as a special case.\n  exp: SimpleExpressionNode | undefined\n}\n\nexport const transformOn: DirectiveTransform = (\n  dir,\n  node,\n  context,\n  augmentor,\n) => {\n  const { loc, modifiers, arg } = dir as VOnDirectiveNode\n  if (!dir.exp && !modifiers.length) {\n    context.onError(createCompilerError(ErrorCodes.X_V_ON_NO_EXPRESSION, loc))\n  }\n  let eventName: ExpressionNode\n  if (arg.type === NodeTypes.SIMPLE_EXPRESSION) {\n    if (arg.isStatic) {\n      let rawName = arg.content\n      if (__DEV__ && rawName.startsWith('vnode')) {\n        context.onError(createCompilerError(ErrorCodes.X_VNODE_HOOKS, arg.loc))\n      }\n      if (rawName.startsWith('vue:')) {\n        rawName = `vnode-${rawName.slice(4)}`\n      }\n      const eventString =\n        node.tagType !== ElementTypes.ELEMENT ||\n        rawName.startsWith('vnode') ||\n        !/[A-Z]/.test(rawName)\n          ? // for non-element and vnode lifecycle event listeners, auto convert\n            // it to camelCase. See issue #2249\n            toHandlerKey(camelize(rawName))\n          : // preserve case for plain element listeners that have uppercase\n            // letters, as these may be custom elements' custom events\n            `on:${rawName}`\n      eventName = createSimpleExpression(eventString, true, arg.loc)\n    } else {\n      // #2388\n      eventName = createCompoundExpression([\n        `${context.helperString(TO_HANDLER_KEY)}(`,\n        arg,\n        `)`,\n      ])\n    }\n  } else {\n    // already a compound expression.\n    eventName = arg\n    eventName.children.unshift(`${context.helperString(TO_HANDLER_KEY)}(`)\n    eventName.children.push(`)`)\n  }\n\n  // handler processing\n  let exp: ExpressionNode | undefined = dir.exp as\n    | SimpleExpressionNode\n    | undefined\n  if (exp && !exp.content.trim()) {\n    exp = undefined\n  }\n  let shouldCache: boolean = context.cacheHandlers && !exp && !context.inVOnce\n  if (exp) {\n    const isMemberExp = isMemberExpression(exp, context)\n    const isInlineStatement = !(isMemberExp || isFnExpression(exp, context))\n    const hasMultipleStatements = exp.content.includes(`;`)\n\n    // process the expression since it's been skipped\n    if (!__BROWSER__ && context.prefixIdentifiers) {\n      isInlineStatement && context.addIdentifiers(`$event`)\n      exp = dir.exp = processExpression(\n        exp,\n        context,\n        false,\n        hasMultipleStatements,\n      )\n      isInlineStatement && context.removeIdentifiers(`$event`)\n      // with scope analysis, the function is hoistable if it has no reference\n      // to scope variables.\n      shouldCache =\n        context.cacheHandlers &&\n        // unnecessary to cache inside v-once\n        !context.inVOnce &&\n        // runtime constants don't need to be cached\n        // (this is analyzed by compileScript in SFC <script setup>)\n        !(exp.type === NodeTypes.SIMPLE_EXPRESSION && exp.constType > 0) &&\n        // #1541 bail if this is a member exp handler passed to a component -\n        // we need to use the original function to preserve arity,\n        // e.g. <transition> relies on checking cb.length to determine\n        // transition end handling. Inline function is ok since its arity\n        // is preserved even when cached.\n        !(isMemberExp && node.tagType === ElementTypes.COMPONENT) &&\n        // bail if the function references closure variables (v-for, v-slot)\n        // it must be passed fresh to avoid stale values.\n        !hasScopeRef(exp, context.identifiers)\n      // If the expression is optimizable and is a member expression pointing\n      // to a function, turn it into invocation (and wrap in an arrow function\n      // below) so that it always accesses the latest value when called - thus\n      // avoiding the need to be patched.\n      if (shouldCache && isMemberExp) {\n        if (exp.type === NodeTypes.SIMPLE_EXPRESSION) {\n          exp.content = `${exp.content} && ${exp.content}(...args)`\n        } else {\n          exp.children = [...exp.children, ` && `, ...exp.children, `(...args)`]\n        }\n      }\n    }\n\n    if (__DEV__ && __BROWSER__) {\n      validateBrowserExpression(\n        exp as SimpleExpressionNode,\n        context,\n        false,\n        hasMultipleStatements,\n      )\n    }\n\n    if (isInlineStatement || (shouldCache && isMemberExp)) {\n      // wrap inline statement in a function expression\n      exp = createCompoundExpression([\n        `${\n          isInlineStatement\n            ? !__BROWSER__ && context.isTS\n              ? `($event: any)`\n              : `$event`\n            : `${\n                !__BROWSER__ && context.isTS ? `\\n//@ts-ignore\\n` : ``\n              }(...args)`\n        } => ${hasMultipleStatements ? `{` : `(`}`,\n        exp,\n        hasMultipleStatements ? `}` : `)`,\n      ])\n    }\n  }\n\n  let ret: DirectiveTransformResult = {\n    props: [\n      createObjectProperty(\n        eventName,\n        exp || createSimpleExpression(`() => {}`, false, loc),\n      ),\n    ],\n  }\n\n  // apply extended compiler augmentor\n  if (augmentor) {\n    ret = augmentor(ret)\n  }\n\n  if (shouldCache) {\n    // cache handlers so that it's always the same handler being passed down.\n    // this avoids unnecessary re-renders when users use inline handlers on\n    // components.\n    ret.props[0].value = context.cache(ret.props[0].value)\n  }\n\n  // mark the key as handler for props normalization check\n  ret.props.forEach(p => (p.key.isHandlerKey = true))\n  return ret\n}\n"
  },
  {
    "path": "packages/compiler-core/src/transforms/vOnce.ts",
    "content": "import type { NodeTransform } from '../transform'\nimport { findDir } from '../utils'\nimport { type ElementNode, type ForNode, type IfNode, NodeTypes } from '../ast'\nimport { SET_BLOCK_TRACKING } from '../runtimeHelpers'\n\nconst seen = new WeakSet()\n\nexport const transformOnce: NodeTransform = (node, context) => {\n  if (node.type === NodeTypes.ELEMENT && findDir(node, 'once', true)) {\n    if (seen.has(node) || context.inVOnce || context.inSSR) {\n      return\n    }\n    seen.add(node)\n    context.inVOnce = true\n    context.helper(SET_BLOCK_TRACKING)\n    return () => {\n      context.inVOnce = false\n      const cur = context.currentNode as ElementNode | IfNode | ForNode\n      if (cur.codegenNode) {\n        cur.codegenNode = context.cache(\n          cur.codegenNode,\n          true /* isVNode */,\n          true /* inVOnce */,\n        )\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "packages/compiler-core/src/transforms/vSlot.ts",
    "content": "import {\n  type CallExpression,\n  type ConditionalExpression,\n  type DirectiveNode,\n  type ElementNode,\n  ElementTypes,\n  type ExpressionNode,\n  type FunctionExpression,\n  NodeTypes,\n  type ObjectExpression,\n  type Property,\n  type SlotsExpression,\n  type SourceLocation,\n  type TemplateChildNode,\n  createArrayExpression,\n  createCallExpression,\n  createConditionalExpression,\n  createFunctionExpression,\n  createObjectExpression,\n  createObjectProperty,\n  createSimpleExpression,\n} from '../ast'\nimport type { NodeTransform, TransformContext } from '../transform'\nimport { ErrorCodes, createCompilerError } from '../errors'\nimport {\n  assert,\n  findDir,\n  hasScopeRef,\n  isCommentOrWhitespace,\n  isStaticExp,\n  isTemplateNode,\n  isVSlot,\n  isWhitespaceText,\n} from '../utils'\nimport { CREATE_SLOTS, RENDER_LIST, WITH_CTX } from '../runtimeHelpers'\nimport { createForLoopParams, finalizeForParseResult } from './vFor'\nimport { SlotFlags, slotFlagsText } from '@vue/shared'\n\nconst defaultFallback = createSimpleExpression(`undefined`, false)\n\n// A NodeTransform that:\n// 1. Tracks scope identifiers for scoped slots so that they don't get prefixed\n//    by transformExpression. This is only applied in non-browser builds with\n//    { prefixIdentifiers: true }.\n// 2. Track v-slot depths so that we know a slot is inside another slot.\n//    Note the exit callback is executed before buildSlots() on the same node,\n//    so only nested slots see positive numbers.\nexport const trackSlotScopes: NodeTransform = (node, context) => {\n  if (\n    node.type === NodeTypes.ELEMENT &&\n    (node.tagType === ElementTypes.COMPONENT ||\n      node.tagType === ElementTypes.TEMPLATE)\n  ) {\n    // We are only checking non-empty v-slot here\n    // since we only care about slots that introduce scope variables.\n    const vSlot = findDir(node, 'slot')\n    if (vSlot) {\n      const slotProps = vSlot.exp\n      if (!__BROWSER__ && context.prefixIdentifiers) {\n        slotProps && context.addIdentifiers(slotProps)\n      }\n      context.scopes.vSlot++\n      return () => {\n        if (!__BROWSER__ && context.prefixIdentifiers) {\n          slotProps && context.removeIdentifiers(slotProps)\n        }\n        context.scopes.vSlot--\n      }\n    }\n  }\n}\n\n// A NodeTransform that tracks scope identifiers for scoped slots with v-for.\n// This transform is only applied in non-browser builds with { prefixIdentifiers: true }\nexport const trackVForSlotScopes: NodeTransform = (node, context) => {\n  let vFor\n  if (\n    isTemplateNode(node) &&\n    node.props.some(isVSlot) &&\n    (vFor = findDir(node, 'for'))\n  ) {\n    const result = vFor.forParseResult\n    if (result) {\n      finalizeForParseResult(result, context)\n      const { value, key, index } = result\n      const { addIdentifiers, removeIdentifiers } = context\n      value && addIdentifiers(value)\n      key && addIdentifiers(key)\n      index && addIdentifiers(index)\n\n      return () => {\n        value && removeIdentifiers(value)\n        key && removeIdentifiers(key)\n        index && removeIdentifiers(index)\n      }\n    }\n  }\n}\n\nexport type SlotFnBuilder = (\n  slotProps: ExpressionNode | undefined,\n  vFor: DirectiveNode | undefined,\n  slotChildren: TemplateChildNode[],\n  loc: SourceLocation,\n) => FunctionExpression\n\nconst buildClientSlotFn: SlotFnBuilder = (props, _vForExp, children, loc) =>\n  createFunctionExpression(\n    props,\n    children,\n    false /* newline */,\n    true /* isSlot */,\n    children.length ? children[0].loc : loc,\n  )\n\n// Instead of being a DirectiveTransform, v-slot processing is called during\n// transformElement to build the slots object for a component.\nexport function buildSlots(\n  node: ElementNode,\n  context: TransformContext,\n  buildSlotFn: SlotFnBuilder = buildClientSlotFn,\n): {\n  slots: SlotsExpression\n  hasDynamicSlots: boolean\n} {\n  context.helper(WITH_CTX)\n\n  const { children, loc } = node\n  const slotsProperties: Property[] = []\n  const dynamicSlots: (ConditionalExpression | CallExpression)[] = []\n\n  // If the slot is inside a v-for or another v-slot, force it to be dynamic\n  // since it likely uses a scope variable.\n  let hasDynamicSlots = context.scopes.vSlot > 0 || context.scopes.vFor > 0\n  // with `prefixIdentifiers: true`, this can be further optimized to make\n  // it dynamic when\n  // 1. the slot arg or exp uses the scope variables.\n  // 2. the slot children use the scope variables.\n  if (!__BROWSER__ && !context.ssr && context.prefixIdentifiers) {\n    hasDynamicSlots =\n      node.props.some(\n        prop =>\n          isVSlot(prop) &&\n          (hasScopeRef(prop.arg, context.identifiers) ||\n            hasScopeRef(prop.exp, context.identifiers)),\n      ) || children.some(child => hasScopeRef(child, context.identifiers))\n  }\n\n  // 1. Check for slot with slotProps on component itself.\n  //    <Comp v-slot=\"{ prop }\"/>\n  const onComponentSlot = findDir(node, 'slot', true)\n  if (onComponentSlot) {\n    const { arg, exp } = onComponentSlot\n    if (arg && !isStaticExp(arg)) {\n      hasDynamicSlots = true\n    }\n    slotsProperties.push(\n      createObjectProperty(\n        arg || createSimpleExpression('default', true),\n        buildSlotFn(exp, undefined, children, loc),\n      ),\n    )\n  }\n\n  // 2. Iterate through children and check for template slots\n  //    <template v-slot:foo=\"{ prop }\">\n  let hasTemplateSlots = false\n  let hasNamedDefaultSlot = false\n  const implicitDefaultChildren: TemplateChildNode[] = []\n  const seenSlotNames = new Set<string>()\n  let conditionalBranchIndex = 0\n\n  for (let i = 0; i < children.length; i++) {\n    const slotElement = children[i]\n    let slotDir\n\n    if (\n      !isTemplateNode(slotElement) ||\n      !(slotDir = findDir(slotElement, 'slot', true))\n    ) {\n      // not a <template v-slot>, skip.\n      if (slotElement.type !== NodeTypes.COMMENT) {\n        implicitDefaultChildren.push(slotElement)\n      }\n      continue\n    }\n\n    if (onComponentSlot) {\n      // already has on-component slot - this is incorrect usage.\n      context.onError(\n        createCompilerError(ErrorCodes.X_V_SLOT_MIXED_SLOT_USAGE, slotDir.loc),\n      )\n      break\n    }\n\n    hasTemplateSlots = true\n    const { children: slotChildren, loc: slotLoc } = slotElement\n    const {\n      arg: slotName = createSimpleExpression(`default`, true),\n      exp: slotProps,\n      loc: dirLoc,\n    } = slotDir\n\n    // check if name is dynamic.\n    let staticSlotName: string | undefined\n    if (isStaticExp(slotName)) {\n      staticSlotName = slotName ? slotName.content : `default`\n    } else {\n      hasDynamicSlots = true\n    }\n\n    const vFor = findDir(slotElement, 'for')\n    const slotFunction = buildSlotFn(slotProps, vFor, slotChildren, slotLoc)\n\n    // check if this slot is conditional (v-if/v-for)\n    let vIf: DirectiveNode | undefined\n    let vElse: DirectiveNode | undefined\n    if ((vIf = findDir(slotElement, 'if'))) {\n      hasDynamicSlots = true\n      dynamicSlots.push(\n        createConditionalExpression(\n          vIf.exp!,\n          buildDynamicSlot(slotName, slotFunction, conditionalBranchIndex++),\n          defaultFallback,\n        ),\n      )\n    } else if (\n      (vElse = findDir(slotElement, /^else(?:-if)?$/, true /* allowEmpty */))\n    ) {\n      // find adjacent v-if\n      let j = i\n      let prev\n      while (j--) {\n        prev = children[j]\n        if (!isCommentOrWhitespace(prev)) {\n          break\n        }\n      }\n      if (prev && isTemplateNode(prev) && findDir(prev, /^(?:else-)?if$/)) {\n        __TEST__ && assert(dynamicSlots.length > 0)\n        // attach this slot to previous conditional\n        let conditional = dynamicSlots[\n          dynamicSlots.length - 1\n        ] as ConditionalExpression\n        while (\n          conditional.alternate.type === NodeTypes.JS_CONDITIONAL_EXPRESSION\n        ) {\n          conditional = conditional.alternate\n        }\n        conditional.alternate = vElse.exp\n          ? createConditionalExpression(\n              vElse.exp,\n              buildDynamicSlot(\n                slotName,\n                slotFunction,\n                conditionalBranchIndex++,\n              ),\n              defaultFallback,\n            )\n          : buildDynamicSlot(slotName, slotFunction, conditionalBranchIndex++)\n      } else {\n        context.onError(\n          createCompilerError(ErrorCodes.X_V_ELSE_NO_ADJACENT_IF, vElse.loc),\n        )\n      }\n    } else if (vFor) {\n      hasDynamicSlots = true\n      const parseResult = vFor.forParseResult\n      if (parseResult) {\n        finalizeForParseResult(parseResult, context)\n        // Render the dynamic slots as an array and add it to the createSlot()\n        // args. The runtime knows how to handle it appropriately.\n        dynamicSlots.push(\n          createCallExpression(context.helper(RENDER_LIST), [\n            parseResult.source,\n            createFunctionExpression(\n              createForLoopParams(parseResult),\n              buildDynamicSlot(slotName, slotFunction),\n              true /* force newline */,\n            ),\n          ]),\n        )\n      } else {\n        context.onError(\n          createCompilerError(\n            ErrorCodes.X_V_FOR_MALFORMED_EXPRESSION,\n            vFor.loc,\n          ),\n        )\n      }\n    } else {\n      // check duplicate static names\n      if (staticSlotName) {\n        if (seenSlotNames.has(staticSlotName)) {\n          context.onError(\n            createCompilerError(\n              ErrorCodes.X_V_SLOT_DUPLICATE_SLOT_NAMES,\n              dirLoc,\n            ),\n          )\n          continue\n        }\n        seenSlotNames.add(staticSlotName)\n        if (staticSlotName === 'default') {\n          hasNamedDefaultSlot = true\n        }\n      }\n      slotsProperties.push(createObjectProperty(slotName, slotFunction))\n    }\n  }\n\n  if (!onComponentSlot) {\n    const buildDefaultSlotProperty = (\n      props: ExpressionNode | undefined,\n      children: TemplateChildNode[],\n    ) => {\n      const fn = buildSlotFn(props, undefined, children, loc)\n      if (__COMPAT__ && context.compatConfig) {\n        fn.isNonScopedSlot = true\n      }\n      return createObjectProperty(`default`, fn)\n    }\n\n    if (!hasTemplateSlots) {\n      // implicit default slot (on component)\n      slotsProperties.push(buildDefaultSlotProperty(undefined, children))\n    } else if (\n      implicitDefaultChildren.length &&\n      // #3766\n      // with whitespace: 'preserve', whitespaces between slots will end up in\n      // implicitDefaultChildren. Ignore if all implicit children are whitespaces.\n      !implicitDefaultChildren.every(isWhitespaceText)\n    ) {\n      // implicit default slot (mixed with named slots)\n      if (hasNamedDefaultSlot) {\n        context.onError(\n          createCompilerError(\n            ErrorCodes.X_V_SLOT_EXTRANEOUS_DEFAULT_SLOT_CHILDREN,\n            implicitDefaultChildren[0].loc,\n          ),\n        )\n      } else {\n        slotsProperties.push(\n          buildDefaultSlotProperty(undefined, implicitDefaultChildren),\n        )\n      }\n    }\n  }\n\n  const slotFlag = hasDynamicSlots\n    ? SlotFlags.DYNAMIC\n    : hasForwardedSlots(node.children)\n      ? SlotFlags.FORWARDED\n      : SlotFlags.STABLE\n  let slots = createObjectExpression(\n    slotsProperties.concat(\n      createObjectProperty(\n        `_`,\n        // 2 = compiled but dynamic = can skip normalization, but must run diff\n        // 1 = compiled and static = can skip normalization AND diff as optimized\n        createSimpleExpression(\n          slotFlag + (__DEV__ ? ` /* ${slotFlagsText[slotFlag]} */` : ``),\n          false,\n        ),\n      ),\n    ),\n    loc,\n  ) as SlotsExpression\n  if (dynamicSlots.length) {\n    slots = createCallExpression(context.helper(CREATE_SLOTS), [\n      slots,\n      createArrayExpression(dynamicSlots),\n    ]) as SlotsExpression\n  }\n\n  return {\n    slots,\n    hasDynamicSlots,\n  }\n}\n\nfunction buildDynamicSlot(\n  name: ExpressionNode,\n  fn: FunctionExpression,\n  index?: number,\n): ObjectExpression {\n  const props = [\n    createObjectProperty(`name`, name),\n    createObjectProperty(`fn`, fn),\n  ]\n  if (index != null) {\n    props.push(\n      createObjectProperty(`key`, createSimpleExpression(String(index), true)),\n    )\n  }\n  return createObjectExpression(props)\n}\n\nfunction hasForwardedSlots(children: TemplateChildNode[]): boolean {\n  for (let i = 0; i < children.length; i++) {\n    const child = children[i]\n    switch (child.type) {\n      case NodeTypes.ELEMENT:\n        if (\n          child.tagType === ElementTypes.SLOT ||\n          hasForwardedSlots(child.children)\n        ) {\n          return true\n        }\n        break\n      case NodeTypes.IF:\n        if (hasForwardedSlots(child.branches)) return true\n        break\n      case NodeTypes.IF_BRANCH:\n      case NodeTypes.FOR:\n        if (hasForwardedSlots(child.children)) return true\n        break\n      default:\n        break\n    }\n  }\n  return false\n}\n"
  },
  {
    "path": "packages/compiler-core/src/utils.ts",
    "content": "import {\n  type BlockCodegenNode,\n  type CacheExpression,\n  type CallExpression,\n  type DirectiveNode,\n  type ElementNode,\n  ElementTypes,\n  type ExpressionNode,\n  type IfBranchNode,\n  type InterpolationNode,\n  type JSChildNode,\n  type MemoExpression,\n  NodeTypes,\n  type ObjectExpression,\n  type Position,\n  type Property,\n  type RenderSlotCall,\n  type RootNode,\n  type SimpleExpressionNode,\n  type SlotOutletNode,\n  type TemplateChildNode,\n  type TemplateNode,\n  type TextNode,\n  type VNodeCall,\n  createCallExpression,\n  createObjectExpression,\n} from './ast'\nimport type { TransformContext } from './transform'\nimport {\n  BASE_TRANSITION,\n  GUARD_REACTIVE_PROPS,\n  KEEP_ALIVE,\n  MERGE_PROPS,\n  NORMALIZE_PROPS,\n  SUSPENSE,\n  TELEPORT,\n  TO_HANDLERS,\n  WITH_MEMO,\n} from './runtimeHelpers'\nimport { NOOP, isObject, isString } from '@vue/shared'\nimport type { PropsExpression } from './transforms/transformElement'\nimport { parseExpression } from '@babel/parser'\nimport type { Expression, Node } from '@babel/types'\nimport { unwrapTSNode } from './babelUtils'\nimport { isWhitespace } from './tokenizer'\n\nexport const isStaticExp = (p: JSChildNode): p is SimpleExpressionNode =>\n  p.type === NodeTypes.SIMPLE_EXPRESSION && p.isStatic\n\nexport function isCoreComponent(tag: string): symbol | void {\n  switch (tag) {\n    case 'Teleport':\n    case 'teleport':\n      return TELEPORT\n    case 'Suspense':\n    case 'suspense':\n      return SUSPENSE\n    case 'KeepAlive':\n    case 'keep-alive':\n      return KEEP_ALIVE\n    case 'BaseTransition':\n    case 'base-transition':\n      return BASE_TRANSITION\n  }\n}\n\nconst nonIdentifierRE = /^$|^\\d|[^\\$\\w\\xA0-\\uFFFF]/\nexport const isSimpleIdentifier = (name: string): boolean =>\n  !nonIdentifierRE.test(name)\n\nenum MemberExpLexState {\n  inMemberExp,\n  inBrackets,\n  inParens,\n  inString,\n}\n\nexport const validFirstIdentCharRE: RegExp = /[A-Za-z_$\\xA0-\\uFFFF]/\nconst validIdentCharRE = /[\\.\\?\\w$\\xA0-\\uFFFF]/\nconst whitespaceRE = /\\s+[.[]\\s*|\\s*[.[]\\s+/g\n\nconst getExpSource = (exp: ExpressionNode): string =>\n  exp.type === NodeTypes.SIMPLE_EXPRESSION ? exp.content : exp.loc.source\n\n/**\n * Simple lexer to check if an expression is a member expression. This is\n * lax and only checks validity at the root level (i.e. does not validate exps\n * inside square brackets), but it's ok since these are only used on template\n * expressions and false positives are invalid expressions in the first place.\n */\nexport const isMemberExpressionBrowser = (exp: ExpressionNode): boolean => {\n  // remove whitespaces around . or [ first\n  const path = getExpSource(exp)\n    .trim()\n    .replace(whitespaceRE, s => s.trim())\n\n  let state = MemberExpLexState.inMemberExp\n  let stateStack: MemberExpLexState[] = []\n  let currentOpenBracketCount = 0\n  let currentOpenParensCount = 0\n  let currentStringType: \"'\" | '\"' | '`' | null = null\n\n  for (let i = 0; i < path.length; i++) {\n    const char = path.charAt(i)\n    switch (state) {\n      case MemberExpLexState.inMemberExp:\n        if (char === '[') {\n          stateStack.push(state)\n          state = MemberExpLexState.inBrackets\n          currentOpenBracketCount++\n        } else if (char === '(') {\n          stateStack.push(state)\n          state = MemberExpLexState.inParens\n          currentOpenParensCount++\n        } else if (\n          !(i === 0 ? validFirstIdentCharRE : validIdentCharRE).test(char)\n        ) {\n          return false\n        }\n        break\n      case MemberExpLexState.inBrackets:\n        if (char === `'` || char === `\"` || char === '`') {\n          stateStack.push(state)\n          state = MemberExpLexState.inString\n          currentStringType = char\n        } else if (char === `[`) {\n          currentOpenBracketCount++\n        } else if (char === `]`) {\n          if (!--currentOpenBracketCount) {\n            state = stateStack.pop()!\n          }\n        }\n        break\n      case MemberExpLexState.inParens:\n        if (char === `'` || char === `\"` || char === '`') {\n          stateStack.push(state)\n          state = MemberExpLexState.inString\n          currentStringType = char\n        } else if (char === `(`) {\n          currentOpenParensCount++\n        } else if (char === `)`) {\n          // if the exp ends as a call then it should not be considered valid\n          if (i === path.length - 1) {\n            return false\n          }\n          if (!--currentOpenParensCount) {\n            state = stateStack.pop()!\n          }\n        }\n        break\n      case MemberExpLexState.inString:\n        if (char === currentStringType) {\n          state = stateStack.pop()!\n          currentStringType = null\n        }\n        break\n    }\n  }\n  return !currentOpenBracketCount && !currentOpenParensCount\n}\n\nexport const isMemberExpressionNode: (\n  exp: ExpressionNode,\n  context: TransformContext,\n) => boolean = __BROWSER__\n  ? (NOOP as any)\n  : (exp, context) => {\n      try {\n        let ret: Node =\n          exp.ast ||\n          parseExpression(getExpSource(exp), {\n            plugins: context.expressionPlugins\n              ? [...context.expressionPlugins, 'typescript']\n              : ['typescript'],\n          })\n        ret = unwrapTSNode(ret) as Expression\n        return (\n          ret.type === 'MemberExpression' ||\n          ret.type === 'OptionalMemberExpression' ||\n          (ret.type === 'Identifier' && ret.name !== 'undefined')\n        )\n      } catch (e) {\n        return false\n      }\n    }\n\nexport const isMemberExpression: (\n  exp: ExpressionNode,\n  context: TransformContext,\n) => boolean = __BROWSER__ ? isMemberExpressionBrowser : isMemberExpressionNode\n\nconst fnExpRE =\n  /^\\s*(?:async\\s*)?(?:\\([^)]*?\\)|[\\w$_]+)\\s*(?::[^=]+)?=>|^\\s*(?:async\\s+)?function(?:\\s+[\\w$]+)?\\s*\\(/\n\nexport const isFnExpressionBrowser: (exp: ExpressionNode) => boolean = exp =>\n  fnExpRE.test(getExpSource(exp))\n\nexport const isFnExpressionNode: (\n  exp: ExpressionNode,\n  context: TransformContext,\n) => boolean = __BROWSER__\n  ? (NOOP as any)\n  : (exp, context) => {\n      try {\n        let ret: Node =\n          exp.ast ||\n          parseExpression(getExpSource(exp), {\n            plugins: context.expressionPlugins\n              ? [...context.expressionPlugins, 'typescript']\n              : ['typescript'],\n          })\n        // parser may parse the exp as statements when it contains semicolons\n        if (ret.type === 'Program') {\n          ret = ret.body[0]\n          if (ret.type === 'ExpressionStatement') {\n            ret = ret.expression\n          }\n        }\n        ret = unwrapTSNode(ret) as Expression\n        return (\n          ret.type === 'FunctionExpression' ||\n          ret.type === 'ArrowFunctionExpression'\n        )\n      } catch (e) {\n        return false\n      }\n    }\n\nexport const isFnExpression: (\n  exp: ExpressionNode,\n  context: TransformContext,\n) => boolean = __BROWSER__ ? isFnExpressionBrowser : isFnExpressionNode\n\nexport function advancePositionWithClone(\n  pos: Position,\n  source: string,\n  numberOfCharacters: number = source.length,\n): Position {\n  return advancePositionWithMutation(\n    {\n      offset: pos.offset,\n      line: pos.line,\n      column: pos.column,\n    },\n    source,\n    numberOfCharacters,\n  )\n}\n\n// advance by mutation without cloning (for performance reasons), since this\n// gets called a lot in the parser\nexport function advancePositionWithMutation(\n  pos: Position,\n  source: string,\n  numberOfCharacters: number = source.length,\n): Position {\n  let linesCount = 0\n  let lastNewLinePos = -1\n  for (let i = 0; i < numberOfCharacters; i++) {\n    if (source.charCodeAt(i) === 10 /* newline char code */) {\n      linesCount++\n      lastNewLinePos = i\n    }\n  }\n\n  pos.offset += numberOfCharacters\n  pos.line += linesCount\n  pos.column =\n    lastNewLinePos === -1\n      ? pos.column + numberOfCharacters\n      : numberOfCharacters - lastNewLinePos\n\n  return pos\n}\n\nexport function assert(condition: boolean, msg?: string): void {\n  /* v8 ignore next 3 */\n  if (!condition) {\n    throw new Error(msg || `unexpected compiler condition`)\n  }\n}\n\nexport function findDir(\n  node: ElementNode,\n  name: string | RegExp,\n  allowEmpty: boolean = false,\n): DirectiveNode | undefined {\n  for (let i = 0; i < node.props.length; i++) {\n    const p = node.props[i]\n    if (\n      p.type === NodeTypes.DIRECTIVE &&\n      (allowEmpty || p.exp) &&\n      (isString(name) ? p.name === name : name.test(p.name))\n    ) {\n      return p\n    }\n  }\n}\n\nexport function findProp(\n  node: ElementNode,\n  name: string,\n  dynamicOnly: boolean = false,\n  allowEmpty: boolean = false,\n): ElementNode['props'][0] | undefined {\n  for (let i = 0; i < node.props.length; i++) {\n    const p = node.props[i]\n    if (p.type === NodeTypes.ATTRIBUTE) {\n      if (dynamicOnly) continue\n      if (p.name === name && (p.value || allowEmpty)) {\n        return p\n      }\n    } else if (\n      p.name === 'bind' &&\n      (p.exp || allowEmpty) &&\n      isStaticArgOf(p.arg, name)\n    ) {\n      return p\n    }\n  }\n}\n\nexport function isStaticArgOf(\n  arg: DirectiveNode['arg'],\n  name: string,\n): boolean {\n  return !!(arg && isStaticExp(arg) && arg.content === name)\n}\n\nexport function hasDynamicKeyVBind(node: ElementNode): boolean {\n  return node.props.some(\n    p =>\n      p.type === NodeTypes.DIRECTIVE &&\n      p.name === 'bind' &&\n      (!p.arg || // v-bind=\"obj\"\n        p.arg.type !== NodeTypes.SIMPLE_EXPRESSION || // v-bind:[_ctx.foo]\n        !p.arg.isStatic), // v-bind:[foo]\n  )\n}\n\nexport function isText(\n  node: TemplateChildNode,\n): node is TextNode | InterpolationNode {\n  return node.type === NodeTypes.INTERPOLATION || node.type === NodeTypes.TEXT\n}\n\nexport function isVPre(p: ElementNode['props'][0]): p is DirectiveNode {\n  return p.type === NodeTypes.DIRECTIVE && p.name === 'pre'\n}\n\nexport function isVSlot(p: ElementNode['props'][0]): p is DirectiveNode {\n  return p.type === NodeTypes.DIRECTIVE && p.name === 'slot'\n}\n\nexport function isTemplateNode(\n  node: RootNode | TemplateChildNode,\n): node is TemplateNode {\n  return (\n    node.type === NodeTypes.ELEMENT && node.tagType === ElementTypes.TEMPLATE\n  )\n}\n\nexport function isSlotOutlet(\n  node: RootNode | TemplateChildNode,\n): node is SlotOutletNode {\n  return node.type === NodeTypes.ELEMENT && node.tagType === ElementTypes.SLOT\n}\n\nconst propsHelperSet = new Set([NORMALIZE_PROPS, GUARD_REACTIVE_PROPS])\n\nfunction getUnnormalizedProps(\n  props: PropsExpression | '{}',\n  callPath: CallExpression[] = [],\n): [PropsExpression | '{}', CallExpression[]] {\n  if (\n    props &&\n    !isString(props) &&\n    props.type === NodeTypes.JS_CALL_EXPRESSION\n  ) {\n    const callee = props.callee\n    if (!isString(callee) && propsHelperSet.has(callee)) {\n      return getUnnormalizedProps(\n        props.arguments[0] as PropsExpression,\n        callPath.concat(props),\n      )\n    }\n  }\n  return [props, callPath]\n}\nexport function injectProp(\n  node: VNodeCall | RenderSlotCall,\n  prop: Property,\n  context: TransformContext,\n): void {\n  let propsWithInjection: ObjectExpression | CallExpression | undefined\n  /**\n   * 1. mergeProps(...)\n   * 2. toHandlers(...)\n   * 3. normalizeProps(...)\n   * 4. normalizeProps(guardReactiveProps(...))\n   *\n   * we need to get the real props before normalization\n   */\n  let props =\n    node.type === NodeTypes.VNODE_CALL ? node.props : node.arguments[2]\n  let callPath: CallExpression[] = []\n  let parentCall: CallExpression | undefined\n  if (\n    props &&\n    !isString(props) &&\n    props.type === NodeTypes.JS_CALL_EXPRESSION\n  ) {\n    const ret = getUnnormalizedProps(props)\n    props = ret[0]\n    callPath = ret[1]\n    parentCall = callPath[callPath.length - 1]\n  }\n\n  if (props == null || isString(props)) {\n    propsWithInjection = createObjectExpression([prop])\n  } else if (props.type === NodeTypes.JS_CALL_EXPRESSION) {\n    // merged props... add ours\n    // only inject key to object literal if it's the first argument so that\n    // if doesn't override user provided keys\n    const first = props.arguments[0] as string | JSChildNode\n    if (!isString(first) && first.type === NodeTypes.JS_OBJECT_EXPRESSION) {\n      // #6631\n      if (!hasProp(prop, first)) {\n        first.properties.unshift(prop)\n      }\n    } else {\n      if (props.callee === TO_HANDLERS) {\n        // #2366\n        propsWithInjection = createCallExpression(context.helper(MERGE_PROPS), [\n          createObjectExpression([prop]),\n          props,\n        ])\n      } else {\n        props.arguments.unshift(createObjectExpression([prop]))\n      }\n    }\n    !propsWithInjection && (propsWithInjection = props)\n  } else if (props.type === NodeTypes.JS_OBJECT_EXPRESSION) {\n    if (!hasProp(prop, props)) {\n      props.properties.unshift(prop)\n    }\n    propsWithInjection = props\n  } else {\n    // single v-bind with expression, return a merged replacement\n    propsWithInjection = createCallExpression(context.helper(MERGE_PROPS), [\n      createObjectExpression([prop]),\n      props,\n    ])\n    // in the case of nested helper call, e.g. `normalizeProps(guardReactiveProps(props))`,\n    // it will be rewritten as `normalizeProps(mergeProps({ key: 0 }, props))`,\n    // the `guardReactiveProps` will no longer be needed\n    if (parentCall && parentCall.callee === GUARD_REACTIVE_PROPS) {\n      parentCall = callPath[callPath.length - 2]\n    }\n  }\n  if (node.type === NodeTypes.VNODE_CALL) {\n    if (parentCall) {\n      parentCall.arguments[0] = propsWithInjection\n    } else {\n      node.props = propsWithInjection\n    }\n  } else {\n    if (parentCall) {\n      parentCall.arguments[0] = propsWithInjection\n    } else {\n      node.arguments[2] = propsWithInjection\n    }\n  }\n}\n\n// check existing key to avoid overriding user provided keys\nfunction hasProp(prop: Property, props: ObjectExpression) {\n  let result = false\n  if (prop.key.type === NodeTypes.SIMPLE_EXPRESSION) {\n    const propKeyName = prop.key.content\n    result = props.properties.some(\n      p =>\n        p.key.type === NodeTypes.SIMPLE_EXPRESSION &&\n        p.key.content === propKeyName,\n    )\n  }\n  return result\n}\n\nexport function toValidAssetId(\n  name: string,\n  type: 'component' | 'directive' | 'filter',\n): string {\n  // see issue#4422, we need adding identifier on validAssetId if variable `name` has specific character\n  return `_${type}_${name.replace(/[^\\w]/g, (searchValue, replaceValue) => {\n    return searchValue === '-' ? '_' : name.charCodeAt(replaceValue).toString()\n  })}`\n}\n\n// Check if a node contains expressions that reference current context scope ids\nexport function hasScopeRef(\n  node:\n    | TemplateChildNode\n    | IfBranchNode\n    | ExpressionNode\n    | CacheExpression\n    | undefined,\n  ids: TransformContext['identifiers'],\n): boolean {\n  if (!node || Object.keys(ids).length === 0) {\n    return false\n  }\n  switch (node.type) {\n    case NodeTypes.ELEMENT:\n      for (let i = 0; i < node.props.length; i++) {\n        const p = node.props[i]\n        if (\n          p.type === NodeTypes.DIRECTIVE &&\n          (hasScopeRef(p.arg, ids) || hasScopeRef(p.exp, ids))\n        ) {\n          return true\n        }\n      }\n      return node.children.some(c => hasScopeRef(c, ids))\n    case NodeTypes.FOR:\n      if (hasScopeRef(node.source, ids)) {\n        return true\n      }\n      return node.children.some(c => hasScopeRef(c, ids))\n    case NodeTypes.IF:\n      return node.branches.some(b => hasScopeRef(b, ids))\n    case NodeTypes.IF_BRANCH:\n      if (hasScopeRef(node.condition, ids)) {\n        return true\n      }\n      return node.children.some(c => hasScopeRef(c, ids))\n    case NodeTypes.SIMPLE_EXPRESSION:\n      return (\n        !node.isStatic &&\n        isSimpleIdentifier(node.content) &&\n        !!ids[node.content]\n      )\n    case NodeTypes.COMPOUND_EXPRESSION:\n      return node.children.some(c => isObject(c) && hasScopeRef(c, ids))\n    case NodeTypes.INTERPOLATION:\n    case NodeTypes.TEXT_CALL:\n      return hasScopeRef(node.content, ids)\n    case NodeTypes.TEXT:\n    case NodeTypes.COMMENT:\n    case NodeTypes.JS_CACHE_EXPRESSION:\n      return false\n    default:\n      if (__DEV__) {\n        const exhaustiveCheck: never = node\n        exhaustiveCheck\n      }\n      return false\n  }\n}\n\nexport function getMemoedVNodeCall(\n  node: BlockCodegenNode | MemoExpression,\n): VNodeCall | RenderSlotCall {\n  if (node.type === NodeTypes.JS_CALL_EXPRESSION && node.callee === WITH_MEMO) {\n    return node.arguments[1].returns as VNodeCall\n  } else {\n    return node\n  }\n}\n\nexport const forAliasRE: RegExp = /([\\s\\S]*?)\\s+(?:in|of)\\s+(\\S[\\s\\S]*)/\n\nexport function isAllWhitespace(str: string): boolean {\n  for (let i = 0; i < str.length; i++) {\n    if (!isWhitespace(str.charCodeAt(i))) {\n      return false\n    }\n  }\n  return true\n}\n\nexport function isWhitespaceText(node: TemplateChildNode): boolean {\n  return (\n    (node.type === NodeTypes.TEXT && isAllWhitespace(node.content)) ||\n    (node.type === NodeTypes.TEXT_CALL && isWhitespaceText(node.content))\n  )\n}\n\nexport function isCommentOrWhitespace(node: TemplateChildNode): boolean {\n  return node.type === NodeTypes.COMMENT || isWhitespaceText(node)\n}\n"
  },
  {
    "path": "packages/compiler-core/src/validateExpression.ts",
    "content": "import type { SimpleExpressionNode } from './ast'\nimport type { TransformContext } from './transform'\nimport { ErrorCodes, createCompilerError } from './errors'\n\n// these keywords should not appear inside expressions, but operators like\n// 'typeof', 'instanceof', and 'in' are allowed\nconst prohibitedKeywordRE = new RegExp(\n  '\\\\b' +\n    (\n      'arguments,await,break,case,catch,class,const,continue,debugger,default,' +\n      'delete,do,else,export,extends,finally,for,function,if,import,let,new,' +\n      'return,super,switch,throw,try,var,void,while,with,yield'\n    )\n      .split(',')\n      .join('\\\\b|\\\\b') +\n    '\\\\b',\n)\n\n// strip strings in expressions\nconst stripStringRE =\n  /'(?:[^'\\\\]|\\\\.)*'|\"(?:[^\"\\\\]|\\\\.)*\"|`(?:[^`\\\\]|\\\\.)*\\$\\{|\\}(?:[^`\\\\]|\\\\.)*`|`(?:[^`\\\\]|\\\\.)*`/g\n\n/**\n * Validate a non-prefixed expression.\n * This is only called when using the in-browser runtime compiler since it\n * doesn't prefix expressions.\n */\nexport function validateBrowserExpression(\n  node: SimpleExpressionNode,\n  context: TransformContext,\n  asParams = false,\n  asRawStatements = false,\n): void {\n  const exp = node.content\n\n  // empty expressions are validated per-directive since some directives\n  // do allow empty expressions.\n  if (!exp.trim()) {\n    return\n  }\n\n  try {\n    new Function(\n      asRawStatements\n        ? ` ${exp} `\n        : `return ${asParams ? `(${exp}) => {}` : `(${exp})`}`,\n    )\n  } catch (e: any) {\n    let message = e.message\n    const keywordMatch = exp\n      .replace(stripStringRE, '')\n      .match(prohibitedKeywordRE)\n    if (keywordMatch) {\n      message = `avoid using JavaScript keyword as property name: \"${keywordMatch[0]}\"`\n    }\n    context.onError(\n      createCompilerError(\n        ErrorCodes.X_INVALID_EXPRESSION,\n        node.loc,\n        undefined,\n        message,\n      ),\n    )\n  }\n}\n"
  },
  {
    "path": "packages/compiler-dom/LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2018-present, Yuxi (Evan) You\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "packages/compiler-dom/README.md",
    "content": "# @vue/compiler-dom\n"
  },
  {
    "path": "packages/compiler-dom/__tests__/__snapshots__/index.spec.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`compile > should contain standard transforms 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { toDisplayString: _toDisplayString, createElementVNode: _createElementVNode, normalizeStyle: _normalizeStyle, Fragment: _Fragment, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue\n\n    return (_openBlock(), _createElementBlock(_Fragment, null, [\n      _createElementVNode(\"div\", {\n        textContent: _toDisplayString(text)\n      }, null, 8 /* PROPS */, [\"textContent\"]),\n      _createElementVNode(\"div\", { innerHTML: html }, null, 8 /* PROPS */, [\"innerHTML\"]),\n      _createElementVNode(\"div\", null, \"test\"),\n      _createElementVNode(\"div\", { style: {\"color\":\"red\"} }, \"red\"),\n      _createElementVNode(\"div\", {\n        style: _normalizeStyle({color: 'green'})\n      }, null, 4 /* STYLE */)\n    ], 64 /* STABLE_FRAGMENT */))\n  }\n}\"\n`;\n"
  },
  {
    "path": "packages/compiler-dom/__tests__/decoderHtmlBrowser.spec.ts",
    "content": "/**\n * @vitest-environment jsdom\n */\nimport { decodeHtmlBrowser } from '../src/decodeHtmlBrowser'\n\ndescribe('decodeHtmlBrowser', () => {\n  it('should decode HTML correctly', () => {\n    expect(decodeHtmlBrowser(' abc  123 ')).toBe(' abc  123 ')\n\n    expect(decodeHtmlBrowser('&')).toBe('&')\n    expect(decodeHtmlBrowser('&amp;')).toBe('&')\n    expect(decodeHtmlBrowser('&amp;amp;')).toBe('&amp;')\n\n    expect(decodeHtmlBrowser('<')).toBe('<')\n    expect(decodeHtmlBrowser('&lt;')).toBe('<')\n    expect(decodeHtmlBrowser('&amp;lt;')).toBe('&lt;')\n\n    expect(decodeHtmlBrowser('>')).toBe('>')\n    expect(decodeHtmlBrowser('&gt;')).toBe('>')\n    expect(decodeHtmlBrowser('&amp;gt;')).toBe('&gt;')\n\n    expect(decodeHtmlBrowser('&nbsp;')).toBe('\\u00a0')\n    expect(decodeHtmlBrowser('&quot;')).toBe('\"')\n    expect(decodeHtmlBrowser('&apos;')).toBe(\"'\")\n\n    expect(decodeHtmlBrowser('&Eacute;')).toBe('\\u00c9')\n    expect(decodeHtmlBrowser('&#xc9;')).toBe('\\u00c9')\n    expect(decodeHtmlBrowser('&#201;')).toBe('\\u00c9')\n\n    // #3001 html tags inside attribute values\n    expect(decodeHtmlBrowser('<strong>Text</strong>', true)).toBe(\n      '<strong>Text</strong>',\n    )\n    expect(decodeHtmlBrowser('<strong>&amp;</strong>', true)).toBe(\n      '<strong>&</strong>',\n    )\n    expect(\n      decodeHtmlBrowser(\n        '<strong>&lt;strong&gt;&amp;&lt;/strong&gt;</strong>',\n        true,\n      ),\n    ).toBe('<strong><strong>&</strong></strong>')\n    expect(decodeHtmlBrowser('\"', true)).toBe('\"')\n    expect(decodeHtmlBrowser(\"'\", true)).toBe(\"'\")\n  })\n})\n"
  },
  {
    "path": "packages/compiler-dom/__tests__/index.spec.ts",
    "content": "import { compile } from '../src'\n\ndescribe('compile', () => {\n  it('should contain standard transforms', () => {\n    const { code } = compile(`<div v-text=\"text\"></div>\n        <div v-html=\"html\"></div>\n        <div v-cloak>test</div>\n        <div style=\"color:red\">red</div>\n        <div :style=\"{color: 'green'}\"></div>`)\n\n    expect(code).toMatchSnapshot()\n  })\n})\n"
  },
  {
    "path": "packages/compiler-dom/__tests__/parse.spec.ts",
    "content": "import {\n  type AttributeNode,\n  ConstantTypes,\n  type ElementNode,\n  ElementTypes,\n  type InterpolationNode,\n  Namespaces,\n  NodeTypes,\n  type TextNode,\n  baseParse as parse,\n} from '@vue/compiler-core'\nimport { parserOptions } from '../src/parserOptions'\n\ndescribe('DOM parser', () => {\n  describe('Text', () => {\n    test('textarea handles comments/elements as just text', () => {\n      const ast = parse(\n        '<textarea>some<div>text</div>and<!--comment--></textarea>',\n        parserOptions,\n      )\n      const element = ast.children[0] as ElementNode\n      const text = element.children[0] as TextNode\n      expect(element.children.length).toBe(1)\n      expect(text).toStrictEqual({\n        type: NodeTypes.TEXT,\n        content: 'some<div>text</div>and<!--comment-->',\n        loc: {\n          start: { offset: 10, line: 1, column: 11 },\n          end: { offset: 46, line: 1, column: 47 },\n          source: 'some<div>text</div>and<!--comment-->',\n        },\n      })\n    })\n\n    test('<textarea> should remove leading newline', () => {\n      const ast = parse('<textarea>\\nhello</textarea>', parserOptions)\n      const element = ast.children[0] as ElementNode\n      const text = element.children[0] as TextNode\n      expect(element.children.length).toBe(1)\n      expect(text).toStrictEqual({\n        type: NodeTypes.TEXT,\n        content: 'hello',\n        loc: {\n          start: { offset: 10, line: 1, column: 11 },\n          end: { offset: 16, line: 2, column: 6 },\n          source: '\\nhello',\n        },\n      })\n    })\n\n    test('should not treat Uppercase component as special tag', () => {\n      const ast = parse(\n        '<TextArea>some<div>text</div>and<!--comment--></TextArea>',\n        parserOptions,\n      )\n      const element = ast.children[0] as ElementNode\n      expect(element.children.map(n => n.type)).toMatchObject([\n        NodeTypes.TEXT,\n        NodeTypes.ELEMENT,\n        NodeTypes.TEXT,\n        NodeTypes.COMMENT,\n      ])\n    })\n\n    test('textarea handles entities', () => {\n      const ast = parse('<textarea>&amp;</textarea>', parserOptions)\n      const element = ast.children[0] as ElementNode\n      const text = element.children[0] as TextNode\n\n      expect(text).toStrictEqual({\n        type: NodeTypes.TEXT,\n        content: '&',\n        loc: {\n          start: { offset: 10, line: 1, column: 11 },\n          end: { offset: 15, line: 1, column: 16 },\n          source: '&amp;',\n        },\n      })\n    })\n\n    test('textarea support interpolation', () => {\n      const ast = parse('<textarea><div>{{ foo }}</textarea>', parserOptions)\n      const element = ast.children[0] as ElementNode\n      expect(element.children).toMatchObject([\n        { type: NodeTypes.TEXT, content: `<div>` },\n        {\n          type: NodeTypes.INTERPOLATION,\n          content: {\n            type: NodeTypes.SIMPLE_EXPRESSION,\n            content: `foo`,\n            isStatic: false,\n          },\n        },\n      ])\n    })\n\n    test('style handles comments/elements as just a text', () => {\n      const ast = parse(\n        '<style>some<div>text</div>and<!--comment--></style>',\n        parserOptions,\n      )\n      const element = ast.children[0] as ElementNode\n      const text = element.children[0] as TextNode\n\n      expect(text).toStrictEqual({\n        type: NodeTypes.TEXT,\n        content: 'some<div>text</div>and<!--comment-->',\n        loc: {\n          start: { offset: 7, line: 1, column: 8 },\n          end: { offset: 43, line: 1, column: 44 },\n          source: 'some<div>text</div>and<!--comment-->',\n        },\n      })\n    })\n\n    test(\"style doesn't handle character references\", () => {\n      const ast = parse('<style>&amp;</style>', parserOptions)\n      const element = ast.children[0] as ElementNode\n      const text = element.children[0] as TextNode\n\n      expect(text).toStrictEqual({\n        type: NodeTypes.TEXT,\n        content: '&amp;',\n        loc: {\n          start: { offset: 7, line: 1, column: 8 },\n          end: { offset: 12, line: 1, column: 13 },\n          source: '&amp;',\n        },\n      })\n    })\n\n    test('CDATA', () => {\n      const ast = parse('<svg><![CDATA[some text]]></svg>', parserOptions)\n      const text = (ast.children[0] as ElementNode).children![0] as TextNode\n\n      expect(text).toStrictEqual({\n        type: NodeTypes.TEXT,\n        content: 'some text',\n        loc: {\n          start: { offset: 14, line: 1, column: 15 },\n          end: { offset: 23, line: 1, column: 24 },\n          source: 'some text',\n        },\n      })\n    })\n\n    test('<pre> tag should preserve raw whitespace', () => {\n      const rawText = `  \\na   <div>foo \\n bar</div>   \\n   c`\n      const ast = parse(`<pre>${rawText}</pre>`, parserOptions)\n      expect((ast.children[0] as ElementNode).children).toMatchObject([\n        {\n          type: NodeTypes.TEXT,\n          content: `  \\na   `,\n        },\n        {\n          type: NodeTypes.ELEMENT,\n          children: [\n            {\n              type: NodeTypes.TEXT,\n              content: `foo \\n bar`,\n            },\n          ],\n        },\n        {\n          type: NodeTypes.TEXT,\n          content: `   \\n   c`,\n        },\n      ])\n    })\n\n    // #908\n    test('<pre> tag should remove leading newline', () => {\n      const rawText = `\\nhello<div>\\nbye</div>`\n      const ast = parse(`<pre>${rawText}</pre>`, parserOptions)\n      expect((ast.children[0] as ElementNode).children).toMatchObject([\n        {\n          type: NodeTypes.TEXT,\n          content: `hello`,\n        },\n        {\n          type: NodeTypes.ELEMENT,\n          children: [\n            {\n              type: NodeTypes.TEXT,\n              // should not remove the leading newline for nested elements\n              content: `\\nbye`,\n            },\n          ],\n        },\n      ])\n    })\n\n    // #945\n    test('&nbsp; should not be condensed', () => {\n      const nbsp = String.fromCharCode(160)\n      const ast = parse(`foo&nbsp;&nbsp;bar`, parserOptions)\n      expect(ast.children[0]).toMatchObject({\n        type: NodeTypes.TEXT,\n        content: `foo${nbsp}${nbsp}bar`,\n      })\n    })\n\n    // https://html.spec.whatwg.org/multipage/parsing.html#named-character-reference-state\n    test('HTML entities compatibility in text', () => {\n      const ast = parse('&ampersand;', parserOptions)\n      const text = ast.children[0] as TextNode\n\n      expect(text).toStrictEqual({\n        type: NodeTypes.TEXT,\n        content: '&ersand;',\n        loc: {\n          start: { offset: 0, line: 1, column: 1 },\n          end: { offset: 11, line: 1, column: 12 },\n          source: '&ampersand;',\n        },\n      })\n    })\n\n    // https://html.spec.whatwg.org/multipage/parsing.html#named-character-reference-state\n    test('HTML entities compatibility in attribute', () => {\n      const ast = parse(\n        '<div a=\"&ampersand;\" b=\"&amp;ersand;\" c=\"&amp!\"></div>',\n        parserOptions,\n      )\n      const element = ast.children[0] as ElementNode\n      const text1 = (element.props[0] as AttributeNode).value\n      const text2 = (element.props[1] as AttributeNode).value\n      const text3 = (element.props[2] as AttributeNode).value\n\n      expect(text1).toStrictEqual({\n        type: NodeTypes.TEXT,\n        content: '&ampersand;',\n        loc: {\n          start: { offset: 7, line: 1, column: 8 },\n          end: { offset: 20, line: 1, column: 21 },\n          source: '\"&ampersand;\"',\n        },\n      })\n      expect(text2).toStrictEqual({\n        type: NodeTypes.TEXT,\n        content: '&ersand;',\n        loc: {\n          start: { offset: 23, line: 1, column: 24 },\n          end: { offset: 37, line: 1, column: 38 },\n          source: '\"&amp;ersand;\"',\n        },\n      })\n      expect(text3).toStrictEqual({\n        type: NodeTypes.TEXT,\n        content: '&!',\n        loc: {\n          start: { offset: 40, line: 1, column: 41 },\n          end: { offset: 47, line: 1, column: 48 },\n          source: '\"&amp!\"',\n        },\n      })\n    })\n\n    test('Some control character reference should be replaced.', () => {\n      const ast = parse('&#x86;', parserOptions)\n      const text = ast.children[0] as TextNode\n\n      expect(text).toStrictEqual({\n        type: NodeTypes.TEXT,\n        content: '†',\n        loc: {\n          start: { offset: 0, line: 1, column: 1 },\n          end: { offset: 6, line: 1, column: 7 },\n          source: '&#x86;',\n        },\n      })\n    })\n  })\n\n  describe('Interpolation', () => {\n    test('HTML entities in interpolation should be translated for backward compatibility.', () => {\n      const ast = parse('<div>{{ a &lt; b }}</div>', parserOptions)\n      const element = ast.children[0] as ElementNode\n      const interpolation = element.children[0] as InterpolationNode\n\n      expect(interpolation).toStrictEqual({\n        type: NodeTypes.INTERPOLATION,\n        content: {\n          type: NodeTypes.SIMPLE_EXPRESSION,\n          content: `a < b`,\n          isStatic: false,\n          constType: ConstantTypes.NOT_CONSTANT,\n          loc: {\n            start: { offset: 8, line: 1, column: 9 },\n            end: { offset: 16, line: 1, column: 17 },\n            source: 'a &lt; b',\n          },\n        },\n        loc: {\n          start: { offset: 5, line: 1, column: 6 },\n          end: { offset: 19, line: 1, column: 20 },\n          source: '{{ a &lt; b }}',\n        },\n      })\n    })\n  })\n\n  describe('Element', () => {\n    test('void element', () => {\n      const ast = parse('<img>after', parserOptions)\n      const element = ast.children[0] as ElementNode\n\n      expect(element).toStrictEqual({\n        type: NodeTypes.ELEMENT,\n        ns: Namespaces.HTML,\n        tag: 'img',\n        tagType: ElementTypes.ELEMENT,\n        props: [],\n        children: [],\n        loc: {\n          start: { offset: 0, line: 1, column: 1 },\n          end: { offset: 5, line: 1, column: 6 },\n          source: '<img>',\n        },\n        codegenNode: undefined,\n      })\n    })\n\n    test('native element', () => {\n      const ast = parse('<div></div><comp></comp><Comp></Comp>', parserOptions)\n\n      expect(ast.children[0]).toMatchObject({\n        type: NodeTypes.ELEMENT,\n        tag: 'div',\n        tagType: ElementTypes.ELEMENT,\n      })\n\n      expect(ast.children[1]).toMatchObject({\n        type: NodeTypes.ELEMENT,\n        tag: 'comp',\n        tagType: ElementTypes.COMPONENT,\n      })\n\n      expect(ast.children[2]).toMatchObject({\n        type: NodeTypes.ELEMENT,\n        tag: 'Comp',\n        tagType: ElementTypes.COMPONENT,\n      })\n    })\n\n    test('Strict end tag detection for textarea.', () => {\n      const ast = parse(\n        '<textarea>hello</textarea</textarea0></texTArea>',\n        parserOptions,\n      )\n      const element = ast.children[0] as ElementNode\n      const text = element.children[0] as TextNode\n\n      expect(ast.children.length).toBe(1)\n      expect(text).toStrictEqual({\n        type: NodeTypes.TEXT,\n        content: 'hello</textarea</textarea0>',\n        loc: {\n          start: { offset: 10, line: 1, column: 11 },\n          end: { offset: 37, line: 1, column: 38 },\n          source: 'hello</textarea</textarea0>',\n        },\n      })\n    })\n  })\n\n  describe('Namespaces', () => {\n    test('HTML namespace', () => {\n      const ast = parse('<html>test</html>', parserOptions)\n      const element = ast.children[0] as ElementNode\n\n      expect(element.ns).toBe(Namespaces.HTML)\n    })\n\n    test('SVG namespace', () => {\n      const ast = parse('<svg>test</svg>', parserOptions)\n      const element = ast.children[0] as ElementNode\n\n      expect(element.ns).toBe(Namespaces.SVG)\n    })\n\n    test('MATH_ML namespace', () => {\n      const ast = parse('<math>test</math>', parserOptions)\n      const element = ast.children[0] as ElementNode\n\n      expect(element.ns).toBe(Namespaces.MATH_ML)\n    })\n\n    test('SVG in MATH_ML namespace', () => {\n      const ast = parse(\n        '<math><annotation-xml><svg></svg></annotation-xml></math>',\n        parserOptions,\n      )\n      const elementMath = ast.children[0] as ElementNode\n      const elementAnnotation = elementMath.children[0] as ElementNode\n      const elementSvg = elementAnnotation.children[0] as ElementNode\n\n      expect(elementMath.ns).toBe(Namespaces.MATH_ML)\n      expect(elementSvg.ns).toBe(Namespaces.SVG)\n    })\n\n    test('html text/html in MATH_ML namespace', () => {\n      const ast = parse(\n        '<math><annotation-xml encoding=\"text/html\"><test/></annotation-xml></math>',\n        parserOptions,\n      )\n\n      const elementMath = ast.children[0] as ElementNode\n      const elementAnnotation = elementMath.children[0] as ElementNode\n      const element = elementAnnotation.children[0] as ElementNode\n\n      expect(elementMath.ns).toBe(Namespaces.MATH_ML)\n      expect(element.ns).toBe(Namespaces.HTML)\n    })\n\n    test('html application/xhtml+xml in MATH_ML namespace', () => {\n      const ast = parse(\n        '<math><annotation-xml encoding=\"application/xhtml+xml\"><test/></annotation-xml></math>',\n        parserOptions,\n      )\n      const elementMath = ast.children[0] as ElementNode\n      const elementAnnotation = elementMath.children[0] as ElementNode\n      const element = elementAnnotation.children[0] as ElementNode\n\n      expect(elementMath.ns).toBe(Namespaces.MATH_ML)\n      expect(element.ns).toBe(Namespaces.HTML)\n    })\n\n    test('mtext malignmark in MATH_ML namespace', () => {\n      const ast = parse(\n        '<math><mtext><malignmark/></mtext></math>',\n        parserOptions,\n      )\n      const elementMath = ast.children[0] as ElementNode\n      const elementText = elementMath.children[0] as ElementNode\n      const element = elementText.children[0] as ElementNode\n\n      expect(elementMath.ns).toBe(Namespaces.MATH_ML)\n      expect(element.ns).toBe(Namespaces.MATH_ML)\n    })\n\n    test('mtext and not malignmark tag in MATH_ML namespace', () => {\n      const ast = parse('<math><mtext><test/></mtext></math>', parserOptions)\n      const elementMath = ast.children[0] as ElementNode\n      const elementText = elementMath.children[0] as ElementNode\n      const element = elementText.children[0] as ElementNode\n\n      expect(elementMath.ns).toBe(Namespaces.MATH_ML)\n      expect(element.ns).toBe(Namespaces.HTML)\n    })\n\n    test('foreignObject tag in SVG namespace', () => {\n      const ast = parse(\n        '<svg><foreignObject><test/></foreignObject></svg>',\n        parserOptions,\n      )\n      const elementSvg = ast.children[0] as ElementNode\n      const elementForeignObject = elementSvg.children[0] as ElementNode\n      const element = elementForeignObject.children[0] as ElementNode\n\n      expect(elementSvg.ns).toBe(Namespaces.SVG)\n      expect(element.ns).toBe(Namespaces.HTML)\n    })\n\n    test('desc tag in SVG namespace', () => {\n      const ast = parse('<svg><desc><test/></desc></svg>', parserOptions)\n      const elementSvg = ast.children[0] as ElementNode\n      const elementDesc = elementSvg.children[0] as ElementNode\n      const element = elementDesc.children[0] as ElementNode\n\n      expect(elementSvg.ns).toBe(Namespaces.SVG)\n      expect(element.ns).toBe(Namespaces.HTML)\n    })\n\n    test('title tag in SVG namespace', () => {\n      const ast = parse('<svg><title><test/></title></svg>', parserOptions)\n      const elementSvg = ast.children[0] as ElementNode\n      const elementTitle = elementSvg.children[0] as ElementNode\n      const element = elementTitle.children[0] as ElementNode\n\n      expect(elementSvg.ns).toBe(Namespaces.SVG)\n      expect(element.ns).toBe(Namespaces.HTML)\n    })\n\n    test('SVG in HTML namespace', () => {\n      const ast = parse('<html><svg></svg></html>', parserOptions)\n      const elementHtml = ast.children[0] as ElementNode\n      const element = elementHtml.children[0] as ElementNode\n\n      expect(elementHtml.ns).toBe(Namespaces.HTML)\n      expect(element.ns).toBe(Namespaces.SVG)\n    })\n\n    test('MATH in HTML namespace', () => {\n      const ast = parse('<html><math></math></html>', parserOptions)\n      const elementHtml = ast.children[0] as ElementNode\n      const element = elementHtml.children[0] as ElementNode\n\n      expect(elementHtml.ns).toBe(Namespaces.HTML)\n      expect(element.ns).toBe(Namespaces.MATH_ML)\n    })\n\n    test('root ns', () => {\n      const ast = parse('<foreignObject><test/></foreignObject>', {\n        ...parserOptions,\n        ns: Namespaces.SVG,\n      })\n      const elementForieng = ast.children[0] as ElementNode\n      const element = elementForieng.children[0] as ElementNode\n\n      expect(elementForieng.ns).toBe(Namespaces.SVG)\n      expect(element.ns).toBe(Namespaces.HTML)\n    })\n\n    test('correct XML handling with root ns', () => {\n      // when root ns is an XML namespace, there should be no special content\n      // treatment for <script>, <style>, <textarea> etc.\n      const ast = parse('<script><g/><g/></script>', {\n        ...parserOptions,\n        ns: Namespaces.SVG,\n      })\n      const elementSvg = ast.children[0] as ElementNode\n      // should parse as nodes instead of text\n      expect(elementSvg.children).toMatchObject([\n        { type: NodeTypes.ELEMENT, tag: 'g' },\n        { type: NodeTypes.ELEMENT, tag: 'g' },\n      ])\n    })\n  })\n})\n"
  },
  {
    "path": "packages/compiler-dom/__tests__/transforms/Transition.spec.ts",
    "content": "import { compile } from '../../src'\n\ndescribe('Transition multi children warnings', () => {\n  function checkWarning(\n    template: string,\n    shouldWarn: boolean,\n    message = `<Transition> expects exactly one child element or component.`,\n  ) {\n    const spy = vi.fn()\n    compile(template.trim(), {\n      hoistStatic: true,\n      transformHoist: null,\n      onError: err => {\n        spy(err.message)\n      },\n    })\n\n    if (shouldWarn) expect(spy).toHaveBeenCalledWith(message)\n    else expect(spy).not.toHaveBeenCalled()\n  }\n\n  test('warns if multiple children', () => {\n    checkWarning(\n      `\n      <transition>\n        <div>hey</div>\n        <div>hey</div>\n      </transition>\n      `,\n      true,\n    )\n  })\n\n  test('warns with v-for', () => {\n    checkWarning(\n      `\n      <transition>\n        <div v-for=\"i in items\">hey</div>\n      </transition>\n      `,\n      true,\n    )\n  })\n\n  test('warns with multiple v-if + v-for', () => {\n    checkWarning(\n      `\n      <transition>\n        <div v-if=\"a\" v-for=\"i in items\">hey</div>\n        <div v-else v-for=\"i in items\">hey</div>\n      </transition>\n      `,\n      true,\n    )\n  })\n\n  test('warns with template v-if', () => {\n    checkWarning(\n      `\n      <transition>\n        <template v-if=\"ok\"></template>\n      </transition>\n      `,\n      true,\n    )\n  })\n\n  test('warns with multiple templates', () => {\n    checkWarning(\n      `\n      <transition>\n        <template v-if=\"a\"></template>\n        <template v-else></template>\n      </transition>\n      `,\n      true,\n    )\n  })\n\n  test('warns if multiple children with v-if', () => {\n    checkWarning(\n      `\n      <transition>\n        <div v-if=\"one\">hey</div>\n        <div v-if=\"other\">hey</div>\n      </transition>\n      `,\n      true,\n    )\n  })\n\n  test('does not warn with regular element', () => {\n    checkWarning(\n      `\n      <transition>\n        <div>hey</div>\n      </transition>\n      `,\n      false,\n    )\n  })\n\n  test('does not warn with one single v-if', () => {\n    checkWarning(\n      `\n      <transition>\n        <div v-if=\"a\">hey</div>\n      </transition>\n      `,\n      false,\n    )\n  })\n\n  test('does not warn with v-if v-else-if v-else', () => {\n    checkWarning(\n      `\n      <transition>\n        <div v-if=\"a\">hey</div>\n        <div v-else-if=\"b\">hey</div>\n        <div v-else>hey</div>\n      </transition>\n      `,\n      false,\n    )\n  })\n\n  test('does not warn with v-if v-else', () => {\n    checkWarning(\n      `\n      <transition>\n        <div v-if=\"a\">hey</div>\n        <div v-else>hey</div>\n      </transition>\n      `,\n      false,\n    )\n  })\n\n  test('non-breaking spaces are treated as normal text', () => {\n    checkWarning(\n      `\n      <transition>\n        \\u00a0\n        <div>foo</div>\n      </transition>\n      `,\n      true,\n    )\n  })\n})\n\ntest('inject persisted when child has v-show', () => {\n  expect(\n    compile(`\n    <transition>\n      <div v-show=\"ok\" />\n    </transition>\n    `).code,\n  ).toMatchSnapshot()\n})\n\ntest('the v-if/else-if/else branches in Transition should ignore comments', () => {\n  expect(\n    compile(`\n    <transition>\n      <div v-if=\"a\">hey</div>\n      <!-- this should be ignored -->\n      <div v-else-if=\"b\">hey</div>\n      <!-- this should be ignored -->\n      <div v-else>\n        <p v-if=\"c\"/>\n        <!-- this should not be ignored -->\n        <p v-else/>\n      </div>\n    </transition>\n    `).code,\n  ).toMatchSnapshot()\n})\n\ntest('comments and preserved whitespace are ignored', () => {\n  expect(\n    compile(\n      `\n      <transition>\n        <!-- foo --> <!-- bar -->\n        <div>foo bar</div>\n      </transition>\n      `,\n      {\n        whitespace: 'preserve',\n      },\n    ).code,\n  ).toMatchSnapshot()\n})\n"
  },
  {
    "path": "packages/compiler-dom/__tests__/transforms/__snapshots__/Transition.spec.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`comments and preserved whitespace are ignored 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { createCommentVNode: _createCommentVNode, createElementVNode: _createElementVNode, Transition: _Transition, withCtx: _withCtx, openBlock: _openBlock, createBlock: _createBlock } = _Vue\n\n    return (_openBlock(), _createBlock(_Transition, null, {\n      default: _withCtx(() => [\n        _createElementVNode(\"div\", null, \"foo bar\")\n      ]),\n      _: 1 /* STABLE */\n    }))\n  }\n}\"\n`;\n\nexports[`inject persisted when child has v-show 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { vShow: _vShow, createElementVNode: _createElementVNode, withDirectives: _withDirectives, Transition: _Transition, withCtx: _withCtx, openBlock: _openBlock, createBlock: _createBlock } = _Vue\n\n    return (_openBlock(), _createBlock(_Transition, { persisted: \"\" }, {\n      default: _withCtx(() => [\n        _withDirectives(_createElementVNode(\"div\", null, null, 512 /* NEED_PATCH */), [\n          [_vShow, ok]\n        ])\n      ]),\n      _: 1 /* STABLE */\n    }))\n  }\n}\"\n`;\n\nexports[`the v-if/else-if/else branches in Transition should ignore comments 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { openBlock: _openBlock, createElementBlock: _createElementBlock, createCommentVNode: _createCommentVNode, createElementVNode: _createElementVNode, Fragment: _Fragment, Transition: _Transition, withCtx: _withCtx, createBlock: _createBlock } = _Vue\n\n    return (_openBlock(), _createBlock(_Transition, null, {\n      default: _withCtx(() => [\n        a\n          ? (_openBlock(), _createElementBlock(\"div\", { key: 0 }, \"hey\"))\n          : b\n            ? (_openBlock(), _createElementBlock(\"div\", { key: 1 }, \"hey\"))\n            : (_openBlock(), _createElementBlock(\"div\", { key: 2 }, [\n                c\n                  ? (_openBlock(), _createElementBlock(\"p\", { key: 0 }))\n                  : (_openBlock(), _createElementBlock(_Fragment, { key: 1 }, [\n                      _createCommentVNode(\" this should not be ignored \"),\n                      _createElementVNode(\"p\")\n                    ], 2112 /* STABLE_FRAGMENT, DEV_ROOT_FRAGMENT */))\n              ]))\n      ]),\n      _: 1 /* STABLE */\n    }))\n  }\n}\"\n`;\n"
  },
  {
    "path": "packages/compiler-dom/__tests__/transforms/__snapshots__/stringifyStatic.spec.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`stringify static html > eligible content (elements > 20) + non-eligible content 1`] = `\n\"const { createElementVNode: _createElementVNode, createStaticVNode: _createStaticVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue\n\nreturn function render(_ctx, _cache) {\n  return (_openBlock(), _createElementBlock(\"div\", null, [...(_cache[0] || (_cache[0] = [\n    _createStaticVNode(\"<span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span>\", 20),\n    _createElementVNode(\"div\", { key: \"1\" }, \"1\", -1 /* CACHED */),\n    _createStaticVNode(\"<span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span>\", 20)\n  ]))]))\n}\"\n`;\n\nexports[`stringify static html > eligible content + v-once node 1`] = `\n\"const { setBlockTracking: _setBlockTracking, toDisplayString: _toDisplayString, createTextVNode: _createTextVNode, createElementVNode: _createElementVNode, createStaticVNode: _createStaticVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue\n\nreturn function render(_ctx, _cache) {\n  return (_openBlock(), _createElementBlock(\"div\", null, [\n    _cache[0] || (\n      _setBlockTracking(-1, true),\n      (_cache[0] = _createElementVNode(\"div\", null, [\n        _createTextVNode(_toDisplayString(_ctx.msg), 1 /* TEXT */)\n      ])).cacheIndex = 0,\n      _setBlockTracking(1),\n      _cache[0]\n    ),\n    _cache[1] || (_cache[1] = _createStaticVNode(\"<span class=\\\\\"foo\\\\\">foo</span><span class=\\\\\"foo\\\\\">foo</span><span class=\\\\\"foo\\\\\">foo</span><span class=\\\\\"foo\\\\\">foo</span><span class=\\\\\"foo\\\\\">foo</span>\", 5))\n  ]))\n}\"\n`;\n\nexports[`stringify static html > escape 1`] = `\n\"const { toDisplayString: _toDisplayString, normalizeClass: _normalizeClass, createElementVNode: _createElementVNode, createStaticVNode: _createStaticVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue\n\nreturn function render(_ctx, _cache) {\n  return (_openBlock(), _createElementBlock(\"div\", null, [...(_cache[0] || (_cache[0] = [\n    _createStaticVNode(\"<div><span class=\\\\\"foo&gt;ar\\\\\">1 + &lt;</span><span>&amp;</span><span class=\\\\\"foo&gt;ar\\\\\">1 + &lt;</span><span>&amp;</span><span class=\\\\\"foo&gt;ar\\\\\">1 + &lt;</span><span>&amp;</span><span class=\\\\\"foo&gt;ar\\\\\">1 + &lt;</span><span>&amp;</span><span class=\\\\\"foo&gt;ar\\\\\">1 + &lt;</span><span>&amp;</span></div>\", 1)\n  ]))]))\n}\"\n`;\n\nexports[`stringify static html > serializing constant bindings 1`] = `\n\"const { toDisplayString: _toDisplayString, normalizeClass: _normalizeClass, createElementVNode: _createElementVNode, createStaticVNode: _createStaticVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue\n\nreturn function render(_ctx, _cache) {\n  return (_openBlock(), _createElementBlock(\"div\", null, [...(_cache[0] || (_cache[0] = [\n    _createStaticVNode(\"<div style=\\\\\"color:red;\\\\\"><span class=\\\\\"foo bar\\\\\">1 + false</span><span class=\\\\\"foo bar\\\\\">1 + false</span><span class=\\\\\"foo bar\\\\\">1 + false</span><span class=\\\\\"foo bar\\\\\">1 + false</span><span class=\\\\\"foo bar\\\\\">1 + false</span></div>\", 1)\n  ]))]))\n}\"\n`;\n\nexports[`stringify static html > serializing template string style 1`] = `\n\"const { toDisplayString: _toDisplayString, normalizeClass: _normalizeClass, createElementVNode: _createElementVNode, createStaticVNode: _createStaticVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue\n\nreturn function render(_ctx, _cache) {\n  return (_openBlock(), _createElementBlock(\"div\", null, [...(_cache[0] || (_cache[0] = [\n    _createStaticVNode(\"<div style=\\\\\"color:red;\\\\\"><span class=\\\\\"foo bar\\\\\">1 + false</span><span class=\\\\\"foo bar\\\\\">1 + false</span><span class=\\\\\"foo bar\\\\\">1 + false</span><span class=\\\\\"foo bar\\\\\">1 + false</span><span class=\\\\\"foo bar\\\\\">1 + false</span></div>\", 1)\n  ]))]))\n}\"\n`;\n\nexports[`stringify static html > should bail for <option> elements with null values 1`] = `\n\"const { createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue\n\nreturn function render(_ctx, _cache) {\n  return (_openBlock(), _createElementBlock(\"div\", null, [...(_cache[0] || (_cache[0] = [\n    _createElementVNode(\"select\", null, [\n      _createElementVNode(\"option\", { value: null }),\n      _createElementVNode(\"option\", { value: \"1\" }),\n      _createElementVNode(\"option\", { value: \"1\" }),\n      _createElementVNode(\"option\", { value: \"1\" }),\n      _createElementVNode(\"option\", { value: \"1\" }),\n      _createElementVNode(\"option\", { value: \"1\" })\n    ], -1 /* CACHED */)\n  ]))]))\n}\"\n`;\n\nexports[`stringify static html > should bail for <option> elements with number values 1`] = `\n\"const { createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue\n\nreturn function render(_ctx, _cache) {\n  return (_openBlock(), _createElementBlock(\"div\", null, [...(_cache[0] || (_cache[0] = [\n    _createElementVNode(\"select\", null, [\n      _createElementVNode(\"option\", { value: 1 }),\n      _createElementVNode(\"option\", { value: 1 }),\n      _createElementVNode(\"option\", { value: 1 }),\n      _createElementVNode(\"option\", { value: 1 }),\n      _createElementVNode(\"option\", { value: 1 })\n    ], -1 /* CACHED */)\n  ]))]))\n}\"\n`;\n\nexports[`stringify static html > should bail for comments 1`] = `\n\"const { createCommentVNode: _createCommentVNode, createElementVNode: _createElementVNode, createStaticVNode: _createStaticVNode, Fragment: _Fragment, openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue\n\nconst _hoisted_1 = { class: \"a\" }\n\nreturn function render(_ctx, _cache) {\n  return (_openBlock(), _createElementBlock(_Fragment, null, [\n    _createCommentVNode(\" Comment 1 \"),\n    _createElementVNode(\"div\", _hoisted_1, [\n      _createCommentVNode(\" Comment 2 \"),\n      _cache[0] || (_cache[0] = _createStaticVNode(\"<span class=\\\\\"b\\\\\"></span><span class=\\\\\"b\\\\\"></span><span class=\\\\\"b\\\\\"></span><span class=\\\\\"b\\\\\"></span><span class=\\\\\"b\\\\\"></span>\", 5))\n    ])\n  ], 2112 /* STABLE_FRAGMENT, DEV_ROOT_FRAGMENT */))\n}\"\n`;\n\nexports[`stringify static html > should bail on bindings that are cached but not stringifiable 1`] = `\n\"const { createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue\n\nreturn function render(_ctx, _cache) {\n  return (_openBlock(), _createElementBlock(\"div\", null, [...(_cache[0] || (_cache[0] = [\n    _createElementVNode(\"div\", null, [\n      _createElementVNode(\"span\", { class: \"foo\" }, \"foo\"),\n      _createElementVNode(\"span\", { class: \"foo\" }, \"foo\"),\n      _createElementVNode(\"span\", { class: \"foo\" }, \"foo\"),\n      _createElementVNode(\"span\", { class: \"foo\" }, \"foo\"),\n      _createElementVNode(\"span\", { class: \"foo\" }, \"foo\"),\n      _createElementVNode(\"img\", { src: _imports_0_ })\n    ], -1 /* CACHED */)\n  ]))]))\n}\"\n`;\n\nexports[`stringify static html > should work for <option> elements with string values 1`] = `\n\"const { createElementVNode: _createElementVNode, createStaticVNode: _createStaticVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue\n\nreturn function render(_ctx, _cache) {\n  return (_openBlock(), _createElementBlock(\"div\", null, [...(_cache[0] || (_cache[0] = [\n    _createStaticVNode(\"<select><option value=\\\\\"1\\\\\"></option><option value=\\\\\"1\\\\\"></option><option value=\\\\\"1\\\\\"></option><option value=\\\\\"1\\\\\"></option><option value=\\\\\"1\\\\\"></option></select>\", 1)\n  ]))]))\n}\"\n`;\n\nexports[`stringify static html > should work for multiple adjacent nodes 1`] = `\n\"const { createElementVNode: _createElementVNode, createStaticVNode: _createStaticVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue\n\nreturn function render(_ctx, _cache) {\n  return (_openBlock(), _createElementBlock(\"div\", null, [...(_cache[0] || (_cache[0] = [\n    _createStaticVNode(\"<span class=\\\\\"foo\\\\\"></span><span class=\\\\\"foo\\\\\"></span><span class=\\\\\"foo\\\\\"></span><span class=\\\\\"foo\\\\\"></span><span class=\\\\\"foo\\\\\"></span>\", 5)\n  ]))]))\n}\"\n`;\n\nexports[`stringify static html > should work on eligible content (elements > 20) 1`] = `\n\"const { createElementVNode: _createElementVNode, createStaticVNode: _createStaticVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue\n\nreturn function render(_ctx, _cache) {\n  return (_openBlock(), _createElementBlock(\"div\", null, [...(_cache[0] || (_cache[0] = [\n    _createStaticVNode(\"<div><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></div>\", 1)\n  ]))]))\n}\"\n`;\n\nexports[`stringify static html > should work on eligible content (elements with binding > 5) 1`] = `\n\"const { createElementVNode: _createElementVNode, createStaticVNode: _createStaticVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue\n\nreturn function render(_ctx, _cache) {\n  return (_openBlock(), _createElementBlock(\"div\", null, [...(_cache[0] || (_cache[0] = [\n    _createStaticVNode(\"<div><span class=\\\\\"foo\\\\\"></span><span class=\\\\\"foo\\\\\"></span><span class=\\\\\"foo\\\\\"></span><span class=\\\\\"foo\\\\\"></span><span class=\\\\\"foo\\\\\"></span></div>\", 1)\n  ]))]))\n}\"\n`;\n\nexports[`stringify static html > should work with bindings that are non-static but stringifiable 1`] = `\n\"const { createElementVNode: _createElementVNode, createStaticVNode: _createStaticVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue\n\nreturn function render(_ctx, _cache) {\n  return (_openBlock(), _createElementBlock(\"div\", null, [...(_cache[0] || (_cache[0] = [\n    _createStaticVNode(\"<div><span class=\\\\\"foo\\\\\">foo</span><span class=\\\\\"foo\\\\\">foo</span><span class=\\\\\"foo\\\\\">foo</span><span class=\\\\\"foo\\\\\">foo</span><span class=\\\\\"foo\\\\\">foo</span><img src=\\\\\"\" + _imports_0_ + \"\\\\\"></div>\", 1)\n  ]))]))\n}\"\n`;\n\nexports[`stringify static html > stringify v-html 1`] = `\n\"const { createElementVNode: _createElementVNode, createStaticVNode: _createStaticVNode } = Vue\n\nreturn function render(_ctx, _cache) {\n  return _cache[0] || (_cache[0] = _createStaticVNode(\"<pre data-type=\\\\\"js\\\\\"><code><span>show-it </span></code></pre><div class><span class>1</span><span class>2</span></div>\", 2))\n}\"\n`;\n\nexports[`stringify static html > stringify v-text 1`] = `\n\"const { createElementVNode: _createElementVNode, createStaticVNode: _createStaticVNode } = Vue\n\nreturn function render(_ctx, _cache) {\n  return _cache[0] || (_cache[0] = _createStaticVNode(\"<pre data-type=\\\\\"js\\\\\"><code>&lt;span&gt;show-it &lt;/span&gt;</code></pre><div class><span class>1</span><span class>2</span></div>\", 2))\n}\"\n`;\n\nexports[`stringify static html > stringify v-text with escape 1`] = `\n\"const { createElementVNode: _createElementVNode, createStaticVNode: _createStaticVNode } = Vue\n\nreturn function render(_ctx, _cache) {\n  return _cache[0] || (_cache[0] = _createStaticVNode(\"<pre data-type=\\\\\"js\\\\\"><code>text1</code></pre><div class><span class>1</span><span class>2</span></div>\", 2))\n}\"\n`;\n"
  },
  {
    "path": "packages/compiler-dom/__tests__/transforms/__snapshots__/vModel.spec.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`compiler: transform v-model > errors > should allow usage on custom element 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { vModelText: _vModelText, withDirectives: _withDirectives, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue\n\n    return _withDirectives((_openBlock(), _createElementBlock(\"my-input\", {\n      \"onUpdate:modelValue\": $event => ((model) = $event)\n    }, null, 8 /* PROPS */, [\"onUpdate:modelValue\"])), [\n      [_vModelText, model]\n    ])\n  }\n}\"\n`;\n\nexports[`compiler: transform v-model > input w/ dynamic v-bind 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { vModelDynamic: _vModelDynamic, mergeProps: _mergeProps, withDirectives: _withDirectives, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue\n\n    return _withDirectives((_openBlock(), _createElementBlock(\"input\", _mergeProps(obj, {\n      \"onUpdate:modelValue\": $event => ((model) = $event)\n    }), null, 16 /* FULL_PROPS */, [\"onUpdate:modelValue\"])), [\n      [_vModelDynamic, model]\n    ])\n  }\n}\"\n`;\n\nexports[`compiler: transform v-model > input w/ dynamic v-bind 2`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { vModelDynamic: _vModelDynamic, withDirectives: _withDirectives, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue\n\n    return _withDirectives((_openBlock(), _createElementBlock(\"input\", {\n      \"onUpdate:modelValue\": $event => ((model) = $event)\n    }, null, 8 /* PROPS */, [\"onUpdate:modelValue\"])), [\n      [_vModelDynamic, model]\n    ])\n  }\n}\"\n`;\n\nexports[`compiler: transform v-model > input with v-bind shorthand type after v-model should use dynamic model 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { vModelDynamic: _vModelDynamic, withDirectives: _withDirectives, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue\n\n    return _withDirectives((_openBlock(), _createElementBlock(\"input\", {\n      \"onUpdate:modelValue\": $event => ((model) = $event)\n    }, null, 8 /* PROPS */, [\"onUpdate:modelValue\"])), [\n      [_vModelDynamic, model]\n    ])\n  }\n}\"\n`;\n\nexports[`compiler: transform v-model > modifiers > .lazy 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { vModelText: _vModelText, withDirectives: _withDirectives, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue\n\n    return _withDirectives((_openBlock(), _createElementBlock(\"input\", {\n      \"onUpdate:modelValue\": $event => ((model) = $event)\n    }, null, 8 /* PROPS */, [\"onUpdate:modelValue\"])), [\n      [\n        _vModelText,\n        model,\n        void 0,\n        { lazy: true }\n      ]\n    ])\n  }\n}\"\n`;\n\nexports[`compiler: transform v-model > modifiers > .number 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { vModelText: _vModelText, withDirectives: _withDirectives, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue\n\n    return _withDirectives((_openBlock(), _createElementBlock(\"input\", {\n      \"onUpdate:modelValue\": $event => ((model) = $event)\n    }, null, 8 /* PROPS */, [\"onUpdate:modelValue\"])), [\n      [\n        _vModelText,\n        model,\n        void 0,\n        { number: true }\n      ]\n    ])\n  }\n}\"\n`;\n\nexports[`compiler: transform v-model > modifiers > .trim 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { vModelText: _vModelText, withDirectives: _withDirectives, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue\n\n    return _withDirectives((_openBlock(), _createElementBlock(\"input\", {\n      \"onUpdate:modelValue\": $event => ((model) = $event)\n    }, null, 8 /* PROPS */, [\"onUpdate:modelValue\"])), [\n      [\n        _vModelText,\n        model,\n        void 0,\n        { trim: true }\n      ]\n    ])\n  }\n}\"\n`;\n\nexports[`compiler: transform v-model > simple expression 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { vModelText: _vModelText, withDirectives: _withDirectives, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue\n\n    return _withDirectives((_openBlock(), _createElementBlock(\"input\", {\n      \"onUpdate:modelValue\": $event => ((model) = $event)\n    }, null, 8 /* PROPS */, [\"onUpdate:modelValue\"])), [\n      [_vModelText, model]\n    ])\n  }\n}\"\n`;\n\nexports[`compiler: transform v-model > simple expression for input (checkbox) 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { vModelCheckbox: _vModelCheckbox, withDirectives: _withDirectives, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue\n\n    return _withDirectives((_openBlock(), _createElementBlock(\"input\", {\n      type: \"checkbox\",\n      \"onUpdate:modelValue\": $event => ((model) = $event)\n    }, null, 8 /* PROPS */, [\"onUpdate:modelValue\"])), [\n      [_vModelCheckbox, model]\n    ])\n  }\n}\"\n`;\n\nexports[`compiler: transform v-model > simple expression for input (dynamic type) 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { vModelDynamic: _vModelDynamic, withDirectives: _withDirectives, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue\n\n    return _withDirectives((_openBlock(), _createElementBlock(\"input\", {\n      \"onUpdate:modelValue\": $event => ((model) = $event)\n    }, null, 8 /* PROPS */, [\"onUpdate:modelValue\"])), [\n      [_vModelDynamic, model]\n    ])\n  }\n}\"\n`;\n\nexports[`compiler: transform v-model > simple expression for input (radio) 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { vModelRadio: _vModelRadio, withDirectives: _withDirectives, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue\n\n    return _withDirectives((_openBlock(), _createElementBlock(\"input\", {\n      type: \"radio\",\n      \"onUpdate:modelValue\": $event => ((model) = $event)\n    }, null, 8 /* PROPS */, [\"onUpdate:modelValue\"])), [\n      [_vModelRadio, model]\n    ])\n  }\n}\"\n`;\n\nexports[`compiler: transform v-model > simple expression for input (text) 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { vModelText: _vModelText, withDirectives: _withDirectives, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue\n\n    return _withDirectives((_openBlock(), _createElementBlock(\"input\", {\n      type: \"text\",\n      \"onUpdate:modelValue\": $event => ((model) = $event)\n    }, null, 8 /* PROPS */, [\"onUpdate:modelValue\"])), [\n      [_vModelText, model]\n    ])\n  }\n}\"\n`;\n\nexports[`compiler: transform v-model > simple expression for select 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { vModelSelect: _vModelSelect, withDirectives: _withDirectives, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue\n\n    return _withDirectives((_openBlock(), _createElementBlock(\"select\", {\n      \"onUpdate:modelValue\": $event => ((model) = $event)\n    }, null, 8 /* PROPS */, [\"onUpdate:modelValue\"])), [\n      [_vModelSelect, model]\n    ])\n  }\n}\"\n`;\n\nexports[`compiler: transform v-model > simple expression for textarea 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { vModelText: _vModelText, withDirectives: _withDirectives, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue\n\n    return _withDirectives((_openBlock(), _createElementBlock(\"textarea\", {\n      \"onUpdate:modelValue\": $event => ((model) = $event)\n    }, null, 8 /* PROPS */, [\"onUpdate:modelValue\"])), [\n      [_vModelText, model]\n    ])\n  }\n}\"\n`;\n"
  },
  {
    "path": "packages/compiler-dom/__tests__/transforms/__snapshots__/vShow.spec.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`compiler: v-show transform > simple expression 1`] = `\n\"const _Vue = Vue\n\nreturn function render(_ctx, _cache) {\n  with (_ctx) {\n    const { vShow: _vShow, withDirectives: _withDirectives, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue\n\n    return _withDirectives((_openBlock(), _createElementBlock(\"div\", null, null, 512 /* NEED_PATCH */)), [\n      [_vShow, a]\n    ])\n  }\n}\"\n`;\n"
  },
  {
    "path": "packages/compiler-dom/__tests__/transforms/ignoreSideEffectTags.spec.ts",
    "content": "import { type CompilerError, compile } from '../../src'\n\ndescribe('compiler: ignore side effect tags', () => {\n  it('should ignore script', () => {\n    let err: CompilerError | undefined\n    const { code } = compile(`<script>console.log(1)</script>`, {\n      onError(e) {\n        err = e\n      },\n    })\n    expect(code).not.toMatch('script')\n    expect(err).toBeDefined()\n    expect(err!.message).toMatch(`Tags with side effect`)\n  })\n\n  it('should ignore style', () => {\n    let err: CompilerError | undefined\n    const { code } = compile(`<style>h1 { color: red }</style>`, {\n      onError(e) {\n        err = e\n      },\n    })\n    expect(code).not.toMatch('style')\n    expect(err).toBeDefined()\n    expect(err!.message).toMatch(`Tags with side effect`)\n  })\n})\n"
  },
  {
    "path": "packages/compiler-dom/__tests__/transforms/stringifyStatic.spec.ts",
    "content": "import {\n  CREATE_STATIC,\n  ConstantTypes,\n  NodeTypes,\n  compile,\n  createSimpleExpression,\n} from '../../src'\nimport {\n  StringifyThresholds,\n  stringifyStatic,\n} from '../../src/transforms/stringifyStatic'\n\ndescribe('stringify static html', () => {\n  function compileWithStringify(template: string) {\n    return compile(template, {\n      hoistStatic: true,\n      prefixIdentifiers: true,\n      transformHoist: stringifyStatic,\n    })\n  }\n\n  function repeat(code: string, n: number): string {\n    return code.repeat(n)\n  }\n\n  /**\n   * Assert cached node NOT stringified\n   */\n  function cachedArrayBailedMatcher(n = 1) {\n    return {\n      type: NodeTypes.JS_CACHE_EXPRESSION,\n      value: {\n        type: NodeTypes.JS_ARRAY_EXPRESSION,\n        elements: new Array(n).fill(0).map(() => ({\n          // should remain VNODE_CALL instead of JS_CALL_EXPRESSION\n          codegenNode: { type: NodeTypes.VNODE_CALL },\n        })),\n      },\n    }\n  }\n\n  /**\n   * Assert cached node is stringified (no content check)\n   */\n  function cachedArraySuccessMatcher(n = 1) {\n    return {\n      type: NodeTypes.JS_CACHE_EXPRESSION,\n      value: {\n        type: NodeTypes.JS_ARRAY_EXPRESSION,\n        elements: new Array(n).fill(0).map(() => ({\n          type: NodeTypes.JS_CALL_EXPRESSION,\n          callee: CREATE_STATIC,\n        })),\n      },\n    }\n  }\n\n  /**\n   * Assert cached node stringified with desired content and node count\n   */\n  function cachedArrayStaticNodeMatcher(content: string, count: number) {\n    return {\n      type: NodeTypes.JS_CACHE_EXPRESSION,\n      value: {\n        type: NodeTypes.JS_ARRAY_EXPRESSION,\n        elements: [\n          {\n            type: NodeTypes.JS_CALL_EXPRESSION,\n            callee: CREATE_STATIC,\n            arguments: [JSON.stringify(content), String(count)],\n          },\n        ],\n      },\n    }\n  }\n\n  test('should bail on non-eligible static trees', () => {\n    const { ast } = compileWithStringify(\n      `<div><div><div>hello</div><div>hello</div></div></div>`,\n    )\n    // should be cached children array\n    expect(ast.cached[0]!.value.type).toBe(NodeTypes.JS_ARRAY_EXPRESSION)\n  })\n\n  test('should work on eligible content (elements with binding > 5)', () => {\n    const { code, ast } = compileWithStringify(\n      `<div><div>${repeat(\n        `<span class=\"foo\"/>`,\n        StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,\n      )}</div></div>`,\n    )\n\n    // should be optimized now\n    expect(ast.cached).toMatchObject([\n      cachedArrayStaticNodeMatcher(\n        `<div>${repeat(\n          `<span class=\"foo\"></span>`,\n          StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,\n        )}</div>`,\n        1,\n      ),\n    ])\n\n    expect(code).toMatchSnapshot()\n  })\n\n  test('should work on eligible content (elements > 20)', () => {\n    const { code, ast } = compileWithStringify(\n      `<div><div>${repeat(\n        `<span/>`,\n        StringifyThresholds.NODE_COUNT,\n      )}</div></div>`,\n    )\n    // should be optimized now\n    expect(ast.cached).toMatchObject([\n      cachedArrayStaticNodeMatcher(\n        `<div>${repeat(`<span></span>`, StringifyThresholds.NODE_COUNT)}</div>`,\n        1,\n      ),\n    ])\n\n    expect(code).toMatchSnapshot()\n  })\n\n  test('should work for multiple adjacent nodes', () => {\n    const { ast, code } = compileWithStringify(\n      `<div>${repeat(\n        `<span class=\"foo\"/>`,\n        StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,\n      )}</div>`,\n    )\n    expect(ast.cached).toMatchObject([\n      cachedArrayStaticNodeMatcher(\n        repeat(\n          `<span class=\"foo\"></span>`,\n          StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,\n        ),\n        StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,\n      ),\n    ])\n\n    expect(code).toMatchSnapshot()\n  })\n\n  test('serializing constant bindings', () => {\n    const { ast, code } = compileWithStringify(\n      `<div><div :style=\"{ color: 'red' }\">${repeat(\n        `<span :class=\"[{ foo: true }, { bar: true }]\">{{ 1 }} + {{ false }}</span>`,\n        StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,\n      )}</div></div>`,\n    )\n    // should be optimized now\n    expect(ast.cached).toMatchObject([\n      cachedArrayStaticNodeMatcher(\n        `<div style=\"color:red;\">${repeat(\n          `<span class=\"foo bar\">1 + false</span>`,\n          StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,\n        )}</div>`,\n        1,\n      ),\n    ])\n    expect(code).toMatchSnapshot()\n  })\n\n  // #12391\n  test('serializing template string style', () => {\n    const { ast, code } = compileWithStringify(\n      `<div><div :style=\"\\`color:red;\\`\">${repeat(\n        `<span :class=\"[{ foo: true }, { bar: true }]\">{{ 1 }} + {{ false }}</span>`,\n        StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,\n      )}</div></div>`,\n    )\n    // should be optimized now\n    expect(ast.cached).toMatchObject([\n      cachedArrayStaticNodeMatcher(\n        `<div style=\"color:red;\">${repeat(\n          `<span class=\"foo bar\">1 + false</span>`,\n          StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,\n        )}</div>`,\n        1,\n      ),\n    ])\n    expect(code).toMatchSnapshot()\n  })\n\n  test('escape', () => {\n    const { ast, code } = compileWithStringify(\n      `<div><div>${repeat(\n        `<span :class=\"'foo' + '&gt;ar'\">{{ 1 }} + {{ '<' }}</span>` +\n          `<span>&amp;</span>`,\n        StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,\n      )}</div></div>`,\n    )\n    // should be optimized now\n    expect(ast.cached).toMatchObject([\n      cachedArrayStaticNodeMatcher(\n        `<div>${repeat(\n          `<span class=\"foo&gt;ar\">1 + &lt;</span>` + `<span>&amp;</span>`,\n          StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,\n        )}</div>`,\n        1,\n      ),\n    ])\n    expect(code).toMatchSnapshot()\n  })\n\n  test('should bail on bindings that are cached but not stringifiable', () => {\n    const { ast, code } = compile(\n      `<div><div>${repeat(\n        `<span class=\"foo\">foo</span>`,\n        StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,\n      )}<img src=\"./foo\" /></div></div>`,\n      {\n        hoistStatic: true,\n        prefixIdentifiers: true,\n        transformHoist: stringifyStatic,\n        nodeTransforms: [\n          node => {\n            if (node.type === NodeTypes.ELEMENT && node.tag === 'img') {\n              const exp = createSimpleExpression(\n                '_imports_0_',\n                false,\n                node.loc,\n                ConstantTypes.CAN_CACHE,\n              )\n              node.props[0] = {\n                type: NodeTypes.DIRECTIVE,\n                name: 'bind',\n                arg: createSimpleExpression('src', true),\n                exp,\n                modifiers: [],\n                loc: node.loc,\n              }\n            }\n          },\n        ],\n      },\n    )\n    expect(ast.cached).toMatchObject([cachedArrayBailedMatcher()])\n    expect(code).toMatchSnapshot()\n  })\n\n  test('should work with bindings that are non-static but stringifiable', () => {\n    // if a binding is non-static but marked as CAN_STRINGIFY, it means it's\n    // a known reference to a constant string.\n    const { ast, code } = compile(\n      `<div><div>${repeat(\n        `<span class=\"foo\">foo</span>`,\n        StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,\n      )}<img src=\"./foo\" /></div></div>`,\n      {\n        hoistStatic: true,\n        prefixIdentifiers: true,\n        transformHoist: stringifyStatic,\n        nodeTransforms: [\n          node => {\n            if (node.type === NodeTypes.ELEMENT && node.tag === 'img') {\n              const exp = createSimpleExpression(\n                '_imports_0_',\n                false,\n                node.loc,\n                ConstantTypes.CAN_STRINGIFY,\n              )\n              node.props[0] = {\n                type: NodeTypes.DIRECTIVE,\n                name: 'bind',\n                arg: createSimpleExpression('src', true),\n                exp,\n                modifiers: [],\n                loc: node.loc,\n              }\n            }\n          },\n        ],\n      },\n    )\n    expect(ast.cached).toMatchObject([cachedArraySuccessMatcher()])\n    expect(code).toMatchSnapshot()\n  })\n\n  // #1128\n  test('should bail on non-attribute bindings', () => {\n    const { ast } = compileWithStringify(\n      `<div><div><input indeterminate>${repeat(\n        `<span class=\"foo\">foo</span>`,\n        StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,\n      )}</div></div>`,\n    )\n    expect(ast.cached).toMatchObject([cachedArrayBailedMatcher()])\n\n    const { ast: ast2 } = compileWithStringify(\n      `<div><div><input :indeterminate=\"true\">${repeat(\n        `<span class=\"foo\">foo</span>`,\n        StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,\n      )}</div></div>`,\n    )\n    expect(ast2.cached).toMatchObject([cachedArrayBailedMatcher()])\n\n    const { ast: ast3 } = compileWithStringify(\n      `<div><div>${repeat(\n        `<span class=\"foo\">foo</span>`,\n        StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,\n      )}<input indeterminate></div></div>`,\n    )\n    expect(ast3.cached).toMatchObject([cachedArrayBailedMatcher()])\n\n    const { ast: ast4 } = compileWithStringify(\n      `<div><div>${repeat(\n        `<span class=\"foo\">foo</span>`,\n        StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,\n      )}<input :indeterminate=\"true\"></div></div>`,\n    )\n    expect(ast4.cached).toMatchObject([cachedArrayBailedMatcher()])\n  })\n\n  test('should bail on tags that has placement constraints (eg.tables related tags)', () => {\n    const { ast } = compileWithStringify(\n      `<table><tbody>${repeat(\n        `<tr class=\"foo\"><td>foo</td></tr>`,\n        StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,\n      )}</tbody></table>`,\n    )\n    expect(ast.cached).toMatchObject([cachedArrayBailedMatcher()])\n  })\n\n  test('should bail inside slots', () => {\n    const { ast } = compileWithStringify(\n      `<foo>${repeat(\n        `<div class=\"foo\"></div>`,\n        StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,\n      )}</foo>`,\n    )\n    expect(ast.cached).toMatchObject([\n      cachedArrayBailedMatcher(StringifyThresholds.ELEMENT_WITH_BINDING_COUNT),\n    ])\n\n    const { ast: ast2 } = compileWithStringify(\n      `<foo><template #foo>${repeat(\n        `<div class=\"foo\"></div>`,\n        StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,\n      )}</template></foo>`,\n    )\n    expect(ast2.cached).toMatchObject([\n      cachedArrayBailedMatcher(StringifyThresholds.ELEMENT_WITH_BINDING_COUNT),\n    ])\n  })\n\n  test('should remove attribute for `null`', () => {\n    const { ast } = compileWithStringify(\n      `<div>${repeat(\n        `<span :title=\"null\"></span>`,\n        StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,\n      )}</div>`,\n    )\n\n    expect(ast.cached).toMatchObject([\n      cachedArrayStaticNodeMatcher(\n        repeat(`<span></span>`, StringifyThresholds.ELEMENT_WITH_BINDING_COUNT),\n        StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,\n      ),\n    ])\n  })\n\n  // #6617\n  test('should remove boolean attribute for `false`', () => {\n    const { ast } = compileWithStringify(\n      `<button :disabled=\"false\">enable</button>${repeat(\n        `<div></div>`,\n        StringifyThresholds.NODE_COUNT,\n      )}`,\n    )\n    expect(ast.cached).toMatchObject([\n      {\n        type: NodeTypes.JS_CACHE_EXPRESSION,\n        value: {\n          type: NodeTypes.JS_CALL_EXPRESSION,\n          callee: CREATE_STATIC,\n          arguments: [\n            JSON.stringify(\n              `<button>enable</button>${repeat(\n                `<div></div>`,\n                StringifyThresholds.NODE_COUNT,\n              )}`,\n            ),\n            '21',\n          ],\n        },\n      },\n    ])\n  })\n\n  test('should stringify svg', () => {\n    const svg = `<svg width=\"50\" height=\"50\" viewBox=\"0 0 50 50\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">`\n    const repeated = `<rect width=\"50\" height=\"50\" fill=\"#C4C4C4\"></rect>`\n    const { ast } = compileWithStringify(\n      `<div>${svg}${repeat(\n        repeated,\n        StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,\n      )}</svg></div>`,\n    )\n\n    expect(ast.cached).toMatchObject([\n      cachedArrayStaticNodeMatcher(\n        `${svg}${repeat(\n          repeated,\n          StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,\n        )}</svg>`,\n        1,\n      ),\n    ])\n  })\n\n  test('should stringify mathML', () => {\n    const math = `<math xmlns=\"http://www.w3.org/1998/Math/MathML\">`\n    const repeated = `<ms>1</ms>`\n    const { ast } = compileWithStringify(\n      `<div>${math}${repeat(\n        repeated,\n        StringifyThresholds.NODE_COUNT,\n      )}</math></div>`,\n    )\n\n    expect(ast.cached).toMatchObject([\n      cachedArrayStaticNodeMatcher(\n        `${math}${repeat(repeated, StringifyThresholds.NODE_COUNT)}</math>`,\n        1,\n      ),\n    ])\n  })\n\n  // #5439\n  test('stringify v-html', () => {\n    const { code } = compileWithStringify(`\n      <pre  data-type=\"js\"><code v-html=\"'&lt;span&gt;show-it &lt;/span&gt;'\"></code></pre>\n      <div class>\n        <span class>1</span><span class>2</span>\n      </div>`)\n    expect(code).toMatch(`<code><span>show-it </span></code>`)\n    expect(code).toMatchSnapshot()\n  })\n\n  test('stringify v-text', () => {\n    const { code } = compileWithStringify(`\n      <pre  data-type=\"js\"><code v-text=\"'&lt;span&gt;show-it &lt;/span&gt;'\"></code></pre>\n      <div class>\n        <span class>1</span><span class>2</span>\n      </div>`)\n    expect(code).toMatch(`<code>&lt;span&gt;show-it &lt;/span&gt;</code>`)\n    expect(code).toMatchSnapshot()\n  })\n\n  test('stringify v-text with escape', () => {\n    const { code } = compileWithStringify(`\n      <pre  data-type=\"js\"><code v-text=\"\n                \\`text1\\`\"></code></pre>\n      <div class>\n        <span class>1</span><span class>2</span>\n      </div>`)\n    expect(code).toMatch(`<code>text1</code>`)\n    expect(code).toMatchSnapshot()\n  })\n\n  test('should work for <option> elements with string values', () => {\n    const { ast, code } = compileWithStringify(\n      `<div><select>${repeat(\n        `<option value=\"1\" />`,\n        StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,\n      )}</select></div>`,\n    )\n    // should be optimized now\n    expect(ast.cached).toMatchObject([\n      cachedArrayStaticNodeMatcher(\n        `<select>${repeat(\n          `<option value=\"1\"></option>`,\n          StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,\n        )}</select>`,\n        1,\n      ),\n    ])\n    expect(code).toMatchSnapshot()\n  })\n\n  test('should bail for <option> elements with number values', () => {\n    const { ast, code } = compileWithStringify(\n      `<div><select>${repeat(\n        `<option :value=\"1\" />`,\n        StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,\n      )}</select></div>`,\n    )\n    expect(ast.cached).toMatchObject([cachedArrayBailedMatcher()])\n    expect(code).toMatchSnapshot()\n  })\n\n  test('should bail for comments', () => {\n    const { code } = compileWithStringify(\n      `<!-- Comment 1 --><div class=\"a\"><!-- Comment 2 -->${repeat(\n        `<span class=\"b\"/>`,\n        StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,\n      )}</div>`,\n    )\n    expect(code).toMatchSnapshot()\n  })\n\n  test('should bail for <option> elements with null values', () => {\n    const { ast, code } = compileWithStringify(\n      `<div><select><option :value=\"null\" />${repeat(\n        `<option value=\"1\" />`,\n        StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,\n      )}</select></div>`,\n    )\n    expect(ast.cached).toMatchObject([cachedArrayBailedMatcher()])\n    expect(code).toMatchSnapshot()\n  })\n\n  test('eligible content (elements > 20) + non-eligible content', () => {\n    const { code } = compileWithStringify(\n      `<div>${repeat(\n        `<span/>`,\n        StringifyThresholds.NODE_COUNT,\n      )}<div key=\"1\">1</div>${repeat(\n        `<span/>`,\n        StringifyThresholds.NODE_COUNT,\n      )}</div>`,\n    )\n\n    expect(code).toMatchSnapshot()\n  })\n\n  test('eligible content + v-once node', () => {\n    const { code } = compileWithStringify(\n      `<div>\n        <div v-once>{{ msg }}</div>\n        ${repeat(`<span class=\"foo\">foo</span>`, StringifyThresholds.ELEMENT_WITH_BINDING_COUNT)}\n      </div>`,\n    )\n    expect(code).toMatchSnapshot()\n  })\n})\n"
  },
  {
    "path": "packages/compiler-dom/__tests__/transforms/transformStyle.spec.ts",
    "content": "import {\n  type CompilerOptions,\n  type ElementNode,\n  NodeTypes,\n  type VNodeCall,\n  baseParse as parse,\n  transform,\n} from '@vue/compiler-core'\nimport { transformBind } from '../../../compiler-core/src/transforms/vBind'\nimport { transformElement } from '../../../compiler-core/src/transforms/transformElement'\nimport { transformStyle } from '../../src/transforms/transformStyle'\n\nfunction transformWithStyleTransform(\n  template: string,\n  options: CompilerOptions = {},\n) {\n  const ast = parse(template)\n  transform(ast, {\n    nodeTransforms: [transformStyle],\n    ...options,\n  })\n  return {\n    root: ast,\n    node: ast.children[0] as ElementNode,\n  }\n}\n\ndescribe('compiler: style transform', () => {\n  test('should transform into directive node', () => {\n    const { node } = transformWithStyleTransform(`<div style=\"color: red\"/>`)\n    expect(node.props[0]).toMatchObject({\n      type: NodeTypes.DIRECTIVE,\n      name: `bind`,\n      arg: {\n        type: NodeTypes.SIMPLE_EXPRESSION,\n        content: `style`,\n        isStatic: true,\n      },\n      exp: {\n        type: NodeTypes.SIMPLE_EXPRESSION,\n        content: `{\"color\":\"red\"}`,\n        isStatic: false,\n      },\n    })\n  })\n\n  test('working with v-bind transform', () => {\n    const { node } = transformWithStyleTransform(`<div style=\"color: red\"/>`, {\n      nodeTransforms: [transformStyle, transformElement],\n      directiveTransforms: {\n        bind: transformBind,\n      },\n    })\n    expect((node.codegenNode as VNodeCall).props).toMatchObject({\n      type: NodeTypes.JS_OBJECT_EXPRESSION,\n      properties: [\n        {\n          key: {\n            type: NodeTypes.SIMPLE_EXPRESSION,\n            content: `style`,\n            isStatic: true,\n          },\n          value: {\n            type: NodeTypes.SIMPLE_EXPRESSION,\n            content: `{\"color\":\"red\"}`,\n            isStatic: false,\n          },\n        },\n      ],\n    })\n    // should not cause the STYLE patchFlag to be attached\n    expect((node.codegenNode as VNodeCall).patchFlag).toBeUndefined()\n  })\n})\n"
  },
  {
    "path": "packages/compiler-dom/__tests__/transforms/vHtml.spec.ts",
    "content": "import {\n  type CompilerOptions,\n  type PlainElementNode,\n  baseParse as parse,\n  transform,\n} from '@vue/compiler-core'\nimport { transformVHtml } from '../../src/transforms/vHtml'\nimport { transformElement } from '../../../compiler-core/src/transforms/transformElement'\nimport { createObjectMatcher } from '../../../compiler-core/__tests__/testUtils'\nimport { PatchFlags } from '@vue/shared'\nimport { DOMErrorCodes } from '../../src/errors'\n\nfunction transformWithVHtml(template: string, options: CompilerOptions = {}) {\n  const ast = parse(template)\n  transform(ast, {\n    nodeTransforms: [transformElement],\n    directiveTransforms: {\n      html: transformVHtml,\n    },\n    ...options,\n  })\n  return ast\n}\n\ndescribe('compiler: v-html transform', () => {\n  it('should convert v-html to innerHTML', () => {\n    const ast = transformWithVHtml(`<div v-html=\"test\"/>`)\n    expect((ast.children[0] as PlainElementNode).codegenNode).toMatchObject({\n      tag: `\"div\"`,\n      props: createObjectMatcher({\n        innerHTML: `[test]`,\n      }),\n      children: undefined,\n      patchFlag: PatchFlags.PROPS,\n      dynamicProps: `[\"innerHTML\"]`,\n    })\n  })\n\n  it('should raise error and ignore children when v-html is present', () => {\n    const onError = vi.fn()\n    const ast = transformWithVHtml(`<div v-html=\"test\">hello</div>`, {\n      onError,\n    })\n    expect(onError.mock.calls).toMatchObject([\n      [{ code: DOMErrorCodes.X_V_HTML_WITH_CHILDREN }],\n    ])\n    expect((ast.children[0] as PlainElementNode).codegenNode).toMatchObject({\n      tag: `\"div\"`,\n      props: createObjectMatcher({\n        innerHTML: `[test]`,\n      }),\n      children: undefined, // <-- children should have been removed\n      patchFlag: PatchFlags.PROPS,\n      dynamicProps: `[\"innerHTML\"]`,\n    })\n  })\n\n  it('should raise error if has no expression', () => {\n    const onError = vi.fn()\n    transformWithVHtml(`<div v-html></div>`, {\n      onError,\n    })\n    expect(onError.mock.calls).toMatchObject([\n      [{ code: DOMErrorCodes.X_V_HTML_NO_EXPRESSION }],\n    ])\n  })\n})\n"
  },
  {
    "path": "packages/compiler-dom/__tests__/transforms/vModel.spec.ts",
    "content": "import {\n  type CompilerOptions,\n  generate,\n  baseParse as parse,\n  transform,\n  transformVBindShorthand,\n} from '@vue/compiler-core'\nimport { transformModel } from '../../src/transforms/vModel'\nimport { transformElement } from '../../../compiler-core/src/transforms/transformElement'\nimport { DOMErrorCodes } from '../../src/errors'\nimport {\n  V_MODEL_CHECKBOX,\n  V_MODEL_DYNAMIC,\n  V_MODEL_RADIO,\n  V_MODEL_SELECT,\n  V_MODEL_TEXT,\n} from '../../src/runtimeHelpers'\n\nfunction transformWithModel(template: string, options: CompilerOptions = {}) {\n  const ast = parse(template)\n  transform(ast, {\n    nodeTransforms: [transformVBindShorthand, transformElement],\n    directiveTransforms: {\n      model: transformModel,\n    },\n    ...options,\n  })\n  return ast\n}\n\ndescribe('compiler: transform v-model', () => {\n  test('simple expression', () => {\n    const root = transformWithModel('<input v-model=\"model\" />')\n\n    expect(root.helpers).toContain(V_MODEL_TEXT)\n    expect(generate(root).code).toMatchSnapshot()\n  })\n\n  test('simple expression for input (text)', () => {\n    const root = transformWithModel('<input type=\"text\" v-model=\"model\" />')\n\n    expect(root.helpers).toContain(V_MODEL_TEXT)\n    expect(generate(root).code).toMatchSnapshot()\n  })\n\n  test('simple expression for input (radio)', () => {\n    const root = transformWithModel('<input type=\"radio\" v-model=\"model\" />')\n\n    expect(root.helpers).toContain(V_MODEL_RADIO)\n    expect(generate(root).code).toMatchSnapshot()\n  })\n\n  test('simple expression for input (checkbox)', () => {\n    const root = transformWithModel('<input type=\"checkbox\" v-model=\"model\" />')\n\n    expect(root.helpers).toContain(V_MODEL_CHECKBOX)\n    expect(generate(root).code).toMatchSnapshot()\n  })\n\n  test('simple expression for input (dynamic type)', () => {\n    const root = transformWithModel('<input :type=\"foo\" v-model=\"model\" />')\n\n    expect(root.helpers).toContain(V_MODEL_DYNAMIC)\n    expect(generate(root).code).toMatchSnapshot()\n  })\n\n  // #13169\n  test('input with v-bind shorthand type after v-model should use dynamic model', () => {\n    const root = transformWithModel('<input v-model=\"model\" :type/>')\n\n    expect(root.helpers).toContain(V_MODEL_DYNAMIC)\n    expect(generate(root).code).toMatchSnapshot()\n  })\n\n  test('input w/ dynamic v-bind', () => {\n    const root = transformWithModel('<input v-bind=\"obj\" v-model=\"model\" />')\n\n    expect(root.helpers).toContain(V_MODEL_DYNAMIC)\n    expect(generate(root).code).toMatchSnapshot()\n\n    const root2 = transformWithModel(\n      '<input v-bind:[key]=\"val\" v-model=\"model\" />',\n    )\n    expect(root2.helpers).toContain(V_MODEL_DYNAMIC)\n    expect(generate(root2).code).toMatchSnapshot()\n  })\n\n  test('simple expression for select', () => {\n    const root = transformWithModel('<select v-model=\"model\" />')\n\n    expect(root.helpers).toContain(V_MODEL_SELECT)\n    expect(generate(root).code).toMatchSnapshot()\n  })\n\n  test('simple expression for textarea', () => {\n    const root = transformWithModel('<textarea v-model=\"model\" />')\n\n    expect(root.helpers).toContain(V_MODEL_TEXT)\n    expect(generate(root).code).toMatchSnapshot()\n  })\n\n  describe('errors', () => {\n    test('plain elements with argument', () => {\n      const onError = vi.fn()\n      transformWithModel('<input v-model:value=\"model\" />', { onError })\n\n      expect(onError).toHaveBeenCalledTimes(1)\n      expect(onError).toHaveBeenCalledWith(\n        expect.objectContaining({\n          code: DOMErrorCodes.X_V_MODEL_ARG_ON_ELEMENT,\n        }),\n      )\n    })\n\n    test('invalid element', () => {\n      const onError = vi.fn()\n      transformWithModel('<span v-model=\"model\" />', { onError })\n\n      expect(onError).toHaveBeenCalledTimes(1)\n      expect(onError).toHaveBeenCalledWith(\n        expect.objectContaining({\n          code: DOMErrorCodes.X_V_MODEL_ON_INVALID_ELEMENT,\n        }),\n      )\n    })\n\n    test('should allow usage on custom element', () => {\n      const onError = vi.fn()\n      const root = transformWithModel('<my-input v-model=\"model\" />', {\n        onError,\n        isCustomElement: tag => tag.startsWith('my-'),\n      })\n      expect(root.helpers).toContain(V_MODEL_TEXT)\n      expect(onError).not.toHaveBeenCalled()\n      expect(generate(root).code).toMatchSnapshot()\n    })\n\n    test('should raise error if used file input element', () => {\n      const onError = vi.fn()\n      transformWithModel(`<input type=\"file\" v-model=\"test\"/>`, {\n        onError,\n      })\n      expect(onError).toHaveBeenCalledWith(\n        expect.objectContaining({\n          code: DOMErrorCodes.X_V_MODEL_ON_FILE_INPUT_ELEMENT,\n        }),\n      )\n    })\n\n    test('should error on dynamic value binding alongside v-model', () => {\n      const onError = vi.fn()\n      transformWithModel(`<input v-model=\"test\" :value=\"test\" />`, {\n        onError,\n      })\n      expect(onError).toHaveBeenCalledWith(\n        expect.objectContaining({\n          code: DOMErrorCodes.X_V_MODEL_UNNECESSARY_VALUE,\n        }),\n      )\n    })\n\n    // #3596\n    test('should NOT error on static value binding alongside v-model', () => {\n      const onError = vi.fn()\n      transformWithModel(`<input v-model=\"test\" value=\"test\" />`, {\n        onError,\n      })\n      expect(onError).not.toHaveBeenCalled()\n    })\n  })\n\n  describe('modifiers', () => {\n    test('.number', () => {\n      const root = transformWithModel('<input  v-model.number=\"model\" />')\n\n      expect(generate(root).code).toMatchSnapshot()\n    })\n\n    test('.trim', () => {\n      const root = transformWithModel('<input  v-model.trim=\"model\" />')\n\n      expect(generate(root).code).toMatchSnapshot()\n    })\n\n    test('.lazy', () => {\n      const root = transformWithModel('<input  v-model.lazy=\"model\" />')\n\n      expect(generate(root).code).toMatchSnapshot()\n    })\n  })\n})\n"
  },
  {
    "path": "packages/compiler-dom/__tests__/transforms/vOn.spec.ts",
    "content": "import {\n  BindingTypes,\n  type CompilerOptions,\n  type ElementNode,\n  NodeTypes,\n  type ObjectExpression,\n  TO_HANDLER_KEY,\n  type VNodeCall,\n  helperNameMap,\n  baseParse as parse,\n  transform,\n} from '@vue/compiler-core'\nimport { transformOn } from '../../src/transforms/vOn'\nimport { V_ON_WITH_KEYS, V_ON_WITH_MODIFIERS } from '../../src/runtimeHelpers'\nimport { transformElement } from '../../../compiler-core/src/transforms/transformElement'\nimport { transformExpression } from '../../../compiler-core/src/transforms/transformExpression'\nimport { PatchFlags } from '@vue/shared'\n\nfunction parseWithVOn(template: string, options: CompilerOptions = {}) {\n  const ast = parse(template)\n  transform(ast, {\n    nodeTransforms: [transformExpression, transformElement],\n    directiveTransforms: {\n      on: transformOn,\n    },\n    ...options,\n  })\n  const node = (ast.children[0] as ElementNode).codegenNode as VNodeCall\n  return {\n    root: ast,\n    node,\n    props: (node.props as ObjectExpression).properties,\n  }\n}\n\ndescribe('compiler-dom: transform v-on', () => {\n  it('should support multiple modifiers w/ prefixIdentifiers: true', () => {\n    const {\n      props: [prop],\n    } = parseWithVOn(`<div @click.stop.prevent=\"test\"/>`, {\n      prefixIdentifiers: true,\n    })\n    expect(prop).toMatchObject({\n      type: NodeTypes.JS_PROPERTY,\n      value: {\n        callee: V_ON_WITH_MODIFIERS,\n        arguments: [{ content: '_ctx.test' }, '[\"stop\",\"prevent\"]'],\n      },\n    })\n  })\n\n  it('should support multiple events and modifiers options w/ prefixIdentifiers: true', () => {\n    const { props } = parseWithVOn(\n      `<div @click.stop=\"test\" @keyup.enter=\"test\" />`,\n      {\n        prefixIdentifiers: true,\n      },\n    )\n    const [clickProp, keyUpProp] = props\n\n    expect(props).toHaveLength(2)\n    expect(clickProp).toMatchObject({\n      type: NodeTypes.JS_PROPERTY,\n      value: {\n        callee: V_ON_WITH_MODIFIERS,\n        arguments: [{ content: '_ctx.test' }, '[\"stop\"]'],\n      },\n    })\n    expect(keyUpProp).toMatchObject({\n      type: NodeTypes.JS_PROPERTY,\n      value: {\n        callee: V_ON_WITH_KEYS,\n        arguments: [{ content: '_ctx.test' }, '[\"enter\"]'],\n      },\n    })\n  })\n\n  it('should support multiple modifiers and event options w/ prefixIdentifiers: true', () => {\n    const {\n      props: [prop],\n    } = parseWithVOn(`<div @click.stop.capture.once=\"test\"/>`, {\n      prefixIdentifiers: true,\n    })\n    expect(prop).toMatchObject({\n      type: NodeTypes.JS_PROPERTY,\n      key: {\n        content: `onClickCaptureOnce`,\n      },\n      value: {\n        callee: V_ON_WITH_MODIFIERS,\n        arguments: [{ content: '_ctx.test' }, '[\"stop\"]'],\n      },\n    })\n  })\n\n  it('should wrap keys guard for keyboard events or dynamic events', () => {\n    const {\n      props: [prop],\n    } = parseWithVOn(`<div @keydown.stop.capture.ctrl.a=\"test\"/>`, {\n      prefixIdentifiers: true,\n    })\n    expect(prop).toMatchObject({\n      type: NodeTypes.JS_PROPERTY,\n      key: {\n        content: `onKeydownCapture`,\n      },\n      value: {\n        callee: V_ON_WITH_KEYS,\n        arguments: [\n          {\n            callee: V_ON_WITH_MODIFIERS,\n            arguments: [{ content: '_ctx.test' }, '[\"stop\",\"ctrl\"]'],\n          },\n          '[\"a\"]',\n        ],\n      },\n    })\n  })\n\n  it('should not wrap keys guard if no key modifier is present', () => {\n    const {\n      props: [prop],\n    } = parseWithVOn(`<div @keyup.exact=\"test\"/>`, {\n      prefixIdentifiers: true,\n    })\n    expect(prop).toMatchObject({\n      type: NodeTypes.JS_PROPERTY,\n      value: {\n        callee: V_ON_WITH_MODIFIERS,\n        arguments: [{ content: '_ctx.test' }, '[\"exact\"]'],\n      },\n    })\n  })\n\n  it('should wrap keys guard for static key event w/ left/right modifiers', () => {\n    const {\n      props: [prop],\n    } = parseWithVOn(`<div @keyup.left=\"test\"/>`, {\n      prefixIdentifiers: true,\n    })\n    expect(prop).toMatchObject({\n      type: NodeTypes.JS_PROPERTY,\n      value: {\n        callee: V_ON_WITH_KEYS,\n        arguments: [{ content: '_ctx.test' }, '[\"left\"]'],\n      },\n    })\n  })\n\n  it('should wrap both for dynamic key event w/ left/right modifiers', () => {\n    const {\n      props: [prop],\n    } = parseWithVOn(`<div @[e].left=\"test\"/>`, {\n      prefixIdentifiers: true,\n    })\n    expect(prop).toMatchObject({\n      type: NodeTypes.JS_PROPERTY,\n      value: {\n        callee: V_ON_WITH_KEYS,\n        arguments: [\n          {\n            callee: V_ON_WITH_MODIFIERS,\n            arguments: [{ content: `_ctx.test` }, `[\"left\"]`],\n          },\n          '[\"left\"]',\n        ],\n      },\n    })\n  })\n\n  it('should not wrap normal guard if there is only keys guard', () => {\n    const {\n      props: [prop],\n    } = parseWithVOn(`<div @keyup.enter=\"test\"/>`, {\n      prefixIdentifiers: true,\n    })\n    expect(prop).toMatchObject({\n      type: NodeTypes.JS_PROPERTY,\n      value: {\n        callee: V_ON_WITH_KEYS,\n        arguments: [{ content: '_ctx.test' }, '[\"enter\"]'],\n      },\n    })\n  })\n\n  test('should transform click.right', () => {\n    const {\n      props: [prop],\n    } = parseWithVOn(`<div @click.right=\"test\"/>`)\n    expect(prop.key).toMatchObject({\n      type: NodeTypes.SIMPLE_EXPRESSION,\n      content: `onContextmenu`,\n    })\n\n    // dynamic\n    const {\n      props: [prop2],\n    } = parseWithVOn(`<div @[event].right=\"test\"/>`)\n    // (_toHandlerKey(event)).toLowerCase() === \"onclick\" ? \"onContextmenu\" : (_toHandlerKey(event))\n    expect(prop2.key).toMatchObject({\n      type: NodeTypes.COMPOUND_EXPRESSION,\n      children: [\n        `(`,\n        {\n          children: [\n            `_${helperNameMap[TO_HANDLER_KEY]}(`,\n            { content: 'event' },\n            `)`,\n          ],\n        },\n        `) === \"onClick\" ? \"onContextmenu\" : (`,\n        {\n          children: [\n            `_${helperNameMap[TO_HANDLER_KEY]}(`,\n            { content: 'event' },\n            `)`,\n          ],\n        },\n        `)`,\n      ],\n    })\n  })\n\n  test('should transform click.middle', () => {\n    const {\n      props: [prop],\n    } = parseWithVOn(`<div @click.middle=\"test\"/>`)\n    expect(prop.key).toMatchObject({\n      type: NodeTypes.SIMPLE_EXPRESSION,\n      content: `onMouseup`,\n    })\n\n    // dynamic\n    const {\n      props: [prop2],\n    } = parseWithVOn(`<div @[event].middle=\"test\"/>`)\n    // (_eventNaming(event)).toLowerCase() === \"onclick\" ? \"onMouseup\" : (_eventNaming(event))\n    expect(prop2.key).toMatchObject({\n      type: NodeTypes.COMPOUND_EXPRESSION,\n      children: [\n        `(`,\n        {\n          children: [\n            `_${helperNameMap[TO_HANDLER_KEY]}(`,\n            { content: 'event' },\n            `)`,\n          ],\n        },\n        `) === \"onClick\" ? \"onMouseup\" : (`,\n        {\n          children: [\n            `_${helperNameMap[TO_HANDLER_KEY]}(`,\n            { content: 'event' },\n            `)`,\n          ],\n        },\n        `)`,\n      ],\n    })\n  })\n\n  test('cache handler w/ modifiers', () => {\n    const {\n      root,\n      props: [prop],\n    } = parseWithVOn(`<div @keyup.enter.capture=\"foo\" />`, {\n      prefixIdentifiers: true,\n      cacheHandlers: true,\n    })\n    expect(root.cached.length).toBe(1)\n    // should not treat cached handler as dynamicProp, so it should have no\n    // dynamicProps flags and only the hydration flag\n    expect((root as any).children[0].codegenNode.patchFlag).toBe(\n      PatchFlags.NEED_HYDRATION,\n    )\n    expect(prop).toMatchObject({\n      key: {\n        content: `onKeyupCapture`,\n      },\n      value: {\n        type: NodeTypes.JS_CACHE_EXPRESSION,\n        index: 0,\n        value: {\n          type: NodeTypes.JS_CALL_EXPRESSION,\n          callee: V_ON_WITH_KEYS,\n        },\n      },\n    })\n  })\n\n  test('should not have PROPS patchFlag for constant v-on handlers with modifiers', () => {\n    const { node } = parseWithVOn(`<div @keydown.up=\"foo\" />`, {\n      prefixIdentifiers: true,\n      bindingMetadata: {\n        foo: BindingTypes.SETUP_CONST,\n      },\n      directiveTransforms: {\n        on: transformOn,\n      },\n    })\n    // should only have hydration flag\n    expect(node.patchFlag).toBe(PatchFlags.NEED_HYDRATION)\n  })\n})\n"
  },
  {
    "path": "packages/compiler-dom/__tests__/transforms/vShow.spec.ts",
    "content": "import {\n  type CompilerOptions,\n  generate,\n  baseParse as parse,\n  transform,\n} from '@vue/compiler-core'\nimport { transformElement } from '../../../compiler-core/src/transforms/transformElement'\nimport { transformShow } from '../../src/transforms/vShow'\nimport { DOMErrorCodes } from '../../src/errors'\n\nfunction transformWithShow(template: string, options: CompilerOptions = {}) {\n  const ast = parse(template)\n  transform(ast, {\n    nodeTransforms: [transformElement],\n    directiveTransforms: {\n      show: transformShow,\n    },\n    ...options,\n  })\n  return ast\n}\n\ndescribe('compiler: v-show transform', () => {\n  test('simple expression', () => {\n    const ast = transformWithShow(`<div v-show=\"a\"/>`)\n\n    expect(generate(ast).code).toMatchSnapshot()\n  })\n\n  test('should raise error if has no expression', () => {\n    const onError = vi.fn()\n    transformWithShow(`<div v-show/>`, { onError })\n\n    expect(onError).toHaveBeenCalledTimes(1)\n    expect(onError).toHaveBeenCalledWith(\n      expect.objectContaining({\n        code: DOMErrorCodes.X_V_SHOW_NO_EXPRESSION,\n      }),\n    )\n  })\n})\n"
  },
  {
    "path": "packages/compiler-dom/__tests__/transforms/vText.spec.ts",
    "content": "import {\n  type CompilerOptions,\n  type PlainElementNode,\n  baseParse as parse,\n  transform,\n} from '@vue/compiler-core'\nimport { transformVText } from '../../src/transforms/vText'\nimport { transformElement } from '../../../compiler-core/src/transforms/transformElement'\nimport { createObjectMatcher } from '../../../compiler-core/__tests__/testUtils'\nimport { PatchFlags } from '@vue/shared'\nimport { DOMErrorCodes } from '../../src/errors'\n\nfunction transformWithVText(template: string, options: CompilerOptions = {}) {\n  const ast = parse(template)\n  transform(ast, {\n    nodeTransforms: [transformElement],\n    directiveTransforms: {\n      text: transformVText,\n    },\n    ...options,\n  })\n  return ast\n}\n\ndescribe('compiler: v-text transform', () => {\n  it('should convert v-text to textContent', () => {\n    const ast = transformWithVText(`<div v-text=\"test\"/>`)\n    expect((ast.children[0] as PlainElementNode).codegenNode).toMatchObject({\n      tag: `\"div\"`,\n      props: createObjectMatcher({\n        textContent: {\n          arguments: [{ content: 'test' }],\n        },\n      }),\n      children: undefined,\n      patchFlag: PatchFlags.PROPS,\n      dynamicProps: `[\"textContent\"]`,\n    })\n  })\n\n  it('should raise error and ignore children when v-text is present', () => {\n    const onError = vi.fn()\n    const ast = transformWithVText(`<div v-text=\"test\">hello</div>`, {\n      onError,\n    })\n    expect(onError.mock.calls).toMatchObject([\n      [{ code: DOMErrorCodes.X_V_TEXT_WITH_CHILDREN }],\n    ])\n    expect((ast.children[0] as PlainElementNode).codegenNode).toMatchObject({\n      tag: `\"div\"`,\n      props: createObjectMatcher({\n        textContent: {\n          arguments: [{ content: 'test' }],\n        },\n      }),\n      children: undefined, // <-- children should have been removed\n      patchFlag: PatchFlags.PROPS,\n      dynamicProps: `[\"textContent\"]`,\n    })\n  })\n\n  it('should raise error if has no expression', () => {\n    const onError = vi.fn()\n    transformWithVText(`<div v-text></div>`, {\n      onError,\n    })\n    expect(onError.mock.calls).toMatchObject([\n      [{ code: DOMErrorCodes.X_V_TEXT_NO_EXPRESSION }],\n    ])\n  })\n})\n"
  },
  {
    "path": "packages/compiler-dom/__tests__/transforms/validateHtmlNesting.spec.ts",
    "content": "import { type CompilerError, compile } from '../../src'\nimport { isValidHTMLNesting } from '../../src/htmlNesting'\n\ndescribe('validate html nesting', () => {\n  it('should warn with p > div', () => {\n    let err: CompilerError | undefined\n    compile(`<p><div></div></p>`, {\n      onWarn: e => (err = e),\n    })\n    expect(err).toBeDefined()\n    expect(err!.message).toMatch(`<div> cannot be child of <p>`)\n  })\n\n  it('should not warn with select > hr', () => {\n    let err: CompilerError | undefined\n    compile(`<select><hr></select>`, {\n      onWarn: e => (err = e),\n    })\n    expect(err).toBeUndefined()\n  })\n\n  // #13318\n  it('should not warn when parent tag is template', () => {\n    let err: CompilerError | undefined\n    compile(`<template><tr/></template>`, {\n      onWarn: e => (err = e),\n    })\n    expect(err).toBeUndefined()\n  })\n})\n\n/**\n * Copied from https://github.com/MananTank/validate-html-nesting\n * with ISC license\n */\ndescribe('isValidHTMLNesting', () => {\n  test('form', () => {\n    // invalid\n    expect(isValidHTMLNesting('form', 'form')).toBe(false)\n\n    // valid\n    expect(isValidHTMLNesting('form', 'div')).toBe(true)\n    expect(isValidHTMLNesting('form', 'input')).toBe(true)\n    expect(isValidHTMLNesting('form', 'select')).toBe(true)\n    expect(isValidHTMLNesting('form', 'button')).toBe(true)\n    expect(isValidHTMLNesting('form', 'label')).toBe(true)\n    expect(isValidHTMLNesting('form', 'h1')).toBe(true)\n  })\n\n  test('p', () => {\n    // invalid\n    expect(isValidHTMLNesting('p', 'p')).toBe(false)\n    expect(isValidHTMLNesting('p', 'div')).toBe(false)\n    expect(isValidHTMLNesting('p', 'hr')).toBe(false)\n    expect(isValidHTMLNesting('p', 'blockquote')).toBe(false)\n    expect(isValidHTMLNesting('p', 'pre')).toBe(false)\n\n    // valid\n    expect(isValidHTMLNesting('p', 'a')).toBe(true)\n    expect(isValidHTMLNesting('p', 'span')).toBe(true)\n    expect(isValidHTMLNesting('p', 'abbr')).toBe(true)\n    expect(isValidHTMLNesting('p', 'button')).toBe(true)\n    expect(isValidHTMLNesting('p', 'b')).toBe(true)\n    expect(isValidHTMLNesting('p', 'i')).toBe(true)\n    expect(isValidHTMLNesting('p', 'input')).toBe(true)\n    expect(isValidHTMLNesting('p', 'label')).toBe(true)\n  })\n\n  test('a', () => {\n    // invalid\n    expect(isValidHTMLNesting('a', 'a')).toBe(false)\n\n    // valid\n    expect(isValidHTMLNesting('a', 'div')).toBe(true)\n    expect(isValidHTMLNesting('a', 'span')).toBe(true)\n  })\n\n  test('button', () => {\n    // invalid\n    expect(isValidHTMLNesting('button', 'button')).toBe(false)\n\n    // valid\n    expect(isValidHTMLNesting('button', 'div')).toBe(true)\n    expect(isValidHTMLNesting('button', 'span')).toBe(true)\n  })\n\n  test('table', () => {\n    // invalid\n    expect(isValidHTMLNesting('table', 'tr')).toBe(false)\n    expect(isValidHTMLNesting('table', 'table')).toBe(false)\n    expect(isValidHTMLNesting('table', 'td')).toBe(false)\n\n    // valid\n    expect(isValidHTMLNesting('table', 'thead')).toBe(true)\n    expect(isValidHTMLNesting('table', 'tbody')).toBe(true)\n    expect(isValidHTMLNesting('table', 'tfoot')).toBe(true)\n    expect(isValidHTMLNesting('table', 'caption')).toBe(true)\n    expect(isValidHTMLNesting('table', 'colgroup')).toBe(true)\n  })\n\n  test('td', () => {\n    // valid\n    expect(isValidHTMLNesting('td', 'span')).toBe(true)\n    expect(isValidHTMLNesting('tr', 'td')).toBe(true)\n\n    // invalid\n    expect(isValidHTMLNesting('td', 'td')).toBe(false)\n    expect(isValidHTMLNesting('div', 'td')).toBe(false)\n  })\n\n  test('tbody', () => {\n    // invalid\n    expect(isValidHTMLNesting('tbody', 'td')).toBe(false)\n\n    // valid\n    expect(isValidHTMLNesting('tbody', 'tr')).toBe(true)\n  })\n\n  test('tr', () => {\n    // invalid\n    expect(isValidHTMLNesting('tr', 'tr')).toBe(false)\n    expect(isValidHTMLNesting('table', 'tr')).toBe(false)\n\n    // valid\n    expect(isValidHTMLNesting('tbody', 'tr')).toBe(true)\n    expect(isValidHTMLNesting('thead', 'tr')).toBe(true)\n    expect(isValidHTMLNesting('tfoot', 'tr')).toBe(true)\n    expect(isValidHTMLNesting('tr', 'td')).toBe(true)\n    expect(isValidHTMLNesting('tr', 'th')).toBe(true)\n  })\n\n  test('li', () => {\n    // invalid\n    expect(isValidHTMLNesting('li', 'li')).toBe(false)\n    // valid\n    expect(isValidHTMLNesting('li', 'div')).toBe(true)\n    expect(isValidHTMLNesting('li', 'ul')).toBe(true)\n  })\n\n  test('headings', () => {\n    // invalid\n    expect(isValidHTMLNesting('h1', 'h1')).toBe(false)\n    expect(isValidHTMLNesting('h2', 'h1')).toBe(false)\n    expect(isValidHTMLNesting('h3', 'h1')).toBe(false)\n    expect(isValidHTMLNesting('h1', 'h6')).toBe(false)\n\n    // valid\n    expect(isValidHTMLNesting('h1', 'div')).toBe(true)\n  })\n\n  describe('SVG', () => {\n    test('svg', () => {\n      // invalid non-svg tags as children\n      expect(isValidHTMLNesting('svg', 'div')).toBe(false)\n      expect(isValidHTMLNesting('svg', 'img')).toBe(false)\n      expect(isValidHTMLNesting('svg', 'p')).toBe(false)\n      expect(isValidHTMLNesting('svg', 'h2')).toBe(false)\n      expect(isValidHTMLNesting('svg', 'span')).toBe(false)\n\n      // valid non-svg tags as children\n      expect(isValidHTMLNesting('svg', 'a')).toBe(true)\n      expect(isValidHTMLNesting('svg', 'textarea')).toBe(true)\n      expect(isValidHTMLNesting('svg', 'input')).toBe(true)\n      expect(isValidHTMLNesting('svg', 'select')).toBe(true)\n\n      // valid svg tags as children\n      expect(isValidHTMLNesting('svg', 'g')).toBe(true)\n      expect(isValidHTMLNesting('svg', 'ellipse')).toBe(true)\n      expect(isValidHTMLNesting('svg', 'feOffset')).toBe(true)\n    })\n\n    test('foreignObject', () => {\n      // valid\n      expect(isValidHTMLNesting('foreignObject', 'g')).toBe(true)\n      expect(isValidHTMLNesting('foreignObject', 'div')).toBe(true)\n      expect(isValidHTMLNesting('foreignObject', 'a')).toBe(true)\n      expect(isValidHTMLNesting('foreignObject', 'textarea')).toBe(true)\n    })\n\n    test('g', () => {\n      // valid\n      expect(isValidHTMLNesting('g', 'div')).toBe(true)\n      expect(isValidHTMLNesting('g', 'p')).toBe(true)\n      expect(isValidHTMLNesting('g', 'a')).toBe(true)\n      expect(isValidHTMLNesting('g', 'textarea')).toBe(true)\n      expect(isValidHTMLNesting('g', 'g')).toBe(true)\n    })\n\n    test('dl', () => {\n      // valid\n      expect(isValidHTMLNesting('dl', 'dt')).toBe(true)\n      expect(isValidHTMLNesting('dl', 'dd')).toBe(true)\n      expect(isValidHTMLNesting('dl', 'div')).toBe(true)\n      expect(isValidHTMLNesting('div', 'dt')).toBe(true)\n      expect(isValidHTMLNesting('div', 'dd')).toBe(true)\n\n      // invalid\n      expect(isValidHTMLNesting('span', 'dt')).toBe(false)\n      expect(isValidHTMLNesting('span', 'dd')).toBe(false)\n    })\n  })\n})\n"
  },
  {
    "path": "packages/compiler-dom/index.js",
    "content": "'use strict'\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./dist/compiler-dom.cjs.prod.js')\n} else {\n  module.exports = require('./dist/compiler-dom.cjs.js')\n}\n"
  },
  {
    "path": "packages/compiler-dom/package.json",
    "content": "{\n  \"name\": \"@vue/compiler-dom\",\n  \"version\": \"3.5.30\",\n  \"description\": \"@vue/compiler-dom\",\n  \"main\": \"index.js\",\n  \"module\": \"dist/compiler-dom.esm-bundler.js\",\n  \"types\": \"dist/compiler-dom.d.ts\",\n  \"unpkg\": \"dist/compiler-dom.global.js\",\n  \"jsdelivr\": \"dist/compiler-dom.global.js\",\n  \"files\": [\n    \"index.js\",\n    \"dist\"\n  ],\n  \"exports\": {\n    \".\": {\n      \"types\": \"./dist/compiler-dom.d.ts\",\n      \"node\": {\n        \"production\": \"./dist/compiler-dom.cjs.prod.js\",\n        \"development\": \"./dist/compiler-dom.cjs.js\",\n        \"default\": \"./index.js\"\n      },\n      \"module\": \"./dist/compiler-dom.esm-bundler.js\",\n      \"import\": \"./dist/compiler-dom.esm-bundler.js\",\n      \"require\": \"./index.js\"\n    },\n    \"./*\": \"./*\"\n  },\n  \"sideEffects\": false,\n  \"buildOptions\": {\n    \"name\": \"VueCompilerDOM\",\n    \"compat\": true,\n    \"formats\": [\n      \"esm-bundler\",\n      \"esm-browser\",\n      \"cjs\",\n      \"global\"\n    ]\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/vuejs/core.git\",\n    \"directory\": \"packages/compiler-dom\"\n  },\n  \"keywords\": [\n    \"vue\"\n  ],\n  \"author\": \"Evan You\",\n  \"license\": \"MIT\",\n  \"bugs\": {\n    \"url\": \"https://github.com/vuejs/core/issues\"\n  },\n  \"homepage\": \"https://github.com/vuejs/core/tree/main/packages/compiler-dom#readme\",\n  \"dependencies\": {\n    \"@vue/shared\": \"workspace:*\",\n    \"@vue/compiler-core\": \"workspace:*\"\n  }\n}\n"
  },
  {
    "path": "packages/compiler-dom/src/decodeHtmlBrowser.ts",
    "content": "/* eslint-disable no-restricted-globals */\n\nlet decoder: HTMLDivElement\n\nexport function decodeHtmlBrowser(raw: string, asAttr = false): string {\n  if (!decoder) {\n    decoder = document.createElement('div')\n  }\n  if (asAttr) {\n    decoder.innerHTML = `<div foo=\"${raw.replace(/\"/g, '&quot;')}\">`\n    return decoder.children[0].getAttribute('foo')!\n  } else {\n    decoder.innerHTML = raw\n    return decoder.textContent!\n  }\n}\n"
  },
  {
    "path": "packages/compiler-dom/src/errors.ts",
    "content": "import {\n  type CompilerError,\n  ErrorCodes,\n  type SourceLocation,\n  createCompilerError,\n} from '@vue/compiler-core'\n\nexport interface DOMCompilerError extends CompilerError {\n  code: DOMErrorCodes\n}\n\nexport function createDOMCompilerError(\n  code: DOMErrorCodes,\n  loc?: SourceLocation,\n) {\n  return createCompilerError(\n    code,\n    loc,\n    __DEV__ || !__BROWSER__ ? DOMErrorMessages : undefined,\n  ) as DOMCompilerError\n}\n\nexport enum DOMErrorCodes {\n  X_V_HTML_NO_EXPRESSION = 54 /* ErrorCodes.__EXTEND_POINT__ */,\n  X_V_HTML_WITH_CHILDREN,\n  X_V_TEXT_NO_EXPRESSION,\n  X_V_TEXT_WITH_CHILDREN,\n  X_V_MODEL_ON_INVALID_ELEMENT,\n  X_V_MODEL_ARG_ON_ELEMENT,\n  X_V_MODEL_ON_FILE_INPUT_ELEMENT,\n  X_V_MODEL_UNNECESSARY_VALUE,\n  X_V_SHOW_NO_EXPRESSION,\n  X_TRANSITION_INVALID_CHILDREN,\n  X_IGNORED_SIDE_EFFECT_TAG,\n  __EXTEND_POINT__,\n}\n\nif (__TEST__) {\n  // esbuild cannot infer enum increments if first value is from another\n  // file, so we have to manually keep them in sync. this check ensures it\n  // errors out if there are collisions.\n  if (DOMErrorCodes.X_V_HTML_NO_EXPRESSION < ErrorCodes.__EXTEND_POINT__) {\n    throw new Error(\n      `DOMErrorCodes need to be updated to ${\n        ErrorCodes.__EXTEND_POINT__\n      } to match extension point from core ErrorCodes.`,\n    )\n  }\n}\n\nexport const DOMErrorMessages: { [code: number]: string } = {\n  [DOMErrorCodes.X_V_HTML_NO_EXPRESSION]: `v-html is missing expression.`,\n  [DOMErrorCodes.X_V_HTML_WITH_CHILDREN]: `v-html will override element children.`,\n  [DOMErrorCodes.X_V_TEXT_NO_EXPRESSION]: `v-text is missing expression.`,\n  [DOMErrorCodes.X_V_TEXT_WITH_CHILDREN]: `v-text will override element children.`,\n  [DOMErrorCodes.X_V_MODEL_ON_INVALID_ELEMENT]: `v-model can only be used on <input>, <textarea> and <select> elements.`,\n  [DOMErrorCodes.X_V_MODEL_ARG_ON_ELEMENT]: `v-model argument is not supported on plain elements.`,\n  [DOMErrorCodes.X_V_MODEL_ON_FILE_INPUT_ELEMENT]: `v-model cannot be used on file inputs since they are read-only. Use a v-on:change listener instead.`,\n  [DOMErrorCodes.X_V_MODEL_UNNECESSARY_VALUE]: `Unnecessary value binding used alongside v-model. It will interfere with v-model's behavior.`,\n  [DOMErrorCodes.X_V_SHOW_NO_EXPRESSION]: `v-show is missing expression.`,\n  [DOMErrorCodes.X_TRANSITION_INVALID_CHILDREN]: `<Transition> expects exactly one child element or component.`,\n  [DOMErrorCodes.X_IGNORED_SIDE_EFFECT_TAG]: `Tags with side effect (<script> and <style>) are ignored in client component templates.`,\n}\n"
  },
  {
    "path": "packages/compiler-dom/src/htmlNesting.ts",
    "content": "/**\n * Copied from https://github.com/MananTank/validate-html-nesting\n * with ISC license\n *\n * To avoid runtime dependency on validate-html-nesting\n * This file should not change very often in the original repo\n * but we may need to keep it up-to-date from time to time.\n */\n\n/**\n * returns true if given parent-child nesting is valid HTML\n */\nexport function isValidHTMLNesting(parent: string, child: string): boolean {\n  // if the parent is a template, it can have any child\n  if (parent === 'template') {\n    return true\n  }\n\n  // if we know the list of children that are the only valid children for the given parent\n  if (parent in onlyValidChildren) {\n    return onlyValidChildren[parent].has(child)\n  }\n\n  // if we know the list of parents that are the only valid parents for the given child\n  if (child in onlyValidParents) {\n    return onlyValidParents[child].has(parent)\n  }\n\n  // if we know the list of children that are NOT valid for the given parent\n  if (parent in knownInvalidChildren) {\n    // check if the child is in the list of invalid children\n    // if so, return false\n    if (knownInvalidChildren[parent].has(child)) return false\n  }\n\n  // if we know the list of parents that are NOT valid for the given child\n  if (child in knownInvalidParents) {\n    // check if the parent is in the list of invalid parents\n    // if so, return false\n    if (knownInvalidParents[child].has(parent)) return false\n  }\n\n  return true\n}\n\nconst headings = new Set(['h1', 'h2', 'h3', 'h4', 'h5', 'h6'])\nconst emptySet = new Set([])\n\n/**\n * maps element to set of elements that can be it's children, no other */\nconst onlyValidChildren: Record<string, Set<string>> = {\n  head: new Set([\n    'base',\n    'basefront',\n    'bgsound',\n    'link',\n    'meta',\n    'title',\n    'noscript',\n    'noframes',\n    'style',\n    'script',\n    'template',\n  ]),\n  optgroup: new Set(['option']),\n  select: new Set(['optgroup', 'option', 'hr']),\n  // table\n  table: new Set(['caption', 'colgroup', 'tbody', 'tfoot', 'thead']),\n  tr: new Set(['td', 'th']),\n  colgroup: new Set(['col']),\n  tbody: new Set(['tr']),\n  thead: new Set(['tr']),\n  tfoot: new Set(['tr']),\n  // these elements can not have any children elements\n  script: emptySet,\n  iframe: emptySet,\n  option: emptySet,\n  textarea: emptySet,\n  style: emptySet,\n  title: emptySet,\n}\n\n/** maps elements to set of elements which can be it's parent, no other */\nconst onlyValidParents: Record<string, Set<string>> = {\n  // sections\n  html: emptySet,\n  body: new Set(['html']),\n  head: new Set(['html']),\n  // table\n  td: new Set(['tr']),\n  colgroup: new Set(['table']),\n  caption: new Set(['table']),\n  tbody: new Set(['table']),\n  tfoot: new Set(['table']),\n  col: new Set(['colgroup']),\n  th: new Set(['tr']),\n  thead: new Set(['table']),\n  tr: new Set(['tbody', 'thead', 'tfoot']),\n  // data list\n  dd: new Set(['dl', 'div']),\n  dt: new Set(['dl', 'div']),\n  // other\n  figcaption: new Set(['figure']),\n  // li: new Set([\"ul\", \"ol\"]),\n  summary: new Set(['details']),\n  area: new Set(['map']),\n} as const\n\n/** maps element to set of elements that can not be it's children, others can */\nconst knownInvalidChildren: Record<string, Set<string>> = {\n  p: new Set([\n    'address',\n    'article',\n    'aside',\n    'blockquote',\n    'center',\n    'details',\n    'dialog',\n    'dir',\n    'div',\n    'dl',\n    'fieldset',\n    'figure',\n    'footer',\n    'form',\n    'h1',\n    'h2',\n    'h3',\n    'h4',\n    'h5',\n    'h6',\n    'header',\n    'hgroup',\n    'hr',\n    'li',\n    'main',\n    'nav',\n    'menu',\n    'ol',\n    'p',\n    'pre',\n    'section',\n    'table',\n    'ul',\n  ]),\n  svg: new Set([\n    'b',\n    'blockquote',\n    'br',\n    'code',\n    'dd',\n    'div',\n    'dl',\n    'dt',\n    'em',\n    'embed',\n    'h1',\n    'h2',\n    'h3',\n    'h4',\n    'h5',\n    'h6',\n    'hr',\n    'i',\n    'img',\n    'li',\n    'menu',\n    'meta',\n    'ol',\n    'p',\n    'pre',\n    'ruby',\n    's',\n    'small',\n    'span',\n    'strong',\n    'sub',\n    'sup',\n    'table',\n    'u',\n    'ul',\n    'var',\n  ]),\n} as const\n\n/** maps element to set of elements that can not be it's parent, others can */\nconst knownInvalidParents: Record<string, Set<string>> = {\n  a: new Set(['a']),\n  button: new Set(['button']),\n  dd: new Set(['dd', 'dt']),\n  dt: new Set(['dd', 'dt']),\n  form: new Set(['form']),\n  li: new Set(['li']),\n  h1: headings,\n  h2: headings,\n  h3: headings,\n  h4: headings,\n  h5: headings,\n  h6: headings,\n}\n"
  },
  {
    "path": "packages/compiler-dom/src/index.ts",
    "content": "import {\n  type CodegenResult,\n  type CompilerOptions,\n  type DirectiveTransform,\n  type NodeTransform,\n  type ParserOptions,\n  type RootNode,\n  baseCompile,\n  baseParse,\n  noopDirectiveTransform,\n} from '@vue/compiler-core'\nimport { parserOptions } from './parserOptions'\nimport { transformStyle } from './transforms/transformStyle'\nimport { transformVHtml } from './transforms/vHtml'\nimport { transformVText } from './transforms/vText'\nimport { transformModel } from './transforms/vModel'\nimport { transformOn } from './transforms/vOn'\nimport { transformShow } from './transforms/vShow'\nimport { transformTransition } from './transforms/Transition'\nimport { stringifyStatic } from './transforms/stringifyStatic'\nimport { ignoreSideEffectTags } from './transforms/ignoreSideEffectTags'\nimport { validateHtmlNesting } from './transforms/validateHtmlNesting'\nimport { extend } from '@vue/shared'\n\nexport { parserOptions }\n\nexport const DOMNodeTransforms: NodeTransform[] = [\n  transformStyle,\n  ...(__DEV__ ? [transformTransition, validateHtmlNesting] : []),\n]\n\nexport const DOMDirectiveTransforms: Record<string, DirectiveTransform> = {\n  cloak: noopDirectiveTransform,\n  html: transformVHtml,\n  text: transformVText,\n  model: transformModel, // override compiler-core\n  on: transformOn, // override compiler-core\n  show: transformShow,\n}\n\nexport function compile(\n  src: string | RootNode,\n  options: CompilerOptions = {},\n): CodegenResult {\n  return baseCompile(\n    src,\n    extend({}, parserOptions, options, {\n      nodeTransforms: [\n        // ignore <script> and <tag>\n        // this is not put inside DOMNodeTransforms because that list is used\n        // by compiler-ssr to generate vnode fallback branches\n        ignoreSideEffectTags,\n        ...DOMNodeTransforms,\n        ...(options.nodeTransforms || []),\n      ],\n      directiveTransforms: extend(\n        {},\n        DOMDirectiveTransforms,\n        options.directiveTransforms || {},\n      ),\n      transformHoist: __BROWSER__ ? null : stringifyStatic,\n    }),\n  )\n}\n\nexport function parse(template: string, options: ParserOptions = {}): RootNode {\n  return baseParse(template, extend({}, parserOptions, options))\n}\n\nexport * from './runtimeHelpers'\nexport { transformStyle } from './transforms/transformStyle'\nexport {\n  createDOMCompilerError,\n  DOMErrorCodes,\n  DOMErrorMessages,\n} from './errors'\nexport * from '@vue/compiler-core'\n"
  },
  {
    "path": "packages/compiler-dom/src/parserOptions.ts",
    "content": "import { Namespaces, NodeTypes, type ParserOptions } from '@vue/compiler-core'\nimport { isHTMLTag, isMathMLTag, isSVGTag, isVoidTag } from '@vue/shared'\nimport { TRANSITION, TRANSITION_GROUP } from './runtimeHelpers'\nimport { decodeHtmlBrowser } from './decodeHtmlBrowser'\n\nexport const parserOptions: ParserOptions = {\n  parseMode: 'html',\n  isVoidTag,\n  isNativeTag: tag => isHTMLTag(tag) || isSVGTag(tag) || isMathMLTag(tag),\n  isPreTag: tag => tag === 'pre',\n  isIgnoreNewlineTag: tag => tag === 'pre' || tag === 'textarea',\n  decodeEntities: __BROWSER__ ? decodeHtmlBrowser : undefined,\n\n  isBuiltInComponent: tag => {\n    if (tag === 'Transition' || tag === 'transition') {\n      return TRANSITION\n    } else if (tag === 'TransitionGroup' || tag === 'transition-group') {\n      return TRANSITION_GROUP\n    }\n  },\n\n  // https://html.spec.whatwg.org/multipage/parsing.html#tree-construction-dispatcher\n  getNamespace(tag, parent, rootNamespace) {\n    let ns = parent ? parent.ns : rootNamespace\n    if (parent && ns === Namespaces.MATH_ML) {\n      if (parent.tag === 'annotation-xml') {\n        if (tag === 'svg') {\n          return Namespaces.SVG\n        }\n        if (\n          parent.props.some(\n            a =>\n              a.type === NodeTypes.ATTRIBUTE &&\n              a.name === 'encoding' &&\n              a.value != null &&\n              (a.value.content === 'text/html' ||\n                a.value.content === 'application/xhtml+xml'),\n          )\n        ) {\n          ns = Namespaces.HTML\n        }\n      } else if (\n        /^m(?:[ions]|text)$/.test(parent.tag) &&\n        tag !== 'mglyph' &&\n        tag !== 'malignmark'\n      ) {\n        ns = Namespaces.HTML\n      }\n    } else if (parent && ns === Namespaces.SVG) {\n      if (\n        parent.tag === 'foreignObject' ||\n        parent.tag === 'desc' ||\n        parent.tag === 'title'\n      ) {\n        ns = Namespaces.HTML\n      }\n    }\n\n    if (ns === Namespaces.HTML) {\n      if (tag === 'svg') {\n        return Namespaces.SVG\n      }\n      if (tag === 'math') {\n        return Namespaces.MATH_ML\n      }\n    }\n    return ns\n  },\n}\n"
  },
  {
    "path": "packages/compiler-dom/src/runtimeHelpers.ts",
    "content": "import { registerRuntimeHelpers } from '@vue/compiler-core'\n\nexport const V_MODEL_RADIO: unique symbol = Symbol(__DEV__ ? `vModelRadio` : ``)\nexport const V_MODEL_CHECKBOX: unique symbol = Symbol(\n  __DEV__ ? `vModelCheckbox` : ``,\n)\nexport const V_MODEL_TEXT: unique symbol = Symbol(__DEV__ ? `vModelText` : ``)\nexport const V_MODEL_SELECT: unique symbol = Symbol(\n  __DEV__ ? `vModelSelect` : ``,\n)\nexport const V_MODEL_DYNAMIC: unique symbol = Symbol(\n  __DEV__ ? `vModelDynamic` : ``,\n)\n\nexport const V_ON_WITH_MODIFIERS: unique symbol = Symbol(\n  __DEV__ ? `vOnModifiersGuard` : ``,\n)\nexport const V_ON_WITH_KEYS: unique symbol = Symbol(\n  __DEV__ ? `vOnKeysGuard` : ``,\n)\n\nexport const V_SHOW: unique symbol = Symbol(__DEV__ ? `vShow` : ``)\n\nexport const TRANSITION: unique symbol = Symbol(__DEV__ ? `Transition` : ``)\nexport const TRANSITION_GROUP: unique symbol = Symbol(\n  __DEV__ ? `TransitionGroup` : ``,\n)\n\nregisterRuntimeHelpers({\n  [V_MODEL_RADIO]: `vModelRadio`,\n  [V_MODEL_CHECKBOX]: `vModelCheckbox`,\n  [V_MODEL_TEXT]: `vModelText`,\n  [V_MODEL_SELECT]: `vModelSelect`,\n  [V_MODEL_DYNAMIC]: `vModelDynamic`,\n  [V_ON_WITH_MODIFIERS]: `withModifiers`,\n  [V_ON_WITH_KEYS]: `withKeys`,\n  [V_SHOW]: `vShow`,\n  [TRANSITION]: `Transition`,\n  [TRANSITION_GROUP]: `TransitionGroup`,\n})\n"
  },
  {
    "path": "packages/compiler-dom/src/transforms/Transition.ts",
    "content": "import {\n  type ComponentNode,\n  ElementTypes,\n  type IfBranchNode,\n  type NodeTransform,\n  NodeTypes,\n  isCommentOrWhitespace,\n} from '@vue/compiler-core'\nimport { TRANSITION } from '../runtimeHelpers'\nimport { DOMErrorCodes, createDOMCompilerError } from '../errors'\n\nexport const transformTransition: NodeTransform = (node, context) => {\n  if (\n    node.type === NodeTypes.ELEMENT &&\n    node.tagType === ElementTypes.COMPONENT\n  ) {\n    const component = context.isBuiltInComponent(node.tag)\n    if (component === TRANSITION) {\n      return () => {\n        if (!node.children.length) {\n          return\n        }\n\n        // warn multiple transition children\n        if (hasMultipleChildren(node)) {\n          context.onError(\n            createDOMCompilerError(\n              DOMErrorCodes.X_TRANSITION_INVALID_CHILDREN,\n              {\n                start: node.children[0].loc.start,\n                end: node.children[node.children.length - 1].loc.end,\n                source: '',\n              },\n            ),\n          )\n        }\n\n        // check if it's a single child w/ v-show\n        // if yes, inject \"persisted: true\" to the transition props\n        const child = node.children[0]\n        if (child.type === NodeTypes.ELEMENT) {\n          for (const p of child.props) {\n            if (p.type === NodeTypes.DIRECTIVE && p.name === 'show') {\n              node.props.push({\n                type: NodeTypes.ATTRIBUTE,\n                name: 'persisted',\n                nameLoc: node.loc,\n                value: undefined,\n                loc: node.loc,\n              })\n            }\n          }\n        }\n      }\n    }\n  }\n}\n\nfunction hasMultipleChildren(node: ComponentNode | IfBranchNode): boolean {\n  // filter out potential comment nodes (#1352) and whitespace (#4637)\n  const children = (node.children = node.children.filter(\n    c => !isCommentOrWhitespace(c),\n  ))\n  const child = children[0]\n  return (\n    children.length !== 1 ||\n    child.type === NodeTypes.FOR ||\n    (child.type === NodeTypes.IF && child.branches.some(hasMultipleChildren))\n  )\n}\n"
  },
  {
    "path": "packages/compiler-dom/src/transforms/ignoreSideEffectTags.ts",
    "content": "import { ElementTypes, type NodeTransform, NodeTypes } from '@vue/compiler-core'\nimport { DOMErrorCodes, createDOMCompilerError } from '../errors'\n\nexport const ignoreSideEffectTags: NodeTransform = (node, context) => {\n  if (\n    node.type === NodeTypes.ELEMENT &&\n    node.tagType === ElementTypes.ELEMENT &&\n    (node.tag === 'script' || node.tag === 'style')\n  ) {\n    __DEV__ &&\n      context.onError(\n        createDOMCompilerError(\n          DOMErrorCodes.X_IGNORED_SIDE_EFFECT_TAG,\n          node.loc,\n        ),\n      )\n    context.removeNode()\n  }\n}\n"
  },
  {
    "path": "packages/compiler-dom/src/transforms/stringifyStatic.ts",
    "content": "/**\n * This module is Node-only.\n */\nimport {\n  CREATE_STATIC,\n  type CacheExpression,\n  ConstantTypes,\n  type ElementNode,\n  ElementTypes,\n  type ExpressionNode,\n  type HoistTransform,\n  Namespaces,\n  NodeTypes,\n  type PlainElementNode,\n  type SimpleExpressionNode,\n  type TemplateChildNode,\n  type TextCallNode,\n  type TransformContext,\n  createCallExpression,\n  findDir,\n  isStaticArgOf,\n} from '@vue/compiler-core'\nimport {\n  escapeHtml,\n  isArray,\n  isBooleanAttr,\n  isKnownHtmlAttr,\n  isKnownMathMLAttr,\n  isKnownSvgAttr,\n  isString,\n  isSymbol,\n  isVoidTag,\n  makeMap,\n  normalizeClass,\n  normalizeStyle,\n  stringifyStyle,\n  toDisplayString,\n} from '@vue/shared'\n\nexport enum StringifyThresholds {\n  ELEMENT_WITH_BINDING_COUNT = 5,\n  NODE_COUNT = 20,\n}\n\ntype StringifiableNode = PlainElementNode | TextCallNode\n\n/**\n * Regex for replacing placeholders for embedded constant variables\n * (e.g. import URL string constants generated by compiler-sfc)\n */\nconst expReplaceRE = /__VUE_EXP_START__(.*?)__VUE_EXP_END__/g\n\n/**\n * Turn eligible hoisted static trees into stringified static nodes, e.g.\n *\n * ```js\n * const _hoisted_1 = createStaticVNode(`<div class=\"foo\">bar</div>`)\n * ```\n *\n * A single static vnode can contain stringified content for **multiple**\n * consecutive nodes (element and plain text), called a \"chunk\".\n * `@vue/runtime-dom` will create the content via innerHTML in a hidden\n * container element and insert all the nodes in place. The call must also\n * provide the number of nodes contained in the chunk so that during hydration\n * we can know how many nodes the static vnode should adopt.\n *\n * The optimization scans a children list that contains hoisted nodes, and\n * tries to find the largest chunk of consecutive hoisted nodes before running\n * into a non-hoisted node or the end of the list. A chunk is then converted\n * into a single static vnode and replaces the hoisted expression of the first\n * node in the chunk. Other nodes in the chunk are considered \"merged\" and\n * therefore removed from both the hoist list and the children array.\n *\n * This optimization is only performed in Node.js.\n */\nexport const stringifyStatic: HoistTransform = (children, context, parent) => {\n  // bail stringification for slot content\n  if (context.scopes.vSlot > 0) {\n    return\n  }\n\n  const isParentCached =\n    parent.type === NodeTypes.ELEMENT &&\n    parent.codegenNode &&\n    parent.codegenNode.type === NodeTypes.VNODE_CALL &&\n    parent.codegenNode.children &&\n    !isArray(parent.codegenNode.children) &&\n    parent.codegenNode.children.type === NodeTypes.JS_CACHE_EXPRESSION\n\n  let nc = 0 // current node count\n  let ec = 0 // current element with binding count\n  const currentChunk: StringifiableNode[] = []\n\n  const stringifyCurrentChunk = (currentIndex: number): number => {\n    if (\n      nc >= StringifyThresholds.NODE_COUNT ||\n      ec >= StringifyThresholds.ELEMENT_WITH_BINDING_COUNT\n    ) {\n      // combine all currently eligible nodes into a single static vnode call\n      const staticCall = createCallExpression(context.helper(CREATE_STATIC), [\n        JSON.stringify(\n          currentChunk.map(node => stringifyNode(node, context)).join(''),\n        ).replace(expReplaceRE, `\" + $1 + \"`),\n        // the 2nd argument indicates the number of DOM nodes this static vnode\n        // will insert / hydrate\n        String(currentChunk.length),\n      ])\n\n      const deleteCount = currentChunk.length - 1\n\n      if (isParentCached) {\n        // if the parent is cached, then `children` is also the value of the\n        // CacheExpression. Just replace the corresponding range in the cached\n        // list with staticCall.\n        children.splice(\n          currentIndex - currentChunk.length,\n          currentChunk.length,\n          // @ts-expect-error\n          staticCall,\n        )\n      } else {\n        // replace the first node's hoisted expression with the static vnode call\n        ;(currentChunk[0].codegenNode as CacheExpression).value = staticCall\n        if (currentChunk.length > 1) {\n          // remove merged nodes from children\n          children.splice(currentIndex - currentChunk.length + 1, deleteCount)\n          // also adjust index for the remaining cache items\n          const cacheIndex = context.cached.indexOf(\n            currentChunk[currentChunk.length - 1]\n              .codegenNode as CacheExpression,\n          )\n          if (cacheIndex > -1) {\n            for (let i = cacheIndex; i < context.cached.length; i++) {\n              const c = context.cached[i]\n              if (c) c.index -= deleteCount\n            }\n            context.cached.splice(cacheIndex - deleteCount + 1, deleteCount)\n          }\n        }\n      }\n      return deleteCount\n    }\n    return 0\n  }\n\n  let i = 0\n  for (; i < children.length; i++) {\n    const child = children[i]\n    const isCached = isParentCached || getCachedNode(child)\n    if (isCached) {\n      // presence of cached means child must be a stringifiable node\n      const result = analyzeNode(child as StringifiableNode)\n      if (result) {\n        // node is stringifiable, record state\n        nc += result[0]\n        ec += result[1]\n        currentChunk.push(child as StringifiableNode)\n        continue\n      }\n    }\n    // we only reach here if we ran into a node that is not stringifiable\n    // check if currently analyzed nodes meet criteria for stringification.\n    // adjust iteration index\n    i -= stringifyCurrentChunk(i)\n    // reset state\n    nc = 0\n    ec = 0\n    currentChunk.length = 0\n  }\n  // in case the last node was also stringifiable\n  stringifyCurrentChunk(i)\n}\n\nconst getCachedNode = (\n  node: TemplateChildNode,\n): CacheExpression | undefined => {\n  if (\n    ((node.type === NodeTypes.ELEMENT &&\n      node.tagType === ElementTypes.ELEMENT) ||\n      node.type === NodeTypes.TEXT_CALL) &&\n    node.codegenNode &&\n    node.codegenNode.type === NodeTypes.JS_CACHE_EXPRESSION\n  ) {\n    return node.codegenNode\n  }\n}\n\nconst dataAriaRE = /^(?:data|aria)-/\nconst isStringifiableAttr = (name: string, ns: Namespaces) => {\n  return (\n    (ns === Namespaces.HTML\n      ? isKnownHtmlAttr(name)\n      : ns === Namespaces.SVG\n        ? isKnownSvgAttr(name)\n        : ns === Namespaces.MATH_ML\n          ? isKnownMathMLAttr(name)\n          : false) || dataAriaRE.test(name)\n  )\n}\n\nconst isNonStringifiable = /*@__PURE__*/ makeMap(\n  `caption,thead,tr,th,tbody,td,tfoot,colgroup,col`,\n)\n\n/**\n * for a cached node, analyze it and return:\n * - false: bailed (contains non-stringifiable props or runtime constant)\n * - [nc, ec] where\n *   - nc is the number of nodes inside\n *   - ec is the number of element with bindings inside\n */\nfunction analyzeNode(node: StringifiableNode): [number, number] | false {\n  if (node.type === NodeTypes.ELEMENT && isNonStringifiable(node.tag)) {\n    return false\n  }\n\n  // v-once nodes should not be stringified\n  if (node.type === NodeTypes.ELEMENT && findDir(node, 'once', true)) {\n    return false\n  }\n\n  if (node.type === NodeTypes.TEXT_CALL) {\n    return [1, 0]\n  }\n\n  let nc = 1 // node count\n  let ec = node.props.length > 0 ? 1 : 0 // element w/ binding count\n  let bailed = false\n  const bail = (): false => {\n    bailed = true\n    return false\n  }\n\n  // TODO: check for cases where using innerHTML will result in different\n  // output compared to imperative node insertions.\n  // probably only need to check for most common case\n  // i.e. non-phrasing-content tags inside `<p>`\n  function walk(node: ElementNode): boolean {\n    const isOptionTag = node.tag === 'option' && node.ns === Namespaces.HTML\n    for (let i = 0; i < node.props.length; i++) {\n      const p = node.props[i]\n      // bail on non-attr bindings\n      if (\n        p.type === NodeTypes.ATTRIBUTE &&\n        !isStringifiableAttr(p.name, node.ns)\n      ) {\n        return bail()\n      }\n      if (p.type === NodeTypes.DIRECTIVE && p.name === 'bind') {\n        // bail on non-attr bindings\n        if (\n          p.arg &&\n          (p.arg.type === NodeTypes.COMPOUND_EXPRESSION ||\n            (p.arg.isStatic && !isStringifiableAttr(p.arg.content, node.ns)))\n        ) {\n          return bail()\n        }\n        if (\n          p.exp &&\n          (p.exp.type === NodeTypes.COMPOUND_EXPRESSION ||\n            p.exp.constType < ConstantTypes.CAN_STRINGIFY)\n        ) {\n          return bail()\n        }\n        // <option :value=\"1\"> cannot be safely stringified\n        if (\n          isOptionTag &&\n          isStaticArgOf(p.arg, 'value') &&\n          p.exp &&\n          !p.exp.isStatic\n        ) {\n          return bail()\n        }\n      }\n    }\n    for (let i = 0; i < node.children.length; i++) {\n      nc++\n      const child = node.children[i]\n      if (child.type === NodeTypes.ELEMENT) {\n        if (child.props.length > 0) {\n          ec++\n        }\n        walk(child)\n        if (bailed) {\n          return false\n        }\n      }\n    }\n    return true\n  }\n\n  return walk(node) ? [nc, ec] : false\n}\n\nfunction stringifyNode(\n  node: string | TemplateChildNode,\n  context: TransformContext,\n): string {\n  if (isString(node)) {\n    return node\n  }\n  if (isSymbol(node)) {\n    return ``\n  }\n  switch (node.type) {\n    case NodeTypes.ELEMENT:\n      return stringifyElement(node, context)\n    case NodeTypes.TEXT:\n      return escapeHtml(node.content)\n    case NodeTypes.COMMENT:\n      return `<!--${escapeHtml(node.content)}-->`\n    case NodeTypes.INTERPOLATION:\n      return escapeHtml(toDisplayString(evaluateConstant(node.content)))\n    case NodeTypes.COMPOUND_EXPRESSION:\n      return escapeHtml(evaluateConstant(node))\n    case NodeTypes.TEXT_CALL:\n      return stringifyNode(node.content, context)\n    default:\n      // static trees will not contain if/for nodes\n      return ''\n  }\n}\n\nfunction stringifyElement(\n  node: ElementNode,\n  context: TransformContext,\n): string {\n  let res = `<${node.tag}`\n  let innerHTML = ''\n  for (let i = 0; i < node.props.length; i++) {\n    const p = node.props[i]\n    if (p.type === NodeTypes.ATTRIBUTE) {\n      res += ` ${p.name}`\n      if (p.value) {\n        res += `=\"${escapeHtml(p.value.content)}\"`\n      }\n    } else if (p.type === NodeTypes.DIRECTIVE) {\n      if (p.name === 'bind') {\n        const exp = p.exp as SimpleExpressionNode\n        if (exp.content[0] === '_') {\n          // internally generated string constant references\n          // e.g. imported URL strings via compiler-sfc transformAssetUrl plugin\n          res += ` ${\n            (p.arg as SimpleExpressionNode).content\n          }=\"__VUE_EXP_START__${exp.content}__VUE_EXP_END__\"`\n          continue\n        }\n        // #6568\n        if (\n          isBooleanAttr((p.arg as SimpleExpressionNode).content) &&\n          exp.content === 'false'\n        ) {\n          continue\n        }\n        // constant v-bind, e.g. :foo=\"1\"\n        let evaluated = evaluateConstant(exp)\n        if (evaluated != null) {\n          const arg = p.arg && (p.arg as SimpleExpressionNode).content\n          if (arg === 'class') {\n            evaluated = normalizeClass(evaluated)\n          } else if (arg === 'style') {\n            evaluated = stringifyStyle(normalizeStyle(evaluated))\n          }\n          res += ` ${(p.arg as SimpleExpressionNode).content}=\"${escapeHtml(\n            evaluated,\n          )}\"`\n        }\n      } else if (p.name === 'html') {\n        // #5439 v-html with constant value\n        // not sure why would anyone do this but it can happen\n        innerHTML = evaluateConstant(p.exp as SimpleExpressionNode)\n      } else if (p.name === 'text') {\n        innerHTML = escapeHtml(\n          toDisplayString(evaluateConstant(p.exp as SimpleExpressionNode)),\n        )\n      }\n    }\n  }\n  if (context.scopeId) {\n    res += ` ${context.scopeId}`\n  }\n  res += `>`\n  if (innerHTML) {\n    res += innerHTML\n  } else {\n    for (let i = 0; i < node.children.length; i++) {\n      res += stringifyNode(node.children[i], context)\n    }\n  }\n  if (!isVoidTag(node.tag)) {\n    res += `</${node.tag}>`\n  }\n  return res\n}\n\n// __UNSAFE__\n// Reason: eval.\n// It's technically safe to eval because only constant expressions are possible\n// here, e.g. `{{ 1 }}` or `{{ 'foo' }}`\n// in addition, constant exps bail on presence of parens so you can't even\n// run JSFuck in here. But we mark it unsafe for security review purposes.\n// (see compiler-core/src/transforms/transformExpression)\nfunction evaluateConstant(exp: ExpressionNode): string {\n  if (exp.type === NodeTypes.SIMPLE_EXPRESSION) {\n    return new Function(`return (${exp.content})`)()\n  } else {\n    // compound\n    let res = ``\n    exp.children.forEach(c => {\n      if (isString(c) || isSymbol(c)) {\n        return\n      }\n      if (c.type === NodeTypes.TEXT) {\n        res += c.content\n      } else if (c.type === NodeTypes.INTERPOLATION) {\n        res += toDisplayString(evaluateConstant(c.content))\n      } else {\n        res += evaluateConstant(c as ExpressionNode)\n      }\n    })\n    return res\n  }\n}\n"
  },
  {
    "path": "packages/compiler-dom/src/transforms/transformStyle.ts",
    "content": "import {\n  ConstantTypes,\n  type NodeTransform,\n  NodeTypes,\n  type SimpleExpressionNode,\n  type SourceLocation,\n  createSimpleExpression,\n} from '@vue/compiler-core'\nimport { parseStringStyle } from '@vue/shared'\n\n// Parse inline CSS strings for static style attributes into an object.\n// This is a NodeTransform since it works on the static `style` attribute and\n// converts it into a dynamic equivalent:\n// style=\"color: red\" -> :style='{ \"color\": \"red\" }'\n// It is then processed by `transformElement` and included in the generated\n// props.\nexport const transformStyle: NodeTransform = node => {\n  if (node.type === NodeTypes.ELEMENT) {\n    node.props.forEach((p, i) => {\n      if (p.type === NodeTypes.ATTRIBUTE && p.name === 'style' && p.value) {\n        // replace p with an expression node\n        node.props[i] = {\n          type: NodeTypes.DIRECTIVE,\n          name: `bind`,\n          arg: createSimpleExpression(`style`, true, p.loc),\n          exp: parseInlineCSS(p.value.content, p.loc),\n          modifiers: [],\n          loc: p.loc,\n        }\n      }\n    })\n  }\n}\n\nconst parseInlineCSS = (\n  cssText: string,\n  loc: SourceLocation,\n): SimpleExpressionNode => {\n  const normalized = parseStringStyle(cssText)\n  return createSimpleExpression(\n    JSON.stringify(normalized),\n    false,\n    loc,\n    ConstantTypes.CAN_STRINGIFY,\n  )\n}\n"
  },
  {
    "path": "packages/compiler-dom/src/transforms/vHtml.ts",
    "content": "import {\n  type DirectiveTransform,\n  createObjectProperty,\n  createSimpleExpression,\n} from '@vue/compiler-core'\nimport { DOMErrorCodes, createDOMCompilerError } from '../errors'\n\nexport const transformVHtml: DirectiveTransform = (dir, node, context) => {\n  const { exp, loc } = dir\n  if (!exp) {\n    context.onError(\n      createDOMCompilerError(DOMErrorCodes.X_V_HTML_NO_EXPRESSION, loc),\n    )\n  }\n  if (node.children.length) {\n    context.onError(\n      createDOMCompilerError(DOMErrorCodes.X_V_HTML_WITH_CHILDREN, loc),\n    )\n    node.children.length = 0\n  }\n  return {\n    props: [\n      createObjectProperty(\n        createSimpleExpression(`innerHTML`, true, loc),\n        exp || createSimpleExpression('', true),\n      ),\n    ],\n  }\n}\n"
  },
  {
    "path": "packages/compiler-dom/src/transforms/vModel.ts",
    "content": "import {\n  type DirectiveTransform,\n  ElementTypes,\n  NodeTypes,\n  transformModel as baseTransform,\n  findDir,\n  findProp,\n  hasDynamicKeyVBind,\n  isStaticArgOf,\n} from '@vue/compiler-core'\nimport { DOMErrorCodes, createDOMCompilerError } from '../errors'\nimport {\n  V_MODEL_CHECKBOX,\n  V_MODEL_DYNAMIC,\n  V_MODEL_RADIO,\n  V_MODEL_SELECT,\n  V_MODEL_TEXT,\n} from '../runtimeHelpers'\n\nexport const transformModel: DirectiveTransform = (dir, node, context) => {\n  const baseResult = baseTransform(dir, node, context)\n  // base transform has errors OR component v-model (only need props)\n  if (!baseResult.props.length || node.tagType === ElementTypes.COMPONENT) {\n    return baseResult\n  }\n\n  if (dir.arg) {\n    context.onError(\n      createDOMCompilerError(\n        DOMErrorCodes.X_V_MODEL_ARG_ON_ELEMENT,\n        dir.arg.loc,\n      ),\n    )\n  }\n\n  function checkDuplicatedValue() {\n    const value = findDir(node, 'bind')\n    if (value && isStaticArgOf(value.arg, 'value')) {\n      context.onError(\n        createDOMCompilerError(\n          DOMErrorCodes.X_V_MODEL_UNNECESSARY_VALUE,\n          value.loc,\n        ),\n      )\n    }\n  }\n\n  const { tag } = node\n  const isCustomElement = context.isCustomElement(tag)\n  if (\n    tag === 'input' ||\n    tag === 'textarea' ||\n    tag === 'select' ||\n    isCustomElement\n  ) {\n    let directiveToUse = V_MODEL_TEXT\n    let isInvalidType = false\n    if (tag === 'input' || isCustomElement) {\n      const type = findProp(node, `type`)\n      if (type) {\n        if (type.type === NodeTypes.DIRECTIVE) {\n          // :type=\"foo\"\n          directiveToUse = V_MODEL_DYNAMIC\n        } else if (type.value) {\n          switch (type.value.content) {\n            case 'radio':\n              directiveToUse = V_MODEL_RADIO\n              break\n            case 'checkbox':\n              directiveToUse = V_MODEL_CHECKBOX\n              break\n            case 'file':\n              isInvalidType = true\n              context.onError(\n                createDOMCompilerError(\n                  DOMErrorCodes.X_V_MODEL_ON_FILE_INPUT_ELEMENT,\n                  dir.loc,\n                ),\n              )\n              break\n            default:\n              // text type\n              __DEV__ && checkDuplicatedValue()\n              break\n          }\n        }\n      } else if (hasDynamicKeyVBind(node)) {\n        // element has bindings with dynamic keys, which can possibly contain\n        // \"type\".\n        directiveToUse = V_MODEL_DYNAMIC\n      } else {\n        // text type\n        __DEV__ && checkDuplicatedValue()\n      }\n    } else if (tag === 'select') {\n      directiveToUse = V_MODEL_SELECT\n    } else {\n      // textarea\n      __DEV__ && checkDuplicatedValue()\n    }\n    // inject runtime directive\n    // by returning the helper symbol via needRuntime\n    // the import will replaced a resolveDirective call.\n    if (!isInvalidType) {\n      baseResult.needRuntime = context.helper(directiveToUse)\n    }\n  } else {\n    context.onError(\n      createDOMCompilerError(\n        DOMErrorCodes.X_V_MODEL_ON_INVALID_ELEMENT,\n        dir.loc,\n      ),\n    )\n  }\n\n  // native vmodel doesn't need the `modelValue` props since they are also\n  // passed to the runtime as `binding.value`. removing it reduces code size.\n  baseResult.props = baseResult.props.filter(\n    p =>\n      !(\n        p.key.type === NodeTypes.SIMPLE_EXPRESSION &&\n        p.key.content === 'modelValue'\n      ),\n  )\n\n  return baseResult\n}\n"
  },
  {
    "path": "packages/compiler-dom/src/transforms/vOn.ts",
    "content": "import {\n  CompilerDeprecationTypes,\n  type DirectiveTransform,\n  type ExpressionNode,\n  NodeTypes,\n  type SimpleExpressionNode,\n  type SourceLocation,\n  type TransformContext,\n  transformOn as baseTransform,\n  checkCompatEnabled,\n  createCallExpression,\n  createCompoundExpression,\n  createObjectProperty,\n  createSimpleExpression,\n  isStaticExp,\n} from '@vue/compiler-core'\nimport { V_ON_WITH_KEYS, V_ON_WITH_MODIFIERS } from '../runtimeHelpers'\nimport { capitalize, makeMap } from '@vue/shared'\n\nconst isEventOptionModifier = /*@__PURE__*/ makeMap(`passive,once,capture`)\nconst isNonKeyModifier = /*@__PURE__*/ makeMap(\n  // event propagation management\n  `stop,prevent,self,` +\n    // system modifiers + exact\n    `ctrl,shift,alt,meta,exact,` +\n    // mouse\n    `middle`,\n)\n// left & right could be mouse or key modifiers based on event type\nconst maybeKeyModifier = /*@__PURE__*/ makeMap('left,right')\nconst isKeyboardEvent = /*@__PURE__*/ makeMap(`onkeyup,onkeydown,onkeypress`)\n\nconst resolveModifiers = (\n  key: ExpressionNode,\n  modifiers: SimpleExpressionNode[],\n  context: TransformContext,\n  loc: SourceLocation,\n) => {\n  const keyModifiers = []\n  const nonKeyModifiers = []\n  const eventOptionModifiers = []\n\n  for (let i = 0; i < modifiers.length; i++) {\n    const modifier = modifiers[i].content\n\n    if (\n      __COMPAT__ &&\n      modifier === 'native' &&\n      checkCompatEnabled(\n        CompilerDeprecationTypes.COMPILER_V_ON_NATIVE,\n        context,\n        loc,\n      )\n    ) {\n      eventOptionModifiers.push(modifier)\n    } else if (isEventOptionModifier(modifier)) {\n      // eventOptionModifiers: modifiers for addEventListener() options,\n      // e.g. .passive & .capture\n      eventOptionModifiers.push(modifier)\n    } else {\n      // runtimeModifiers: modifiers that needs runtime guards\n      if (maybeKeyModifier(modifier)) {\n        if (isStaticExp(key)) {\n          if (\n            isKeyboardEvent((key as SimpleExpressionNode).content.toLowerCase())\n          ) {\n            keyModifiers.push(modifier)\n          } else {\n            nonKeyModifiers.push(modifier)\n          }\n        } else {\n          keyModifiers.push(modifier)\n          nonKeyModifiers.push(modifier)\n        }\n      } else {\n        if (isNonKeyModifier(modifier)) {\n          nonKeyModifiers.push(modifier)\n        } else {\n          keyModifiers.push(modifier)\n        }\n      }\n    }\n  }\n\n  return {\n    keyModifiers,\n    nonKeyModifiers,\n    eventOptionModifiers,\n  }\n}\n\nconst transformClick = (key: ExpressionNode, event: string) => {\n  const isStaticClick =\n    isStaticExp(key) && key.content.toLowerCase() === 'onclick'\n  return isStaticClick\n    ? createSimpleExpression(event, true)\n    : key.type !== NodeTypes.SIMPLE_EXPRESSION\n      ? createCompoundExpression([\n          `(`,\n          key,\n          `) === \"onClick\" ? \"${event}\" : (`,\n          key,\n          `)`,\n        ])\n      : key\n}\n\nexport const transformOn: DirectiveTransform = (dir, node, context) => {\n  return baseTransform(dir, node, context, baseResult => {\n    const { modifiers } = dir\n    if (!modifiers.length) return baseResult\n\n    let { key, value: handlerExp } = baseResult.props[0]\n    const { keyModifiers, nonKeyModifiers, eventOptionModifiers } =\n      resolveModifiers(key, modifiers, context, dir.loc)\n\n    // normalize click.right and click.middle since they don't actually fire\n    if (nonKeyModifiers.includes('right')) {\n      key = transformClick(key, `onContextmenu`)\n    }\n    if (nonKeyModifiers.includes('middle')) {\n      key = transformClick(key, `onMouseup`)\n    }\n\n    if (nonKeyModifiers.length) {\n      handlerExp = createCallExpression(context.helper(V_ON_WITH_MODIFIERS), [\n        handlerExp,\n        JSON.stringify(nonKeyModifiers),\n      ])\n    }\n\n    if (\n      keyModifiers.length &&\n      // if event name is dynamic, always wrap with keys guard\n      (!isStaticExp(key) || isKeyboardEvent(key.content.toLowerCase()))\n    ) {\n      handlerExp = createCallExpression(context.helper(V_ON_WITH_KEYS), [\n        handlerExp,\n        JSON.stringify(keyModifiers),\n      ])\n    }\n\n    if (eventOptionModifiers.length) {\n      const modifierPostfix = eventOptionModifiers.map(capitalize).join('')\n      key = isStaticExp(key)\n        ? createSimpleExpression(`${key.content}${modifierPostfix}`, true)\n        : createCompoundExpression([`(`, key, `) + \"${modifierPostfix}\"`])\n    }\n\n    return {\n      props: [createObjectProperty(key, handlerExp)],\n    }\n  })\n}\n"
  },
  {
    "path": "packages/compiler-dom/src/transforms/vShow.ts",
    "content": "import type { DirectiveTransform } from '@vue/compiler-core'\nimport { DOMErrorCodes, createDOMCompilerError } from '../errors'\nimport { V_SHOW } from '../runtimeHelpers'\n\nexport const transformShow: DirectiveTransform = (dir, node, context) => {\n  const { exp, loc } = dir\n  if (!exp) {\n    context.onError(\n      createDOMCompilerError(DOMErrorCodes.X_V_SHOW_NO_EXPRESSION, loc),\n    )\n  }\n\n  return {\n    props: [],\n    needRuntime: context.helper(V_SHOW),\n  }\n}\n"
  },
  {
    "path": "packages/compiler-dom/src/transforms/vText.ts",
    "content": "import {\n  type DirectiveTransform,\n  TO_DISPLAY_STRING,\n  createCallExpression,\n  createObjectProperty,\n  createSimpleExpression,\n  getConstantType,\n} from '@vue/compiler-core'\nimport { DOMErrorCodes, createDOMCompilerError } from '../errors'\n\nexport const transformVText: DirectiveTransform = (dir, node, context) => {\n  const { exp, loc } = dir\n  if (!exp) {\n    context.onError(\n      createDOMCompilerError(DOMErrorCodes.X_V_TEXT_NO_EXPRESSION, loc),\n    )\n  }\n  if (node.children.length) {\n    context.onError(\n      createDOMCompilerError(DOMErrorCodes.X_V_TEXT_WITH_CHILDREN, loc),\n    )\n    node.children.length = 0\n  }\n  return {\n    props: [\n      createObjectProperty(\n        createSimpleExpression(`textContent`, true),\n        exp\n          ? getConstantType(exp, context) > 0\n            ? exp\n            : createCallExpression(\n                context.helperString(TO_DISPLAY_STRING),\n                [exp],\n                loc,\n              )\n          : createSimpleExpression('', true),\n      ),\n    ],\n  }\n}\n"
  },
  {
    "path": "packages/compiler-dom/src/transforms/validateHtmlNesting.ts",
    "content": "import {\n  type CompilerError,\n  ElementTypes,\n  type NodeTransform,\n  NodeTypes,\n} from '@vue/compiler-core'\nimport { isValidHTMLNesting } from '../htmlNesting'\n\nexport const validateHtmlNesting: NodeTransform = (node, context) => {\n  if (\n    node.type === NodeTypes.ELEMENT &&\n    node.tagType === ElementTypes.ELEMENT &&\n    context.parent &&\n    context.parent.type === NodeTypes.ELEMENT &&\n    context.parent.tagType === ElementTypes.ELEMENT &&\n    !isValidHTMLNesting(context.parent.tag, node.tag)\n  ) {\n    const error = new SyntaxError(\n      `<${node.tag}> cannot be child of <${context.parent.tag}>, ` +\n        'according to HTML specifications. ' +\n        'This can cause hydration errors or ' +\n        'potentially disrupt future functionality.',\n    ) as CompilerError\n    error.loc = node.loc\n    context.onWarn(error)\n  }\n}\n"
  },
  {
    "path": "packages/compiler-sfc/LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2018-present, Yuxi (Evan) You\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "packages/compiler-sfc/README.md",
    "content": "# @vue/compiler-sfc\n\n> Lower level utilities for compiling Vue Single File Components\n\n**Note: as of 3.2.13+, this package is included as a dependency of the main `vue` package and can be accessed as `vue/compiler-sfc`. This means you no longer need to explicitly install this package and ensure its version matches that of `vue`'s. Just use the main `vue/compiler-sfc` deep import instead.**\n\nThis package contains lower level utilities that you can use if you are writing a plugin / transform for a bundler or module system that compiles Vue Single File Components (SFCs) into JavaScript. It is used in [vue-loader](https://github.com/vuejs/vue-loader) and [@vitejs/plugin-vue](https://github.com/vitejs/vite-plugin-vue/tree/main/packages/plugin-vue).\n\n## API\n\nThe API is intentionally low-level due to the various considerations when integrating Vue SFCs in a build system:\n\n- Separate hot-module replacement (HMR) for script, template and styles\n  - template updates should not reset component state\n  - style updates should be performed without component re-render\n\n- Leveraging the tool's plugin system for pre-processor handling. e.g. `<style lang=\"scss\">` should be processed by the corresponding webpack loader.\n\n- In some cases, transformers of each block in an SFC do not share the same execution context. For example, when used with `thread-loader` or other parallelized configurations, the template sub-loader in `vue-loader` may not have access to the full SFC and its descriptor.\n\nThe general idea is to generate a facade module that imports the individual blocks of the component. The trick is the module imports itself with different query strings so that the build system can handle each request as \"virtual\" modules:\n\n```\n                                  +--------------------+\n                                  |                    |\n                                  |  script transform  |\n                           +----->+                    |\n                           |      +--------------------+\n                           |\n+--------------------+     |      +--------------------+\n|                    |     |      |                    |\n|  facade transform  +----------->+ template transform |\n|                    |     |      |                    |\n+--------------------+     |      +--------------------+\n                           |\n                           |      +--------------------+\n                           +----->+                    |\n                                  |  style transform   |\n                                  |                    |\n                                  +--------------------+\n```\n\nWhere the facade module looks like this:\n\n```js\n// main script\nimport script from '/project/foo.vue?vue&type=script'\n// template compiled to render function\nimport { render } from '/project/foo.vue?vue&type=template&id=xxxxxx'\n// css\nimport '/project/foo.vue?vue&type=style&index=0&id=xxxxxx'\n\n// attach render function to script\nscript.render = render\n\n// attach additional metadata\n// some of these should be dev only\nscript.__file = 'example.vue'\nscript.__scopeId = 'xxxxxx'\n\n// additional tooling-specific HMR handling code\n// using __VUE_HMR_API__ global\n\nexport default script\n```\n\n### High Level Workflow\n\n1. In facade transform, parse the source into descriptor with the `parse` API and generate the above facade module code based on the descriptor;\n\n2. In script transform, use `compileScript` to process the script. This handles features like `<script setup>` and CSS variable injection. Alternatively, this can be done directly in the facade module (with the code inlined instead of imported), but it will require rewriting `export default` to a temp variable (a `rewriteDefault` convenience API is provided for this purpose) so additional options can be attached to the exported object.\n\n3. In template transform, use `compileTemplate` to compile the raw template into render function code.\n\n4. In style transform, use `compileStyle` to compile raw CSS to handle `<style scoped>`, `<style module>` and CSS variable injection.\n\nOptions needed for these APIs can be passed via the query string.\n\nFor detailed API references and options, check out the source type definitions. For actual usage of these APIs, check out [@vitejs/plugin-vue](https://github.com/vitejs/vite-plugin-vue/tree/main/packages/plugin-vue) or [vue-loader](https://github.com/vuejs/vue-loader/tree/next).\n"
  },
  {
    "path": "packages/compiler-sfc/__tests__/__snapshots__/compileScript.spec.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`SFC analyze <script> bindings > auto name inference > basic 1`] = `\n\"const a = 1\nexport default {\n  __name: 'FooBar',\n  setup(__props, { expose: __expose }) {\n  __expose();\n\nreturn { a }\n}\n\n}\"\n`;\n\nexports[`SFC analyze <script> bindings > auto name inference > do not overwrite manual name (call) 1`] = `\n\"\n        import { defineComponent } from 'vue'\n        const __default__ = defineComponent({\n          name: 'Baz'\n        })\n        \nexport default /*@__PURE__*/Object.assign(__default__, {\n  setup(__props, { expose: __expose }) {\n  __expose();\nconst a = 1\nreturn { a, defineComponent }\n}\n\n})\"\n`;\n\nexports[`SFC analyze <script> bindings > auto name inference > do not overwrite manual name (object) 1`] = `\n\"\n        const __default__ = {\n          name: 'Baz'\n        }\n        \nexport default /*@__PURE__*/Object.assign(__default__, {\n  setup(__props, { expose: __expose }) {\n  __expose();\nconst a = 1\nreturn { a }\n}\n\n})\"\n`;\n\nexports[`SFC compile <script setup> > <script> and <script setup> co-usage > export call expression as default 1`] = `\n\"\n      function fn() {\n        return \"hello, world\";\n      }\n      const __default__ = fn();\n      \nexport default /*@__PURE__*/Object.assign(__default__, {\n  setup(__props, { expose: __expose }) {\n  __expose();\n\n      console.log('foo')\n      \nreturn { fn }\n}\n\n})\"\n`;\n\nexports[`SFC compile <script setup> > <script> and <script setup> co-usage > keep original semi style 1`] = `\n\"\nexport default {\n  props: ['item'],\n  emits: ['change'],\n  setup(__props, { expose: __expose, emit: __emit }) {\n  __expose();\n\n        console.log('test')\n        const props = __props;\n        const emit = __emit;\n        (function () {})()\n        \nreturn { props, emit }\n}\n\n}\"\n`;\n\nexports[`SFC compile <script setup> > <script> and <script setup> co-usage > script first 1`] = `\n\"import { x } from './x'\n      \n      export const n = 1\n\n      const __default__ = {}\n      \nexport default /*@__PURE__*/Object.assign(__default__, {\n  setup(__props, { expose: __expose }) {\n  __expose();\n\n      x()\n      \nreturn { n, get x() { return x } }\n}\n\n})\"\n`;\n\nexports[`SFC compile <script setup> > <script> and <script setup> co-usage > script setup first 1`] = `\n\"import { x } from './x'\n      \n      export const n = 1\n      const __default__ = {}\n      \n\nexport default /*@__PURE__*/Object.assign(__default__, {\n  setup(__props, { expose: __expose }) {\n  __expose();\n\n      x()\n      \nreturn { n, get x() { return x } }\n}\n\n})\"\n`;\n\nexports[`SFC compile <script setup> > <script> and <script setup> co-usage > script setup first, lang=\"ts\", script block content export default 1`] = `\n\"import { defineComponent as _defineComponent } from 'vue'\nimport { x } from './x'\n      \n      const __default__ = {\n        name: \"test\"\n      }\n      \n\nexport default /*@__PURE__*/_defineComponent({\n  ...__default__,\n  setup(__props, { expose: __expose }) {\n  __expose();\n\n      x()\n      \nreturn { get x() { return x } }\n}\n\n})\"\n`;\n\nexports[`SFC compile <script setup> > <script> and <script setup> co-usage > script setup first, named default export 1`] = `\n\"import { x } from './x'\n      \n      export const n = 1\n      const def = {}\n      \n      \nconst __default__ = def\n\n\nexport default /*@__PURE__*/Object.assign(__default__, {\n  setup(__props, { expose: __expose }) {\n  __expose();\n\n      x()\n      \nreturn { n, def, get x() { return x } }\n}\n\n})\"\n`;\n\nexports[`SFC compile <script setup> > <script> and <script setup> co-usage > spaces in ExportDefaultDeclaration node > with many spaces and newline 1`] = `\n\"import { x } from './x'\n        \n        export const n = 1\n        const __default__ = {\n          some:'option'\n        }\n        \nexport default /*@__PURE__*/Object.assign(__default__, {\n  setup(__props, { expose: __expose }) {\n  __expose();\n\n        x()\n        \nreturn { n, get x() { return x } }\n}\n\n})\"\n`;\n\nexports[`SFC compile <script setup> > <script> and <script setup> co-usage > spaces in ExportDefaultDeclaration node > with minimal spaces 1`] = `\n\"import { x } from './x'\n        \n        export const n = 1\n        const __default__ = {\n          some:'option'\n        }\n        \nexport default /*@__PURE__*/Object.assign(__default__, {\n  setup(__props, { expose: __expose }) {\n  __expose();\n\n        x()\n        \nreturn { n, get x() { return x } }\n}\n\n})\"\n`;\n\nexports[`SFC compile <script setup> > async/await detection > expression statement 1`] = `\n\"import { withAsyncContext as _withAsyncContext } from 'vue'\n\nexport default {\n  async setup(__props, { expose: __expose }) {\n  __expose();\n\nlet __temp, __restore\n;(\n  ([__temp,__restore] = _withAsyncContext(() => foo)),\n  await __temp,\n  __restore()\n)\nreturn {  }\n}\n\n}\"\n`;\n\nexports[`SFC compile <script setup> > async/await detection > multiple \\`if for\\` nested statements 1`] = `\n\"import { withAsyncContext as _withAsyncContext } from 'vue'\n\nexport default {\n  async setup(__props, { expose: __expose }) {\n  __expose();\n\nlet __temp, __restore\nif (ok) {\n        for (let a of [1,2,3]) {\n          (\n  ([__temp,__restore] = _withAsyncContext(() => a)),\n  await __temp,\n  __restore()\n)\n        }\n        for (let a of [1,2,3]) {\n          (\n  ([__temp,__restore] = _withAsyncContext(() => a)),\n  await __temp,\n  __restore()\n)\n          ;(\n  ([__temp,__restore] = _withAsyncContext(() => a)),\n  await __temp,\n  __restore()\n)\n        }\n      }\nreturn {  }\n}\n\n}\"\n`;\n\nexports[`SFC compile <script setup> > async/await detection > multiple \\`if while\\` nested statements 1`] = `\n\"import { withAsyncContext as _withAsyncContext } from 'vue'\n\nexport default {\n  async setup(__props, { expose: __expose }) {\n  __expose();\n\nlet __temp, __restore\nif (ok) {\n        while (d) {\n          (\n  ([__temp,__restore] = _withAsyncContext(() => 5)),\n  await __temp,\n  __restore()\n)\n        }\n        while (d) {\n          (\n  ([__temp,__restore] = _withAsyncContext(() => 5)),\n  await __temp,\n  __restore()\n)\n          ;(\n  ([__temp,__restore] = _withAsyncContext(() => 6)),\n  await __temp,\n  __restore()\n)\n          if (c) {\n            let f = 10\n            10 + (\n  ([__temp,__restore] = _withAsyncContext(() => 7)),\n  __temp = await __temp,\n  __restore(),\n  __temp\n)\n          } else {\n            (\n  ([__temp,__restore] = _withAsyncContext(() => 8)),\n  await __temp,\n  __restore()\n)\n            ;(\n  ([__temp,__restore] = _withAsyncContext(() => 9)),\n  await __temp,\n  __restore()\n)\n          }\n        }\n      }\nreturn {  }\n}\n\n}\"\n`;\n\nexports[`SFC compile <script setup> > async/await detection > multiple \\`if\\` nested statements 1`] = `\n\"import { withAsyncContext as _withAsyncContext } from 'vue'\n\nexport default {\n  async setup(__props, { expose: __expose }) {\n  __expose();\n\nlet __temp, __restore\nif (ok) {\n        let a = 'foo'\n        ;(\n  ([__temp,__restore] = _withAsyncContext(() => 0)),\n  __temp = await __temp,\n  __restore(),\n  __temp\n) + (\n  ([__temp,__restore] = _withAsyncContext(() => 1)),\n  __temp = await __temp,\n  __restore(),\n  __temp\n)\n        ;(\n  ([__temp,__restore] = _withAsyncContext(() => 2)),\n  await __temp,\n  __restore()\n)\n      } else if (a) {\n        (\n  ([__temp,__restore] = _withAsyncContext(() => 10)),\n  await __temp,\n  __restore()\n)\n        if (b) {\n          (\n  ([__temp,__restore] = _withAsyncContext(() => 0)),\n  __temp = await __temp,\n  __restore(),\n  __temp\n) + (\n  ([__temp,__restore] = _withAsyncContext(() => 1)),\n  __temp = await __temp,\n  __restore(),\n  __temp\n)\n        } else {\n          let a = 'foo'\n          ;(\n  ([__temp,__restore] = _withAsyncContext(() => 2)),\n  await __temp,\n  __restore()\n)\n        }\n        if (b) {\n          (\n  ([__temp,__restore] = _withAsyncContext(() => 3)),\n  await __temp,\n  __restore()\n)\n          ;(\n  ([__temp,__restore] = _withAsyncContext(() => 4)),\n  await __temp,\n  __restore()\n)\n        }\n      } else {\n        (\n  ([__temp,__restore] = _withAsyncContext(() => 5)),\n  await __temp,\n  __restore()\n)\n      }\nreturn {  }\n}\n\n}\"\n`;\n\nexports[`SFC compile <script setup> > async/await detection > nested await 1`] = `\n\"import { withAsyncContext as _withAsyncContext } from 'vue'\n\nexport default {\n  async setup(__props, { expose: __expose }) {\n  __expose();\n\nlet __temp, __restore\n;(\n  ([__temp,__restore] = _withAsyncContext(async () => ((\n  ([__temp,__restore] = _withAsyncContext(() => foo)),\n  __temp = await __temp,\n  __restore(),\n  __temp\n)))),\n  await __temp,\n  __restore()\n)\nreturn {  }\n}\n\n}\"\n`;\n\nexports[`SFC compile <script setup> > async/await detection > nested await 2`] = `\n\"import { withAsyncContext as _withAsyncContext } from 'vue'\n\nexport default {\n  async setup(__props, { expose: __expose }) {\n  __expose();\n\nlet __temp, __restore\n;(\n  ([__temp,__restore] = _withAsyncContext(async () => (((\n  ([__temp,__restore] = _withAsyncContext(() => foo)),\n  __temp = await __temp,\n  __restore(),\n  __temp\n))))),\n  await __temp,\n  __restore()\n)\nreturn {  }\n}\n\n}\"\n`;\n\nexports[`SFC compile <script setup> > async/await detection > nested await 3`] = `\n\"import { withAsyncContext as _withAsyncContext } from 'vue'\n\nexport default {\n  async setup(__props, { expose: __expose }) {\n  __expose();\n\nlet __temp, __restore\n;(\n  ([__temp,__restore] = _withAsyncContext(async () => ((\n  ([__temp,__restore] = _withAsyncContext(async () => ((\n  ([__temp,__restore] = _withAsyncContext(() => foo)),\n  __temp = await __temp,\n  __restore(),\n  __temp\n)))),\n  __temp = await __temp,\n  __restore(),\n  __temp\n)))),\n  await __temp,\n  __restore()\n)\nreturn {  }\n}\n\n}\"\n`;\n\nexports[`SFC compile <script setup> > async/await detection > nested leading await in expression statement 1`] = `\n\"import { withAsyncContext as _withAsyncContext } from 'vue'\n\nexport default {\n  async setup(__props, { expose: __expose }) {\n  __expose();\n\nlet __temp, __restore\nfoo()\n;(\n  ([__temp,__restore] = _withAsyncContext(() => 1)),\n  __temp = await __temp,\n  __restore(),\n  __temp\n) + (\n  ([__temp,__restore] = _withAsyncContext(() => 2)),\n  __temp = await __temp,\n  __restore(),\n  __temp\n)\nreturn {  }\n}\n\n}\"\n`;\n\nexports[`SFC compile <script setup> > async/await detection > nested statements 1`] = `\n\"import { withAsyncContext as _withAsyncContext } from 'vue'\n\nexport default {\n  async setup(__props, { expose: __expose }) {\n  __expose();\n\nlet __temp, __restore\nif (ok) { (\n  ([__temp,__restore] = _withAsyncContext(() => foo)),\n  await __temp,\n  __restore()\n) } else { (\n  ([__temp,__restore] = _withAsyncContext(() => bar)),\n  await __temp,\n  __restore()\n) }\nreturn {  }\n}\n\n}\"\n`;\n\nexports[`SFC compile <script setup> > async/await detection > ref 1`] = `\n\"import { withAsyncContext as _withAsyncContext } from 'vue'\n\nexport default {\n  async setup(__props, { expose: __expose }) {\n  __expose();\n\nlet __temp, __restore\nlet a = ref(1 + ((\n  ([__temp,__restore] = _withAsyncContext(() => foo)),\n  __temp = await __temp,\n  __restore(),\n  __temp\n)))\nreturn { get a() { return a }, set a(v) { a = v } }\n}\n\n}\"\n`;\n\nexports[`SFC compile <script setup> > async/await detection > should ignore await inside functions 1`] = `\n\"\nexport default {\n  setup(__props, { expose: __expose }) {\n  __expose();\nasync function foo() { await bar }\nreturn { foo }\n}\n\n}\"\n`;\n\nexports[`SFC compile <script setup> > async/await detection > should ignore await inside functions 2`] = `\n\"\nexport default {\n  setup(__props, { expose: __expose }) {\n  __expose();\nconst foo = async () => { await bar }\nreturn { foo }\n}\n\n}\"\n`;\n\nexports[`SFC compile <script setup> > async/await detection > should ignore await inside functions 3`] = `\n\"\nexport default {\n  setup(__props, { expose: __expose }) {\n  __expose();\nconst obj = { async method() { await bar }}\nreturn { obj }\n}\n\n}\"\n`;\n\nexports[`SFC compile <script setup> > async/await detection > should ignore await inside functions 4`] = `\n\"\nexport default {\n  setup(__props, { expose: __expose }) {\n  __expose();\nconst cls = class Foo { async method() { await bar }}\nreturn { cls }\n}\n\n}\"\n`;\n\nexports[`SFC compile <script setup> > async/await detection > single line conditions 1`] = `\n\"import { withAsyncContext as _withAsyncContext } from 'vue'\n\nexport default {\n  async setup(__props, { expose: __expose }) {\n  __expose();\n\nlet __temp, __restore\nif (false) (\n  ([__temp,__restore] = _withAsyncContext(() => foo())),\n  await __temp,\n  __restore()\n)\nreturn {  }\n}\n\n}\"\n`;\n\nexports[`SFC compile <script setup> > async/await detection > variable 1`] = `\n\"import { withAsyncContext as _withAsyncContext } from 'vue'\n\nexport default {\n  async setup(__props, { expose: __expose }) {\n  __expose();\n\nlet __temp, __restore\nconst a = 1 + ((\n  ([__temp,__restore] = _withAsyncContext(() => foo)),\n  __temp = await __temp,\n  __restore(),\n  __temp\n))\nreturn { a }\n}\n\n}\"\n`;\n\nexports[`SFC compile <script setup> > binding analysis for destructure 1`] = `\n\"\nexport default {\n  setup(__props, { expose: __expose }) {\n  __expose();\n\n      const { foo, b: bar, ['x' + 'y']: baz, x: { y, zz: { z }}} = {}\n      \nreturn { foo, bar, baz, y, z }\n}\n\n}\"\n`;\n\nexports[`SFC compile <script setup> > demote const reactive binding to let when used in v-model (inlineTemplate) 1`] = `\n\"import { unref as _unref, resolveComponent as _resolveComponent, isRef as _isRef, openBlock as _openBlock, createBlock as _createBlock } from \"vue\"\n\nimport { reactive } from 'vue'\n      \nexport default {\n  setup(__props) {\n\n      let name = reactive({ first: 'john', last: 'doe' })\n      \nreturn (_ctx, _cache) => {\n  const _component_MyComponent = _resolveComponent(\"MyComponent\")\n\n  return (_openBlock(), _createBlock(_component_MyComponent, {\n    modelValue: _unref(name),\n    \"onUpdate:modelValue\": _cache[0] || (_cache[0] = $event => (_isRef(name) ? (name).value = $event : name = $event))\n  }, null, 8 /* PROPS */, [\"modelValue\"]))\n}\n}\n\n}\"\n`;\n\nexports[`SFC compile <script setup> > demote const reactive binding to let when used in v-model 1`] = `\n\"import { reactive } from 'vue'\n      \nexport default {\n  setup(__props, { expose: __expose }) {\n  __expose();\n\n      let name = reactive({ first: 'john', last: 'doe' })\n      \nreturn { get name() { return name }, set name(v) { name = v }, reactive }\n}\n\n}\"\n`;\n\nexports[`SFC compile <script setup> > errors > should allow defineProps/Emit() referencing imported binding 1`] = `\n\"import { bar } from './bar'\n        \nexport default {\n  props: {\n          foo: {\n            default: () => bar\n          }\n        },\n  emits: {\n          foo: () => bar > 1\n        },\n  setup(__props, { expose: __expose }) {\n  __expose();\n\n        \n        \n        \nreturn { get bar() { return bar } }\n}\n\n}\"\n`;\n\nexports[`SFC compile <script setup> > errors > should allow defineProps/Emit() referencing scope var 1`] = `\n\"const bar = 1\n          \nexport default {\n  props: {\n            foo: {\n              default: bar => bar + 1\n            }\n          },\n  emits: {\n            foo: bar => bar > 1\n          },\n  setup(__props, { expose: __expose }) {\n  __expose();\n\n          \n          \n        \nreturn { bar }\n}\n\n}\"\n`;\n\nexports[`SFC compile <script setup> > imports > dedupe between user & helper 1`] = `\n\"import { useCssVars as _useCssVars, unref as _unref } from 'vue'\nimport { useCssVars, ref } from 'vue'\n      \nexport default {\n  setup(__props, { expose: __expose }) {\n  __expose();\n\n_useCssVars(_ctx => ({\n  \"xxxxxxxx-msg\": (msg.value)\n}))\n\n      const msg = ref()\n      \nreturn { msg, useCssVars, ref }\n}\n\n}\"\n`;\n\nexports[`SFC compile <script setup> > imports > import dedupe between <script> and <script setup> 1`] = `\n\"\n        \n        import { x } from './x'\n        \nexport default {\n  setup(__props, { expose: __expose }) {\n  __expose();\n\n        x()\n        \nreturn { get x() { return x } }\n}\n\n}\"\n`;\n\nexports[`SFC compile <script setup> > imports > should allow defineProps/Emit at the start of imports 1`] = `\n\"import { ref } from 'vue'\n      \nexport default {\n  props: ['foo'],\n  emits: ['bar'],\n  setup(__props, { expose: __expose }) {\n  __expose();\n\n      \n      \n      const r = ref(0)\n      \nreturn { r, ref }\n}\n\n}\"\n`;\n\nexports[`SFC compile <script setup> > imports > should extract comment for import or type declarations 1`] = `\n\"import a from 'a' // comment\n        import b from 'b'\n        \nexport default {\n  setup(__props, { expose: __expose }) {\n  __expose();\n\n        \nreturn { get a() { return a }, get b() { return b } }\n}\n\n}\"\n`;\n\nexports[`SFC compile <script setup> > imports > should hoist and expose imports 1`] = `\n\"import { ref } from 'vue'\n          import 'foo/css'\n        \nexport default {\n  setup(__props, { expose: __expose }) {\n  __expose();\n\n          \nreturn { ref }\n}\n\n}\"\n`;\n\nexports[`SFC compile <script setup> > imports > should support module string names syntax 1`] = `\n\"\n      \n        import { \"😏\" as foo } from './foo'\n      \nexport default {\n  setup(__props, { expose: __expose }) {\n  __expose();\n\n        \nreturn { get foo() { return foo } }\n}\n\n}\"\n`;\n\nexports[`SFC compile <script setup> > inlineTemplate mode > avoid unref() when necessary 1`] = `\n\"import { unref as _unref, toDisplayString as _toDisplayString, createTextVNode as _createTextVNode, withCtx as _withCtx, createVNode as _createVNode, createElementVNode as _createElementVNode, Fragment as _Fragment, openBlock as _openBlock, createElementBlock as _createElementBlock } from \"vue\"\n\nimport { ref } from 'vue'\n        import Foo, { bar } from './Foo.vue'\n        import other from './util'\n        import * as tree from './tree'\n        \nexport default {\n  setup(__props) {\n\n        const count = ref(0)\n        const constant = {}\n        const maybe = foo()\n        let lett = 1\n        function fn() {}\n        \nreturn (_ctx, _cache) => {\n  return (_openBlock(), _createElementBlock(_Fragment, null, [\n    _createVNode(Foo, null, {\n      default: _withCtx(() => [\n        _createTextVNode(_toDisplayString(_unref(bar)), 1 /* TEXT */)\n      ]),\n      _: 1 /* STABLE */\n    }),\n    _createElementVNode(\"div\", { onClick: fn }, _toDisplayString(count.value) + \" \" + _toDisplayString(constant) + \" \" + _toDisplayString(_unref(maybe)) + \" \" + _toDisplayString(_unref(lett)) + \" \" + _toDisplayString(_unref(other)), 1 /* TEXT */),\n    _createTextVNode(\" \" + _toDisplayString(tree.foo()), 1 /* TEXT */)\n  ], 64 /* STABLE_FRAGMENT */))\n}\n}\n\n}\"\n`;\n\nexports[`SFC compile <script setup> > inlineTemplate mode > referencing scope components and directives 1`] = `\n\"import { unref as _unref, createElementVNode as _createElementVNode, withDirectives as _withDirectives, createVNode as _createVNode, Fragment as _Fragment, openBlock as _openBlock, createElementBlock as _createElementBlock } from \"vue\"\n\nimport ChildComp from './Child.vue'\n        import SomeOtherComp from './Other.vue'\n        import vMyDir from './my-dir'\n        \nexport default {\n  setup(__props) {\n\n        \nreturn (_ctx, _cache) => {\n  return (_openBlock(), _createElementBlock(_Fragment, null, [\n    _withDirectives(_createElementVNode(\"div\", null, null, 512 /* NEED_PATCH */), [\n      [_unref(vMyDir)]\n    ]),\n    _createVNode(ChildComp),\n    _createVNode(SomeOtherComp)\n  ], 64 /* STABLE_FRAGMENT */))\n}\n}\n\n}\"\n`;\n\nexports[`SFC compile <script setup> > inlineTemplate mode > should work 1`] = `\n\"import { toDisplayString as _toDisplayString, createElementVNode as _createElementVNode, Fragment as _Fragment, openBlock as _openBlock, createElementBlock as _createElementBlock } from \"vue\"\n\nimport { ref } from 'vue'\n        \nexport default {\n  setup(__props) {\n\n        const count = ref(0)\n        \nreturn (_ctx, _cache) => {\n  return (_openBlock(), _createElementBlock(_Fragment, null, [\n    _createElementVNode(\"div\", null, _toDisplayString(count.value), 1 /* TEXT */),\n    _cache[0] || (_cache[0] = _createElementVNode(\"div\", null, \"static\", -1 /* CACHED */))\n  ], 64 /* STABLE_FRAGMENT */))\n}\n}\n\n}\"\n`;\n\nexports[`SFC compile <script setup> > inlineTemplate mode > ssr codegen 1`] = `\n\"import { ssrRenderAttrs as _ssrRenderAttrs, ssrInterpolate as _ssrInterpolate } from \"vue/server-renderer\"\n\nimport { ref } from 'vue'\n        \nexport default {\n  __ssrInlineRender: true,\n  setup(__props) {\n\n        const count = ref(0)\n        const style = { color: 'red' }\n        const height = ref(0)\n        \nreturn (_ctx, _push, _parent, _attrs) => {\n  const _cssVars = { style: {\n  \":--xxxxxxxx-count\": (count.value),\n  \":--xxxxxxxx-style\\\\\\\\.color\": (style.color),\n  \":--xxxxxxxx-height\\\\\\\\ \\\\\\\\+\\\\\\\\ \\\\\\\\\\\\\"px\\\\\\\\\\\\\"\": (height.value + \"px\")\n}}\n  _push(\\`<!--[--><div\\${\n    _ssrRenderAttrs(_cssVars)\n  }>\\${\n    _ssrInterpolate(count.value)\n  }</div><div\\${\n    _ssrRenderAttrs(_cssVars)\n  }>static</div><!--]-->\\`)\n}\n}\n\n}\"\n`;\n\nexports[`SFC compile <script setup> > inlineTemplate mode > template assignment expression codegen 1`] = `\n\"import { createElementVNode as _createElementVNode, isRef as _isRef, unref as _unref, Fragment as _Fragment, openBlock as _openBlock, createElementBlock as _createElementBlock } from \"vue\"\n\nimport { ref } from 'vue'\n        \nexport default {\n  setup(__props) {\n\n        const count = ref(0)\n        const maybe = foo()\n        let lett = 1\n        let v = ref(1)\n        \nreturn (_ctx, _cache) => {\n  return (_openBlock(), _createElementBlock(_Fragment, null, [\n    _createElementVNode(\"div\", {\n      onClick: _cache[0] || (_cache[0] = $event => (count.value = 1))\n    }),\n    _createElementVNode(\"div\", {\n      onClick: _cache[1] || (_cache[1] = $event => (maybe.value = count.value))\n    }),\n    _createElementVNode(\"div\", {\n      onClick: _cache[2] || (_cache[2] = $event => (_isRef(lett) ? lett.value = count.value : lett = count.value))\n    }),\n    _createElementVNode(\"div\", {\n      onClick: _cache[3] || (_cache[3] = $event => (_isRef(v) ? v.value += 1 : v += 1))\n    }),\n    _createElementVNode(\"div\", {\n      onClick: _cache[4] || (_cache[4] = $event => (_isRef(v) ? v.value -= 1 : v -= 1))\n    }),\n    _createElementVNode(\"div\", {\n      onClick: _cache[5] || (_cache[5] = () => {\n              let a = '' + _unref(lett)\n              _isRef(v) ? v.value = a : v = a\n           })\n    }),\n    _createElementVNode(\"div\", {\n      onClick: _cache[6] || (_cache[6] = () => {\n              // nested scopes\n              (()=>{\n                let x = _ctx.a\n                (()=>{\n                  let z = x\n                  let z2 = z\n                })\n                let lz = _ctx.z\n              })\n              _isRef(v) ? v.value = _ctx.a : v = _ctx.a\n           })\n    })\n  ], 64 /* STABLE_FRAGMENT */))\n}\n}\n\n}\"\n`;\n\nexports[`SFC compile <script setup> > inlineTemplate mode > template destructure assignment codegen 1`] = `\n\"import { createElementVNode as _createElementVNode, Fragment as _Fragment, openBlock as _openBlock, createElementBlock as _createElementBlock } from \"vue\"\n\nimport { ref } from 'vue'\n        \nexport default {\n  setup(__props) {\n\n        const val = {}\n        const count = ref(0)\n        const maybe = foo()\n        let lett = 1\n        \nreturn (_ctx, _cache) => {\n  return (_openBlock(), _createElementBlock(_Fragment, null, [\n    _createElementVNode(\"div\", {\n      onClick: _cache[0] || (_cache[0] = $event => (({ count: count.value } = val)))\n    }),\n    _createElementVNode(\"div\", {\n      onClick: _cache[1] || (_cache[1] = $event => ([maybe.value] = val))\n    }),\n    _createElementVNode(\"div\", {\n      onClick: _cache[2] || (_cache[2] = $event => (({ lett: lett } = val)))\n    })\n  ], 64 /* STABLE_FRAGMENT */))\n}\n}\n\n}\"\n`;\n\nexports[`SFC compile <script setup> > inlineTemplate mode > template update expression codegen 1`] = `\n\"import { createElementVNode as _createElementVNode, isRef as _isRef, Fragment as _Fragment, openBlock as _openBlock, createElementBlock as _createElementBlock } from \"vue\"\n\nimport { ref } from 'vue'\n        \nexport default {\n  setup(__props) {\n\n        const count = ref(0)\n        const maybe = foo()\n        let lett = 1\n        \nreturn (_ctx, _cache) => {\n  return (_openBlock(), _createElementBlock(_Fragment, null, [\n    _createElementVNode(\"div\", {\n      onClick: _cache[0] || (_cache[0] = $event => (count.value++))\n    }),\n    _createElementVNode(\"div\", {\n      onClick: _cache[1] || (_cache[1] = $event => (--count.value))\n    }),\n    _createElementVNode(\"div\", {\n      onClick: _cache[2] || (_cache[2] = $event => (maybe.value++))\n    }),\n    _createElementVNode(\"div\", {\n      onClick: _cache[3] || (_cache[3] = $event => (--maybe.value))\n    }),\n    _createElementVNode(\"div\", {\n      onClick: _cache[4] || (_cache[4] = $event => (_isRef(lett) ? lett.value++ : lett++))\n    }),\n    _createElementVNode(\"div\", {\n      onClick: _cache[5] || (_cache[5] = $event => (_isRef(lett) ? --lett.value : --lett))\n    })\n  ], 64 /* STABLE_FRAGMENT */))\n}\n}\n\n}\"\n`;\n\nexports[`SFC compile <script setup> > inlineTemplate mode > unref + new expression 1`] = `\n\"import { unref as _unref, toDisplayString as _toDisplayString, createElementVNode as _createElementVNode, Fragment as _Fragment, openBlock as _openBlock, createElementBlock as _createElementBlock } from \"vue\"\n\nimport Foo from './foo'\n        \nexport default {\n  setup(__props) {\n\n        \nreturn (_ctx, _cache) => {\n  return (_openBlock(), _createElementBlock(_Fragment, null, [\n    _createElementVNode(\"div\", null, _toDisplayString(new (_unref(Foo))()), 1 /* TEXT */),\n    _createElementVNode(\"div\", null, _toDisplayString(new (_unref(Foo)).Bar()), 1 /* TEXT */)\n  ], 64 /* STABLE_FRAGMENT */))\n}\n}\n\n}\"\n`;\n\nexports[`SFC compile <script setup> > inlineTemplate mode > v-model codegen 1`] = `\n\"import { vModelText as _vModelText, createElementVNode as _createElementVNode, withDirectives as _withDirectives, unref as _unref, isRef as _isRef, Fragment as _Fragment, openBlock as _openBlock, createElementBlock as _createElementBlock } from \"vue\"\n\nimport { ref } from 'vue'\n        \nexport default {\n  setup(__props) {\n\n        const count = ref(0)\n        const maybe = foo()\n        let lett = 1\n        \nreturn (_ctx, _cache) => {\n  return (_openBlock(), _createElementBlock(_Fragment, null, [\n    _withDirectives(_createElementVNode(\"input\", {\n      \"onUpdate:modelValue\": _cache[0] || (_cache[0] = $event => ((count).value = $event))\n    }, null, 512 /* NEED_PATCH */), [\n      [_vModelText, count.value]\n    ]),\n    _withDirectives(_createElementVNode(\"input\", {\n      \"onUpdate:modelValue\": _cache[1] || (_cache[1] = $event => (_isRef(maybe) ? (maybe).value = $event : null))\n    }, null, 512 /* NEED_PATCH */), [\n      [_vModelText, _unref(maybe)]\n    ]),\n    _withDirectives(_createElementVNode(\"input\", {\n      \"onUpdate:modelValue\": _cache[2] || (_cache[2] = $event => (_isRef(lett) ? (lett).value = $event : lett = $event))\n    }, null, 512 /* NEED_PATCH */), [\n      [_vModelText, _unref(lett)]\n    ])\n  ], 64 /* STABLE_FRAGMENT */))\n}\n}\n\n}\"\n`;\n\nexports[`SFC compile <script setup> > inlineTemplate mode > v-model w/ newlines codegen 1`] = `\n\"import { unref as _unref, isRef as _isRef, vModelText as _vModelText, withDirectives as _withDirectives, openBlock as _openBlock, createElementBlock as _createElementBlock } from \"vue\"\n\n\nexport default {\n  setup(__props) {\n\n        const count = ref(0)\n        \nreturn (_ctx, _cache) => {\n  return _withDirectives((_openBlock(), _createElementBlock(\"input\", {\n    \"onUpdate:modelValue\": _cache[0] || (_cache[0] = $event => (_isRef(count) ? (count).value = $event : null))\n  }, null, 512 /* NEED_PATCH */)), [\n    [_vModelText, \n          _unref(count)\n          ]\n  ])\n}\n}\n\n}\"\n`;\n\nexports[`SFC compile <script setup> > inlineTemplate mode > with defineExpose() 1`] = `\n\"\nexport default {\n  setup(__props, { expose: __expose }) {\n\n        const count = ref(0)\n        __expose({ count })\n        \nreturn () => {}\n}\n\n}\"\n`;\n\nexports[`SFC compile <script setup> > should compile JS syntax 1`] = `\n\"const a = 1\n      const b = 2\n      \nexport default {\n  setup(__props, { expose: __expose }) {\n  __expose();\n\n      \nreturn { a, b }\n}\n\n}\"\n`;\n\nexports[`SFC compile <script setup> > should expose top level declarations 1`] = `\n\"import { x } from './x'\n      \n      import { xx } from './x'\n      let aa = 1\n      const bb = 2\n      function cc() {}\n      class dd {}\n      \n\nexport default {\n  setup(__props, { expose: __expose }) {\n  __expose();\n\n      let a = 1\n      const b = 2\n      function c() {}\n      class d {}\n      \nreturn { get aa() { return aa }, set aa(v) { aa = v }, bb, cc, dd, get a() { return a }, set a(v) { a = v }, b, c, d, get xx() { return xx }, get x() { return x } }\n}\n\n}\"\n`;\n\nexports[`SFC compile <script setup> > with TypeScript > const Enum 1`] = `\n\"import { defineComponent as _defineComponent } from 'vue'\nconst enum Foo { A = 123 }\n        \nexport default /*@__PURE__*/_defineComponent({\n  setup(__props, { expose: __expose }) {\n  __expose();\n\n        \nreturn { Foo }\n}\n\n})\"\n`;\n\nexports[`SFC compile <script setup> > with TypeScript > hoist type declarations 1`] = `\n\"import { defineComponent as _defineComponent } from 'vue'\nexport interface Foo {}\n        type Bar = {}\n      \nexport default /*@__PURE__*/_defineComponent({\n  setup(__props, { expose: __expose }) {\n  __expose();\n\n        \nreturn {  }\n}\n\n})\"\n`;\n\nexports[`SFC compile <script setup> > with TypeScript > import type 1`] = `\n\"import { defineComponent as _defineComponent } from 'vue'\nimport type { Foo } from './main.ts'\n        import { type Bar, Baz } from './main.ts'\n        \nexport default /*@__PURE__*/_defineComponent({\n  setup(__props, { expose: __expose }) {\n  __expose();\n\n        \nreturn { get Baz() { return Baz } }\n}\n\n})\"\n`;\n\nexports[`SFC compile <script setup> > with TypeScript > runtime Enum 1`] = `\n\"import { defineComponent as _defineComponent } from 'vue'\nenum Foo { A = 123 }\n        \nexport default /*@__PURE__*/_defineComponent({\n  setup(__props, { expose: __expose }) {\n  __expose();\n\n        \nreturn { Foo }\n}\n\n})\"\n`;\n\nexports[`SFC compile <script setup> > with TypeScript > runtime Enum in normal script 1`] = `\n\"import { defineComponent as _defineComponent } from 'vue'\n\n          export enum D { D = \"D\" }\n          const enum C { C = \"C\" }\n          enum B { B = \"B\" }\n        \nexport default /*@__PURE__*/_defineComponent({\n  setup(__props, { expose: __expose }) {\n  __expose();\n\n        enum Foo { A = 123 }\n        \nreturn { D, C, B, Foo }\n}\n\n})\"\n`;\n\nexports[`SFC compile <script setup> > with TypeScript > with generic attribute 1`] = `\n\"import { defineComponent as _defineComponent } from 'vue'\ntype Bar = {}\n      \nexport default /*@__PURE__*/_defineComponent({\n  setup(__props, { expose: __expose }) {\n  __expose();\n\n        \nreturn {  }\n}\n\n})\"\n`;\n\nexports[`SFC genDefaultAs > <script setup> only 1`] = `\n\"const a = 1\n      \nconst _sfc_ = {\n  setup(__props, { expose: __expose }) {\n  __expose();\n\n      \nreturn { a }\n}\n\n}\"\n`;\n\nexports[`SFC genDefaultAs > <script setup> only w/ ts 1`] = `\n\"import { defineComponent as _defineComponent } from 'vue'\nconst a = 1\n      \nconst _sfc_ = /*@__PURE__*/_defineComponent({\n  setup(__props, { expose: __expose }) {\n  __expose();\n\n      \nreturn { a }\n}\n\n})\"\n`;\n\nexports[`SFC genDefaultAs > <script> + <script setup> 1`] = `\n\"\n      const __default__ = {}\n      \nconst _sfc_ = /*@__PURE__*/Object.assign(__default__, {\n  setup(__props, { expose: __expose }) {\n  __expose();\n\n      const a = 1\n      \nreturn { a }\n}\n\n})\"\n`;\n\nexports[`SFC genDefaultAs > <script> + <script setup> 2`] = `\n\"\n      const __default__ = {}\n      \nconst _sfc_ = /*@__PURE__*/Object.assign(__default__, {\n  setup(__props, { expose: __expose }) {\n  __expose();\n\n      const a = 1\n      \nreturn { a }\n}\n\n})\"\n`;\n\nexports[`SFC genDefaultAs > <script> + <script setup> w/ ts 1`] = `\n\"import { defineComponent as _defineComponent } from 'vue'\n\n      const __default__ = {}\n      \nconst _sfc_ = /*@__PURE__*/_defineComponent({\n  ...__default__,\n  setup(__props, { expose: __expose }) {\n  __expose();\n\n      const a = 1\n      \nreturn { a }\n}\n\n})\"\n`;\n\nexports[`SFC genDefaultAs > normal <script> only 1`] = `\n\"\n      const _sfc_ = {}\n      \"\n`;\n\nexports[`SFC genDefaultAs > normal <script> w/ cssVars 1`] = `\n\"\n      const _sfc_ = {}\n      \nimport { useCssVars as _useCssVars } from 'vue'\nconst __injectCSSVars__ = () => {\n_useCssVars(_ctx => ({\n  \"xxxxxxxx-x\": (_ctx.x)\n}))}\nconst __setup__ = _sfc_.setup\n_sfc_.setup = __setup__\n  ? (props, ctx) => { __injectCSSVars__();return __setup__(props, ctx) }\n  : __injectCSSVars__\n\"\n`;\n\nexports[`SFC genDefaultAs > parser plugins > import attributes (user override for deprecated syntax) 1`] = `\n\"import { foo } from './foo.js' assert { type: 'foobar' }\n        \nexport default {\n  setup(__props, { expose: __expose }) {\n  __expose();\n\n        \nreturn { get foo() { return foo } }\n}\n\n}\"\n`;\n\nexports[`SFC genDefaultAs > parser plugins > import attributes 1`] = `\n\"import { foo } from './foo.js' with { type: 'foobar' }\n        \nexport default {\n  setup(__props, { expose: __expose }) {\n  __expose();\n\n        \nreturn { get foo() { return foo } }\n}\n\n}\"\n`;\n\nexports[`compileScript > should care about runtimeModuleName 1`] = `\n\"import { withAsyncContext as _withAsyncContext } from \"npm:vue\"\n\nexport default {\n  async setup(__props, { expose: __expose }) {\n  __expose();\n\nlet __temp, __restore\n\n        ;(\n  ([__temp,__restore] = _withAsyncContext(() => Promise.resolve(1))),\n  await __temp,\n  __restore()\n)\n      \nreturn {  }\n}\n\n}\"\n`;\n"
  },
  {
    "path": "packages/compiler-sfc/__tests__/__snapshots__/compileTemplate.spec.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`dynamic v-on + static v-on should merged 1`] = `\n\"import { toHandlerKey as _toHandlerKey, mergeProps as _mergeProps, openBlock as _openBlock, createElementBlock as _createElementBlock } from \"vue\"\n\nexport function render(_ctx, _cache) {\n  return (_openBlock(), _createElementBlock(\"input\", _mergeProps({\n    onBlur: _cache[0] || (_cache[0] = (...args) => (_ctx.onBlur && _ctx.onBlur(...args)))\n  }, {\n    [_toHandlerKey(_ctx.validateEvent)]: _cache[1] || (_cache[1] = (...args) => (_ctx.onValidateEvent && _ctx.onValidateEvent(...args)))\n  }), null, 16 /* FULL_PROPS */))\n}\"\n`;\n\nexports[`prefixing props edge case in inline mode 1`] = `\n\"import { defineComponent as _defineComponent } from 'vue'\nimport { unref as _unref, openBlock as _openBlock, createBlock as _createBlock } from \"vue\"\n\n\nexport default /*@__PURE__*/_defineComponent({\n  props: {\n    Foo: { type: Object, required: true }\n  },\n  setup(__props: any) {\n\n    \n  \nreturn (_ctx: any,_cache: any) => {\n  return (_openBlock(), _createBlock(_unref(__props[\"Foo\"]).Bar))\n}\n}\n\n})\"\n`;\n\nexports[`should not hoist srcset URLs in SSR mode 1`] = `\n\"import { resolveComponent as _resolveComponent, withCtx as _withCtx, createVNode as _createVNode } from \"vue\"\nimport { ssrRenderAttr as _ssrRenderAttr, ssrRenderComponent as _ssrRenderComponent } from \"vue/server-renderer\"\nimport _imports_0 from './img/foo.svg'\nimport _imports_1 from './img/bar.svg'\n\n\nexport function ssrRender(_ctx, _push, _parent, _attrs) {\n  const _component_router_link = _resolveComponent(\"router-link\")\n\n  _push(\\`<!--[--><picture><source\\${\n    _ssrRenderAttr(\"srcset\", _imports_0)\n  }><img\\${\n    _ssrRenderAttr(\"src\", _imports_0)\n  }></picture>\\`)\n  _push(_ssrRenderComponent(_component_router_link, null, {\n    default: _withCtx((_, _push, _parent, _scopeId) => {\n      if (_push) {\n        _push(\\`<picture\\${\n          _scopeId\n        }><source\\${\n          _ssrRenderAttr(\"srcset\", _imports_1)\n        }\\${\n          _scopeId\n        }><img\\${\n          _ssrRenderAttr(\"src\", _imports_1)\n        }\\${\n          _scopeId\n        }></picture>\\`)\n      } else {\n        return [\n          _createVNode(\"picture\", null, [\n            _createVNode(\"source\", {\n              srcset: _imports_1\n            }),\n            _createVNode(\"img\", { src: _imports_1 })\n          ])\n        ]\n      }\n    }),\n    _: 1 /* STABLE */\n  }, _parent))\n  _push(\\`<!--]-->\\`)\n}\"\n`;\n\nexports[`template errors 1`] = `\n[\n  [SyntaxError: Error parsing JavaScript expression: Unexpected token (1:3)],\n  [SyntaxError: v-model can only be used on <input>, <textarea> and <select> elements.],\n]\n`;\n"
  },
  {
    "path": "packages/compiler-sfc/__tests__/__snapshots__/cssVars.spec.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`CSS vars injection > codegen > <script> w/ default export 1`] = `\n\"const __default__ = { setup() {} }\nimport { useCssVars as _useCssVars } from 'vue'\nconst __injectCSSVars__ = () => {\n_useCssVars(_ctx => ({\n  \"xxxxxxxx-color\": (_ctx.color)\n}))}\nconst __setup__ = __default__.setup\n__default__.setup = __setup__\n  ? (props, ctx) => { __injectCSSVars__();return __setup__(props, ctx) }\n  : __injectCSSVars__\n\nexport default __default__\"\n`;\n\nexports[`CSS vars injection > codegen > <script> w/ default export in strings/comments 1`] = `\n\"\n          // export default {}\n          const __default__ = {}\n        \nimport { useCssVars as _useCssVars } from 'vue'\nconst __injectCSSVars__ = () => {\n_useCssVars(_ctx => ({\n  \"xxxxxxxx-color\": (_ctx.color)\n}))}\nconst __setup__ = __default__.setup\n__default__.setup = __setup__\n  ? (props, ctx) => { __injectCSSVars__();return __setup__(props, ctx) }\n  : __injectCSSVars__\n\nexport default __default__\"\n`;\n\nexports[`CSS vars injection > codegen > <script> w/ no default export 1`] = `\n\"const a = 1\nconst __default__ = {}\nimport { useCssVars as _useCssVars } from 'vue'\nconst __injectCSSVars__ = () => {\n_useCssVars(_ctx => ({\n  \"xxxxxxxx-color\": (_ctx.color)\n}))}\nconst __setup__ = __default__.setup\n__default__.setup = __setup__\n  ? (props, ctx) => { __injectCSSVars__();return __setup__(props, ctx) }\n  : __injectCSSVars__\n\nexport default __default__\"\n`;\n\nexports[`CSS vars injection > codegen > should ignore comments 1`] = `\n\"import { useCssVars as _useCssVars, unref as _unref } from 'vue'\nconst color = 'red';const width = 100\nexport default {\n  setup(__props, { expose: __expose }) {\n  __expose();\n\n_useCssVars(_ctx => ({\n  \"xxxxxxxx-width\": (width)\n}))\n\nreturn { color, width }\n}\n\n}\"\n`;\n\nexports[`CSS vars injection > codegen > should work with w/ complex expression 1`] = `\n\"import { useCssVars as _useCssVars, unref as _unref } from 'vue'\n\nexport default {\n  setup(__props, { expose: __expose }) {\n  __expose();\n\n_useCssVars(_ctx => ({\n  \"xxxxxxxx-foo\": (_unref(foo)),\n  \"xxxxxxxx-foo\\\\ \\\\+\\\\ \\\\'px\\\\'\": (_unref(foo) + 'px'),\n  \"xxxxxxxx-\\\\(a\\\\ \\\\+\\\\ b\\\\)\\\\ \\\\/\\\\ 2\\\\ \\\\+\\\\ \\\\'px\\\\'\": ((_unref(a) + _unref(b)) / 2 + 'px'),\n  \"xxxxxxxx-\\\\(\\\\(a\\\\ \\\\+\\\\ b\\\\)\\\\)\\\\ \\\\/\\\\ \\\\(2\\\\ \\\\*\\\\ a\\\\)\": (((_unref(a) + _unref(b))) / (2 * _unref(a)))\n}))\n\n        let a = 100\n        let b = 200\n        let foo = 300\n        \nreturn { get a() { return a }, set a(v) { a = v }, get b() { return b }, set b(v) { b = v }, get foo() { return foo }, set foo(v) { foo = v } }\n}\n\n}\"\n`;\n\nexports[`CSS vars injection > codegen > w/ <script setup> 1`] = `\n\"import { useCssVars as _useCssVars, unref as _unref } from 'vue'\nconst color = 'red'\nexport default {\n  setup(__props, { expose: __expose }) {\n  __expose();\n\n_useCssVars(_ctx => ({\n  \"xxxxxxxx-color\": (color)\n}))\n\nreturn { color }\n}\n\n}\"\n`;\n\nexports[`CSS vars injection > codegen > w/ <script setup> using the same var multiple times 1`] = `\n\"import { useCssVars as _useCssVars, unref as _unref } from 'vue'\nconst color = 'red'\n        \nexport default {\n  setup(__props, { expose: __expose }) {\n  __expose();\n\n_useCssVars(_ctx => ({\n  \"xxxxxxxx-color\": (color)\n}))\n\n        \nreturn { color }\n}\n\n}\"\n`;\n\nexports[`CSS vars injection > generating correct code for nested paths 1`] = `\n\"const a = 1\nconst __default__ = {}\nimport { useCssVars as _useCssVars } from 'vue'\nconst __injectCSSVars__ = () => {\n_useCssVars(_ctx => ({\n  \"xxxxxxxx-color\": (_ctx.color),\n  \"xxxxxxxx-font\\\\.size\": (_ctx.font.size)\n}))}\nconst __setup__ = __default__.setup\n__default__.setup = __setup__\n  ? (props, ctx) => { __injectCSSVars__();return __setup__(props, ctx) }\n  : __injectCSSVars__\n\nexport default __default__\"\n`;\n\nexports[`CSS vars injection > w/ <script setup> binding analysis 1`] = `\n\"import { useCssVars as _useCssVars, unref as _unref } from 'vue'\nimport { ref } from 'vue'\n        const color = 'red'\n        \nexport default {\n  props: {\n          foo: String\n        },\n  setup(__props, { expose: __expose }) {\n  __expose();\n\n_useCssVars(_ctx => ({\n  \"xxxxxxxx-color\": (color),\n  \"xxxxxxxx-size\": (size.value),\n  \"xxxxxxxx-foo\": (__props.foo)\n}))\n\n        const size = ref('10px')\n        \n        \nreturn { color, size, ref }\n}\n\n}\"\n`;\n\nexports[`CSS vars injection > w/ normal <script> binding analysis 1`] = `\n\"\n      const __default__ = {\n        setup() {\n          return {\n            size: ref('100px')\n          }\n        }\n      }\n      \nimport { useCssVars as _useCssVars } from 'vue'\nconst __injectCSSVars__ = () => {\n_useCssVars(_ctx => ({\n  \"xxxxxxxx-size\": (_ctx.size)\n}))}\nconst __setup__ = __default__.setup\n__default__.setup = __setup__\n  ? (props, ctx) => { __injectCSSVars__();return __setup__(props, ctx) }\n  : __injectCSSVars__\n\nexport default __default__\"\n`;\n"
  },
  {
    "path": "packages/compiler-sfc/__tests__/__snapshots__/templateTransformAssetUrl.spec.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`compiler sfc: transform asset url > should allow for full base URLs, with paths 1`] = `\n\"import { openBlock as _openBlock, createElementBlock as _createElementBlock } from \"vue\"\n\nexport function render(_ctx, _cache) {\n  return (_openBlock(), _createElementBlock(\"img\", { src: \"http://localhost:3000/src/logo.png\" }))\n}\"\n`;\n\nexports[`compiler sfc: transform asset url > should allow for full base URLs, without paths 1`] = `\n\"import { openBlock as _openBlock, createElementBlock as _createElementBlock } from \"vue\"\n\nexport function render(_ctx, _cache) {\n  return (_openBlock(), _createElementBlock(\"img\", { src: \"http://localhost:3000/logo.png\" }))\n}\"\n`;\n\nexports[`compiler sfc: transform asset url > should allow for full base URLs, without port 1`] = `\n\"import { openBlock as _openBlock, createElementBlock as _createElementBlock } from \"vue\"\n\nexport function render(_ctx, _cache) {\n  return (_openBlock(), _createElementBlock(\"img\", { src: \"http://localhost/logo.png\" }))\n}\"\n`;\n\nexports[`compiler sfc: transform asset url > should allow for full base URLs, without protocol 1`] = `\n\"import { openBlock as _openBlock, createElementBlock as _createElementBlock } from \"vue\"\n\nexport function render(_ctx, _cache) {\n  return (_openBlock(), _createElementBlock(\"img\", { src: \"//localhost/logo.png\" }))\n}\"\n`;\n\nexports[`compiler sfc: transform asset url > support uri fragment 1`] = `\n\"import { createElementVNode as _createElementVNode, Fragment as _Fragment, openBlock as _openBlock, createElementBlock as _createElementBlock } from \"vue\"\nimport _imports_0 from '@svg/file.svg'\n\n\nconst _hoisted_1 = _imports_0 + '#fragment'\n\nexport function render(_ctx, _cache) {\n  return (_openBlock(), _createElementBlock(_Fragment, null, [\n    _cache[0] || (_cache[0] = _createElementVNode(\"use\", { href: _hoisted_1 }, null, -1 /* CACHED */)),\n    _cache[1] || (_cache[1] = _createElementVNode(\"use\", { href: _hoisted_1 }, null, -1 /* CACHED */))\n  ], 64 /* STABLE_FRAGMENT */))\n}\"\n`;\n\nexports[`compiler sfc: transform asset url > support uri is empty 1`] = `\n\"import { openBlock as _openBlock, createElementBlock as _createElementBlock } from \"vue\"\n\nexport function render(_ctx, _cache) {\n  return (_openBlock(), _createElementBlock(\"use\", { href: '' }))\n}\"\n`;\n\nexports[`compiler sfc: transform asset url > transform assetUrls 1`] = `\n\"import { createElementVNode as _createElementVNode, Fragment as _Fragment, openBlock as _openBlock, createElementBlock as _createElementBlock } from \"vue\"\nimport _imports_0 from './logo.png'\nimport _imports_1 from 'fixtures/logo.png'\n\n\nexport function render(_ctx, _cache) {\n  return (_openBlock(), _createElementBlock(_Fragment, null, [\n    _createElementVNode(\"img\", { src: _imports_0 }),\n    _createElementVNode(\"img\", { src: _imports_1 }),\n    _createElementVNode(\"img\", { src: _imports_1 }),\n    _createElementVNode(\"img\", { src: \"http://example.com/fixtures/logo.png\" }),\n    _createElementVNode(\"img\", { src: \"//example.com/fixtures/logo.png\" }),\n    _createElementVNode(\"img\", { src: \"/fixtures/logo.png\" }),\n    _createElementVNode(\"img\", { src: \"data:image/png;base64,i\" })\n  ], 64 /* STABLE_FRAGMENT */))\n}\"\n`;\n\nexports[`compiler sfc: transform asset url > transform with stringify 1`] = `\n\"import { createElementVNode as _createElementVNode, createStaticVNode as _createStaticVNode, openBlock as _openBlock, createElementBlock as _createElementBlock } from \"vue\"\nimport _imports_0 from './bar.png'\nimport _imports_1 from '/bar.png'\n\n\nexport function render(_ctx, _cache) {\n  return (_openBlock(), _createElementBlock(\"div\", null, [...(_cache[0] || (_cache[0] = [\n    _createStaticVNode(\"<img src=\\\\\"\" + _imports_0 + \"\\\\\"><img src=\\\\\"\" + _imports_1 + \"\\\\\"><img src=\\\\\"https://foo.bar/baz.png\\\\\"><img src=\\\\\"//foo.bar/baz.png\\\\\"><img src=\\\\\"\" + _imports_0 + \"\\\\\">\", 5)\n  ]))]))\n}\"\n`;\n\nexports[`compiler sfc: transform asset url > with explicit base 1`] = `\n\"import { createElementVNode as _createElementVNode, Fragment as _Fragment, openBlock as _openBlock, createElementBlock as _createElementBlock } from \"vue\"\nimport _imports_0 from 'bar.png'\nimport _imports_1 from '@theme/bar.png'\n\n\nexport function render(_ctx, _cache) {\n  return (_openBlock(), _createElementBlock(_Fragment, null, [\n    _createElementVNode(\"img\", { src: \"/foo/bar.png\" }),\n    _createElementVNode(\"img\", { src: \"bar.png\" }),\n    _createElementVNode(\"img\", { src: _imports_0 }),\n    _createElementVNode(\"img\", { src: _imports_1 })\n  ], 64 /* STABLE_FRAGMENT */))\n}\"\n`;\n\nexports[`compiler sfc: transform asset url > with includeAbsolute: true 1`] = `\n\"import { createElementVNode as _createElementVNode, Fragment as _Fragment, openBlock as _openBlock, createElementBlock as _createElementBlock } from \"vue\"\nimport _imports_0 from './bar.png'\nimport _imports_1 from '/bar.png'\n\n\nexport function render(_ctx, _cache) {\n  return (_openBlock(), _createElementBlock(_Fragment, null, [\n    _createElementVNode(\"img\", { src: _imports_0 }),\n    _createElementVNode(\"img\", { src: _imports_1 }),\n    _createElementVNode(\"img\", { src: \"https://foo.bar/baz.png\" }),\n    _createElementVNode(\"img\", { src: \"//foo.bar/baz.png\" })\n  ], 64 /* STABLE_FRAGMENT */))\n}\"\n`;\n"
  },
  {
    "path": "packages/compiler-sfc/__tests__/__snapshots__/templateTransformSrcset.spec.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`compiler sfc: transform srcset > srcset w/ explicit base option 1`] = `\n\"import { createElementVNode as _createElementVNode, Fragment as _Fragment, openBlock as _openBlock, createElementBlock as _createElementBlock } from \"vue\"\nimport _imports_0 from '@/logo.png'\n\n\nconst _hoisted_1 = _imports_0 + ', ' + _imports_0 + ' 2x'\nconst _hoisted_2 = _imports_0 + ' 1x, ' + \"/foo/logo.png\" + ' 2x'\n\nexport function render(_ctx, _cache) {\n  return (_openBlock(), _createElementBlock(_Fragment, null, [\n    _cache[0] || (_cache[0] = _createElementVNode(\"img\", { srcset: _hoisted_1 }, null, -1 /* CACHED */)),\n    _cache[1] || (_cache[1] = _createElementVNode(\"img\", { srcset: _hoisted_2 }, null, -1 /* CACHED */))\n  ], 64 /* STABLE_FRAGMENT */))\n}\"\n`;\n\nexports[`compiler sfc: transform srcset > transform empty srcset w/ includeAbsolute: true 1`] = `\n\"import { openBlock as _openBlock, createElementBlock as _createElementBlock } from \"vue\"\n\nconst _hoisted_1 = { srcset: \" \" }\n\nexport function render(_ctx, _cache) {\n  return (_openBlock(), _createElementBlock(\"img\", _hoisted_1))\n}\"\n`;\n\nexports[`compiler sfc: transform srcset > transform srcset 1`] = `\n\"import { createElementVNode as _createElementVNode, Fragment as _Fragment, openBlock as _openBlock, createElementBlock as _createElementBlock } from \"vue\"\nimport _imports_0 from './logo.png'\n\n\nconst _hoisted_1 = _imports_0\nconst _hoisted_2 = _imports_0 + ' 2x'\nconst _hoisted_3 = _imports_0 + ' 2x'\nconst _hoisted_4 = _imports_0 + ', ' + _imports_0 + ' 2x'\nconst _hoisted_5 = _imports_0 + ' 2x, ' + _imports_0\nconst _hoisted_6 = _imports_0 + ' 2x, ' + _imports_0 + ' 3x'\nconst _hoisted_7 = _imports_0 + ', ' + _imports_0 + ' 2x, ' + _imports_0 + ' 3x'\nconst _hoisted_8 = \"/logo.png\" + ', ' + _imports_0 + ' 2x'\n\nexport function render(_ctx, _cache) {\n  return (_openBlock(), _createElementBlock(_Fragment, null, [\n    _cache[0] || (_cache[0] = _createElementVNode(\"img\", {\n      src: \"./logo.png\",\n      srcset: \"\"\n    }, null, -1 /* CACHED */)),\n    _cache[1] || (_cache[1] = _createElementVNode(\"img\", {\n      src: \"./logo.png\",\n      srcset: _hoisted_1\n    }, null, -1 /* CACHED */)),\n    _cache[2] || (_cache[2] = _createElementVNode(\"img\", {\n      src: \"./logo.png\",\n      srcset: _hoisted_2\n    }, null, -1 /* CACHED */)),\n    _cache[3] || (_cache[3] = _createElementVNode(\"img\", {\n      src: \"./logo.png\",\n      srcset: _hoisted_3\n    }, null, -1 /* CACHED */)),\n    _cache[4] || (_cache[4] = _createElementVNode(\"img\", {\n      src: \"./logo.png\",\n      srcset: _hoisted_4\n    }, null, -1 /* CACHED */)),\n    _cache[5] || (_cache[5] = _createElementVNode(\"img\", {\n      src: \"./logo.png\",\n      srcset: _hoisted_5\n    }, null, -1 /* CACHED */)),\n    _cache[6] || (_cache[6] = _createElementVNode(\"img\", {\n      src: \"./logo.png\",\n      srcset: _hoisted_6\n    }, null, -1 /* CACHED */)),\n    _cache[7] || (_cache[7] = _createElementVNode(\"img\", {\n      src: \"./logo.png\",\n      srcset: _hoisted_7\n    }, null, -1 /* CACHED */)),\n    _cache[8] || (_cache[8] = _createElementVNode(\"img\", {\n      src: \"/logo.png\",\n      srcset: \"/logo.png, /logo.png 2x\"\n    }, null, -1 /* CACHED */)),\n    _cache[9] || (_cache[9] = _createElementVNode(\"img\", {\n      src: \"https://example.com/logo.png\",\n      srcset: \"https://example.com/logo.png, https://example.com/logo.png 2x\"\n    }, null, -1 /* CACHED */)),\n    _cache[10] || (_cache[10] = _createElementVNode(\"img\", {\n      src: \"/logo.png\",\n      srcset: _hoisted_8\n    }, null, -1 /* CACHED */)),\n    _cache[11] || (_cache[11] = _createElementVNode(\"img\", {\n      src: \"data:image/png;base64,i\",\n      srcset: \"data:image/png;base64,i 1x, data:image/png;base64,i 2x\"\n    }, null, -1 /* CACHED */))\n  ], 64 /* STABLE_FRAGMENT */))\n}\"\n`;\n\nexports[`compiler sfc: transform srcset > transform srcset w/ base 1`] = `\n\"import { createElementVNode as _createElementVNode, Fragment as _Fragment, openBlock as _openBlock, createElementBlock as _createElementBlock } from \"vue\"\n\nexport function render(_ctx, _cache) {\n  return (_openBlock(), _createElementBlock(_Fragment, null, [\n    _cache[0] || (_cache[0] = _createElementVNode(\"img\", {\n      src: \"./logo.png\",\n      srcset: \"\"\n    }, null, -1 /* CACHED */)),\n    _cache[1] || (_cache[1] = _createElementVNode(\"img\", {\n      src: \"./logo.png\",\n      srcset: \"/foo/logo.png\"\n    }, null, -1 /* CACHED */)),\n    _cache[2] || (_cache[2] = _createElementVNode(\"img\", {\n      src: \"./logo.png\",\n      srcset: \"/foo/logo.png 2x\"\n    }, null, -1 /* CACHED */)),\n    _cache[3] || (_cache[3] = _createElementVNode(\"img\", {\n      src: \"./logo.png\",\n      srcset: \"/foo/logo.png 2x\"\n    }, null, -1 /* CACHED */)),\n    _cache[4] || (_cache[4] = _createElementVNode(\"img\", {\n      src: \"./logo.png\",\n      srcset: \"/foo/logo.png, /foo/logo.png 2x\"\n    }, null, -1 /* CACHED */)),\n    _cache[5] || (_cache[5] = _createElementVNode(\"img\", {\n      src: \"./logo.png\",\n      srcset: \"/foo/logo.png 2x, /foo/logo.png\"\n    }, null, -1 /* CACHED */)),\n    _cache[6] || (_cache[6] = _createElementVNode(\"img\", {\n      src: \"./logo.png\",\n      srcset: \"/foo/logo.png 2x, /foo/logo.png 3x\"\n    }, null, -1 /* CACHED */)),\n    _cache[7] || (_cache[7] = _createElementVNode(\"img\", {\n      src: \"./logo.png\",\n      srcset: \"/foo/logo.png, /foo/logo.png 2x, /foo/logo.png 3x\"\n    }, null, -1 /* CACHED */)),\n    _cache[8] || (_cache[8] = _createElementVNode(\"img\", {\n      src: \"/logo.png\",\n      srcset: \"/logo.png, /logo.png 2x\"\n    }, null, -1 /* CACHED */)),\n    _cache[9] || (_cache[9] = _createElementVNode(\"img\", {\n      src: \"https://example.com/logo.png\",\n      srcset: \"https://example.com/logo.png, https://example.com/logo.png 2x\"\n    }, null, -1 /* CACHED */)),\n    _cache[10] || (_cache[10] = _createElementVNode(\"img\", {\n      src: \"/logo.png\",\n      srcset: \"/logo.png, /foo/logo.png 2x\"\n    }, null, -1 /* CACHED */)),\n    _cache[11] || (_cache[11] = _createElementVNode(\"img\", {\n      src: \"data:image/png;base64,i\",\n      srcset: \"data:image/png;base64,i 1x, data:image/png;base64,i 2x\"\n    }, null, -1 /* CACHED */))\n  ], 64 /* STABLE_FRAGMENT */))\n}\"\n`;\n\nexports[`compiler sfc: transform srcset > transform srcset w/ includeAbsolute: true 1`] = `\n\"import { createElementVNode as _createElementVNode, Fragment as _Fragment, openBlock as _openBlock, createElementBlock as _createElementBlock } from \"vue\"\nimport _imports_0 from './logo.png'\nimport _imports_1 from '/logo.png'\n\n\nconst _hoisted_1 = _imports_0\nconst _hoisted_2 = _imports_0 + ' 2x'\nconst _hoisted_3 = _imports_0 + ' 2x'\nconst _hoisted_4 = _imports_0 + ', ' + _imports_0 + ' 2x'\nconst _hoisted_5 = _imports_0 + ' 2x, ' + _imports_0\nconst _hoisted_6 = _imports_0 + ' 2x, ' + _imports_0 + ' 3x'\nconst _hoisted_7 = _imports_0 + ', ' + _imports_0 + ' 2x, ' + _imports_0 + ' 3x'\nconst _hoisted_8 = _imports_1 + ', ' + _imports_1 + ' 2x'\nconst _hoisted_9 = _imports_1 + ', ' + _imports_0 + ' 2x'\n\nexport function render(_ctx, _cache) {\n  return (_openBlock(), _createElementBlock(_Fragment, null, [\n    _cache[0] || (_cache[0] = _createElementVNode(\"img\", {\n      src: \"./logo.png\",\n      srcset: \"\"\n    }, null, -1 /* CACHED */)),\n    _cache[1] || (_cache[1] = _createElementVNode(\"img\", {\n      src: \"./logo.png\",\n      srcset: _hoisted_1\n    }, null, -1 /* CACHED */)),\n    _cache[2] || (_cache[2] = _createElementVNode(\"img\", {\n      src: \"./logo.png\",\n      srcset: _hoisted_2\n    }, null, -1 /* CACHED */)),\n    _cache[3] || (_cache[3] = _createElementVNode(\"img\", {\n      src: \"./logo.png\",\n      srcset: _hoisted_3\n    }, null, -1 /* CACHED */)),\n    _cache[4] || (_cache[4] = _createElementVNode(\"img\", {\n      src: \"./logo.png\",\n      srcset: _hoisted_4\n    }, null, -1 /* CACHED */)),\n    _cache[5] || (_cache[5] = _createElementVNode(\"img\", {\n      src: \"./logo.png\",\n      srcset: _hoisted_5\n    }, null, -1 /* CACHED */)),\n    _cache[6] || (_cache[6] = _createElementVNode(\"img\", {\n      src: \"./logo.png\",\n      srcset: _hoisted_6\n    }, null, -1 /* CACHED */)),\n    _cache[7] || (_cache[7] = _createElementVNode(\"img\", {\n      src: \"./logo.png\",\n      srcset: _hoisted_7\n    }, null, -1 /* CACHED */)),\n    _cache[8] || (_cache[8] = _createElementVNode(\"img\", {\n      src: \"/logo.png\",\n      srcset: _hoisted_8\n    }, null, -1 /* CACHED */)),\n    _cache[9] || (_cache[9] = _createElementVNode(\"img\", {\n      src: \"https://example.com/logo.png\",\n      srcset: \"https://example.com/logo.png, https://example.com/logo.png 2x\"\n    }, null, -1 /* CACHED */)),\n    _cache[10] || (_cache[10] = _createElementVNode(\"img\", {\n      src: \"/logo.png\",\n      srcset: _hoisted_9\n    }, null, -1 /* CACHED */)),\n    _cache[11] || (_cache[11] = _createElementVNode(\"img\", {\n      src: \"data:image/png;base64,i\",\n      srcset: \"data:image/png;base64,i 1x, data:image/png;base64,i 2x\"\n    }, null, -1 /* CACHED */))\n  ], 64 /* STABLE_FRAGMENT */))\n}\"\n`;\n\nexports[`compiler sfc: transform srcset > transform srcset w/ stringify 1`] = `\n\"import { createElementVNode as _createElementVNode, createStaticVNode as _createStaticVNode, openBlock as _openBlock, createElementBlock as _createElementBlock } from \"vue\"\nimport _imports_0 from './logo.png'\nimport _imports_1 from '/logo.png'\n\n\nconst _hoisted_1 = _imports_0\nconst _hoisted_2 = _imports_0 + ' 2x'\nconst _hoisted_3 = _imports_0 + ' 2x'\nconst _hoisted_4 = _imports_0 + ', ' + _imports_0 + ' 2x'\nconst _hoisted_5 = _imports_0 + ' 2x, ' + _imports_0\nconst _hoisted_6 = _imports_0 + ' 2x, ' + _imports_0 + ' 3x'\nconst _hoisted_7 = _imports_0 + ', ' + _imports_0 + ' 2x, ' + _imports_0 + ' 3x'\nconst _hoisted_8 = _imports_1 + ', ' + _imports_1 + ' 2x'\nconst _hoisted_9 = _imports_1 + ', ' + _imports_0 + ' 2x'\n\nexport function render(_ctx, _cache) {\n  return (_openBlock(), _createElementBlock(\"div\", null, [...(_cache[0] || (_cache[0] = [\n    _createStaticVNode(\"<img src=\\\\\"./logo.png\\\\\" srcset=\\\\\"\\\\\"><img src=\\\\\"./logo.png\\\\\" srcset=\\\\\"\" + _hoisted_1 + \"\\\\\"><img src=\\\\\"./logo.png\\\\\" srcset=\\\\\"\" + _hoisted_2 + \"\\\\\"><img src=\\\\\"./logo.png\\\\\" srcset=\\\\\"\" + _hoisted_3 + \"\\\\\"><img src=\\\\\"./logo.png\\\\\" srcset=\\\\\"\" + _hoisted_4 + \"\\\\\"><img src=\\\\\"./logo.png\\\\\" srcset=\\\\\"\" + _hoisted_5 + \"\\\\\"><img src=\\\\\"./logo.png\\\\\" srcset=\\\\\"\" + _hoisted_6 + \"\\\\\"><img src=\\\\\"./logo.png\\\\\" srcset=\\\\\"\" + _hoisted_7 + \"\\\\\"><img src=\\\\\"/logo.png\\\\\" srcset=\\\\\"\" + _hoisted_8 + \"\\\\\"><img src=\\\\\"https://example.com/logo.png\\\\\" srcset=\\\\\"https://example.com/logo.png, https://example.com/logo.png 2x\\\\\"><img src=\\\\\"/logo.png\\\\\" srcset=\\\\\"\" + _hoisted_9 + \"\\\\\"><img src=\\\\\"data:image/png;base64,i\\\\\" srcset=\\\\\"data:image/png;base64,i 1x, data:image/png;base64,i 2x\\\\\">\", 12)\n  ]))]))\n}\"\n`;\n"
  },
  {
    "path": "packages/compiler-sfc/__tests__/compileScript/__snapshots__/defineEmits.spec.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`defineEmits > basic usage 1`] = `\n\"\nexport default {\n  emits: ['foo', 'bar'],\n  setup(__props, { expose: __expose, emit: __emit }) {\n  __expose();\n\nconst myEmit = __emit\n\nreturn { myEmit }\n}\n\n}\"\n`;\n\nexports[`defineEmits > w/ runtime options 1`] = `\n\"import { defineComponent as _defineComponent } from 'vue'\n\nexport default /*@__PURE__*/_defineComponent({\n  emits: ['a', 'b'],\n  setup(__props, { expose: __expose, emit: __emit }) {\n  __expose();\n\nconst emit = __emit\n\nreturn { emit }\n}\n\n})\"\n`;\n\nexports[`defineEmits > w/ type (exported interface) 1`] = `\n\"import { defineComponent as _defineComponent } from 'vue'\nexport interface Emits { (e: 'foo' | 'bar'): void }\n    \nexport default /*@__PURE__*/_defineComponent({\n  emits: [\"foo\", \"bar\"],\n  setup(__props, { expose: __expose, emit: __emit }) {\n  __expose();\n\n    const emit = __emit\n    \nreturn { emit }\n}\n\n})\"\n`;\n\nexports[`defineEmits > w/ type (exported type alias) 1`] = `\n\"import { defineComponent as _defineComponent } from 'vue'\nexport type Emits = { (e: 'foo' | 'bar'): void }\n    \nexport default /*@__PURE__*/_defineComponent({\n  emits: [\"foo\", \"bar\"],\n  setup(__props, { expose: __expose, emit: __emit }) {\n  __expose();\n\n    const emit = __emit\n    \nreturn { emit }\n}\n\n})\"\n`;\n\nexports[`defineEmits > w/ type (interface ts type) 1`] = `\n\"import { defineComponent as _defineComponent } from 'vue'\ninterface Emits { (e: 'foo'): void }\n    \nexport default /*@__PURE__*/_defineComponent({\n  emits: ['foo'],\n  setup(__props, { expose: __expose, emit: __emit }) {\n  __expose();\n\n    const emit: Emits = __emit\n    \nreturn { emit }\n}\n\n})\"\n`;\n\nexports[`defineEmits > w/ type (interface w/ extends) 1`] = `\n\"import { defineComponent as _defineComponent } from 'vue'\ninterface Base { (e: 'foo'): void }\n    interface Emits extends Base { (e: 'bar'): void }\n    \nexport default /*@__PURE__*/_defineComponent({\n  emits: [\"bar\", \"foo\"],\n  setup(__props, { expose: __expose, emit: __emit }) {\n  __expose();\n\n    const emit = __emit\n    \nreturn { emit }\n}\n\n})\"\n`;\n\nexports[`defineEmits > w/ type (interface) 1`] = `\n\"import { defineComponent as _defineComponent } from 'vue'\ninterface Emits { (e: 'foo' | 'bar'): void }\n    \nexport default /*@__PURE__*/_defineComponent({\n  emits: [\"foo\", \"bar\"],\n  setup(__props, { expose: __expose, emit: __emit }) {\n  __expose();\n\n    const emit = __emit\n    \nreturn { emit }\n}\n\n})\"\n`;\n\nexports[`defineEmits > w/ type (property syntax string literal) 1`] = `\n\"import { defineComponent as _defineComponent } from 'vue'\n\nexport default /*@__PURE__*/_defineComponent({\n  emits: [\"foo:bar\"],\n  setup(__props, { expose: __expose, emit: __emit }) {\n  __expose();\n\n    const emit = __emit\n    \nreturn { emit }\n}\n\n})\"\n`;\n\nexports[`defineEmits > w/ type (property syntax) 1`] = `\n\"import { defineComponent as _defineComponent } from 'vue'\n\nexport default /*@__PURE__*/_defineComponent({\n  emits: [\"foo\", \"bar\"],\n  setup(__props, { expose: __expose, emit: __emit }) {\n  __expose();\n\n    const emit = __emit\n    \nreturn { emit }\n}\n\n})\"\n`;\n\nexports[`defineEmits > w/ type (referenced exported function type) 1`] = `\n\"import { defineComponent as _defineComponent } from 'vue'\nexport type Emits = (e: 'foo' | 'bar') => void\n    \nexport default /*@__PURE__*/_defineComponent({\n  emits: [\"foo\", \"bar\"],\n  setup(__props, { expose: __expose, emit: __emit }) {\n  __expose();\n\n    const emit = __emit\n    \nreturn { emit }\n}\n\n})\"\n`;\n\nexports[`defineEmits > w/ type (referenced function type) 1`] = `\n\"import { defineComponent as _defineComponent } from 'vue'\ntype Emits = (e: 'foo' | 'bar') => void\n    \nexport default /*@__PURE__*/_defineComponent({\n  emits: [\"foo\", \"bar\"],\n  setup(__props, { expose: __expose, emit: __emit }) {\n  __expose();\n\n    const emit = __emit\n    \nreturn { emit }\n}\n\n})\"\n`;\n\nexports[`defineEmits > w/ type (type alias) 1`] = `\n\"import { defineComponent as _defineComponent } from 'vue'\ntype Emits = { (e: 'foo' | 'bar'): void }\n    \nexport default /*@__PURE__*/_defineComponent({\n  emits: [\"foo\", \"bar\"],\n  setup(__props, { expose: __expose, emit: __emit }) {\n  __expose();\n\n    const emit = __emit\n    \nreturn { emit }\n}\n\n})\"\n`;\n\nexports[`defineEmits > w/ type (type literal w/ call signatures) 1`] = `\n\"import { defineComponent as _defineComponent } from 'vue'\n\nexport default /*@__PURE__*/_defineComponent({\n  emits: [\"foo\", \"bar\", \"baz\"],\n  setup(__props, { expose: __expose, emit: __emit }) {\n  __expose();\n\n    const emit = __emit\n    \nreturn { emit }\n}\n\n})\"\n`;\n\nexports[`defineEmits > w/ type (type references in union) 1`] = `\n\"import { defineComponent as _defineComponent } from 'vue'\ntype BaseEmit = \"change\"\n    type Emit = \"some\" | \"emit\" | BaseEmit\n    \nexport default /*@__PURE__*/_defineComponent({\n  emits: [\"some\", \"emit\", \"change\", \"another\"],\n  setup(__props, { expose: __expose, emit: __emit }) {\n  __expose();\n\n    const emit = __emit;\n    \nreturn { emit }\n}\n\n})\"\n`;\n\nexports[`defineEmits > w/ type (union) 1`] = `\n\"import { defineComponent as _defineComponent } from 'vue'\n\nexport default /*@__PURE__*/_defineComponent({\n  emits: [\"foo\", \"bar\", \"baz\"],\n  setup(__props, { expose: __expose, emit: __emit }) {\n  __expose();\n\n    const emit = __emit\n    \nreturn { emit }\n}\n\n})\"\n`;\n\nexports[`defineEmits > w/ type 1`] = `\n\"import { defineComponent as _defineComponent } from 'vue'\n\nexport default /*@__PURE__*/_defineComponent({\n  emits: [\"foo\", \"bar\"],\n  setup(__props, { expose: __expose, emit: __emit }) {\n  __expose();\n\n    const emit = __emit\n    \nreturn { emit }\n}\n\n})\"\n`;\n\nexports[`defineEmits > w/ type from normal script 1`] = `\n\"import { defineComponent as _defineComponent } from 'vue'\n\n      export interface Emits { (e: 'foo' | 'bar'): void }\n    \nexport default /*@__PURE__*/_defineComponent({\n  emits: [\"foo\", \"bar\"],\n  setup(__props, { expose: __expose, emit: __emit }) {\n  __expose();\n\n    const emit = __emit\n    \nreturn { emit }\n}\n\n})\"\n`;\n"
  },
  {
    "path": "packages/compiler-sfc/__tests__/compileScript/__snapshots__/defineExpose.spec.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`<script> after <script setup> the script content not end with \\`\\\\n\\` 1`] = `\n\"import { x } from './x'\n  const n = 1\n\nexport default {\n  setup(__props, { expose: __expose }) {\n  __expose();\n\n  \nreturn { n, get x() { return x } }\n}\n\n}\"\n`;\n\nexports[`defineExpose() 1`] = `\n\"\nexport default {\n  setup(__props, { expose: __expose }) {\n\n__expose({ foo: 123 })\n\nreturn {  }\n}\n\n}\"\n`;\n"
  },
  {
    "path": "packages/compiler-sfc/__tests__/compileScript/__snapshots__/defineModel.spec.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`defineModel() > basic usage 1`] = `\n\"import { useModel as _useModel } from 'vue'\n\nexport default {\n  props: {\n    \"modelValue\": { required: true },\n    \"modelModifiers\": {},\n    \"count\": {},\n    \"countModifiers\": {},\n    \"toString\": { type: Function },\n    \"toStringModifiers\": {},\n  },\n  emits: [\"update:modelValue\", \"update:count\", \"update:toString\"],\n  setup(__props, { expose: __expose }) {\n  __expose();\n\n      const modelValue = _useModel(__props, \"modelValue\")\n      const c = _useModel(__props, 'count')\n      const toString = _useModel(__props, 'toString')\n      \nreturn { modelValue, c, toString }\n}\n\n}\"\n`;\n\nexports[`defineModel() > get / set transformers 1`] = `\n\"import { useModel as _useModel, defineComponent as _defineComponent } from 'vue'\n\nexport default /*@__PURE__*/_defineComponent({\n  props: {\n    \"modelValue\": {\n        required: true\n      },\n    \"modelModifiers\": {},\n  },\n  emits: [\"update:modelValue\"],\n  setup(__props, { expose: __expose }) {\n  __expose();\n\n      const modelValue = _useModel(__props, \"modelValue\", {\n        get(v) { return v - 1 },\n        set: (v) => { return v + 1 },\n        })\n      \nreturn { modelValue }\n}\n\n})\"\n`;\n\nexports[`defineModel() > get / set transformers 2`] = `\n\"import { useModel as _useModel, defineComponent as _defineComponent } from 'vue'\n\nexport default /*@__PURE__*/_defineComponent({\n  props: {\n    \"modelValue\": {\n        default: 0,\n        required: true,\n        },\n    \"modelModifiers\": {},\n  },\n  emits: [\"update:modelValue\"],\n  setup(__props, { expose: __expose }) {\n  __expose();\n\n      const modelValue = _useModel(__props, \"modelValue\", {\n        get(v) { return v - 1 },\n        set: (v) => { return v + 1 },\n      })\n      \nreturn { modelValue }\n}\n\n})\"\n`;\n\nexports[`defineModel() > usage w/ props destructure 1`] = `\n\"import { useModel as _useModel, mergeModels as _mergeModels, defineComponent as _defineComponent } from 'vue'\n\nexport default /*@__PURE__*/_defineComponent({\n  props: /*@__PURE__*/_mergeModels({\n    x: { type: Number, required: true }\n  }, {\n    \"modelValue\": {\n        },\n    \"modelModifiers\": {},\n  }),\n  emits: [\"update:modelValue\"],\n  setup(__props: any, { expose: __expose }) {\n  __expose();\n\n      \n      const modelValue = _useModel(__props, \"modelValue\", {\n        set: (v) => { return v + __props.x }\n      })\n      \nreturn { modelValue }\n}\n\n})\"\n`;\n\nexports[`defineModel() > w/ Boolean And Function types, production mode 1`] = `\n\"import { useModel as _useModel, defineComponent as _defineComponent } from 'vue'\n\nexport default /*@__PURE__*/_defineComponent({\n  props: {\n    \"modelValue\": { type: [Boolean, String] },\n    \"modelModifiers\": {},\n  },\n  emits: [\"update:modelValue\"],\n  setup(__props, { expose: __expose }) {\n  __expose();\n\n      const modelValue = _useModel<boolean | string>(__props, \"modelValue\")\n      \nreturn { modelValue }\n}\n\n})\"\n`;\n\nexports[`defineModel() > w/ array props 1`] = `\n\"import { useModel as _useModel, mergeModels as _mergeModels } from 'vue'\n\nexport default {\n  props: /*@__PURE__*/_mergeModels(['foo', 'bar'], {\n    \"count\": {},\n    \"countModifiers\": {},\n  }),\n  emits: [\"update:count\"],\n  setup(__props, { expose: __expose }) {\n  __expose();\n\n      \n      const count = _useModel(__props, 'count')\n      \nreturn { count }\n}\n\n}\"\n`;\n\nexports[`defineModel() > w/ defineProps and defineEmits 1`] = `\n\"import { useModel as _useModel, mergeModels as _mergeModels } from 'vue'\n\nexport default {\n  props: /*@__PURE__*/_mergeModels({ foo: String }, {\n    \"modelValue\": { default: 0 },\n    \"modelModifiers\": {},\n  }),\n  emits: /*@__PURE__*/_mergeModels(['change'], [\"update:modelValue\"]),\n  setup(__props, { expose: __expose }) {\n  __expose();\n\n      \n      \n      const count = _useModel(__props, \"modelValue\")\n      \nreturn { count }\n}\n\n}\"\n`;\n\nexports[`defineModel() > w/ types, basic usage 1`] = `\n\"import { useModel as _useModel, defineComponent as _defineComponent } from 'vue'\n\nexport default /*@__PURE__*/_defineComponent({\n  props: {\n    \"modelValue\": { type: [Boolean, String] },\n    \"modelModifiers\": {},\n    \"count\": { type: Number },\n    \"countModifiers\": {},\n    \"disabled\": { type: Number, ...{ required: false } },\n    \"disabledModifiers\": {},\n    \"any\": { type: Boolean, skipCheck: true },\n    \"anyModifiers\": {},\n  },\n  emits: [\"update:modelValue\", \"update:count\", \"update:disabled\", \"update:any\"],\n  setup(__props, { expose: __expose }) {\n  __expose();\n\n      const modelValue = _useModel<boolean | string>(__props, \"modelValue\")\n      const count = _useModel<number>(__props, 'count')\n      const disabled = _useModel<number>(__props, 'disabled')\n      const any = _useModel<any | boolean>(__props, 'any')\n      \nreturn { modelValue, count, disabled, any }\n}\n\n})\"\n`;\n\nexports[`defineModel() > w/ types, production mode 1`] = `\n\"import { useModel as _useModel, defineComponent as _defineComponent } from 'vue'\n\nexport default /*@__PURE__*/_defineComponent({\n  props: {\n    \"modelValue\": { type: Boolean },\n    \"modelModifiers\": {},\n    \"fn\": {},\n    \"fnModifiers\": {},\n    \"fnWithDefault\": { type: Function, ...{ default: () => null } },\n    \"fnWithDefaultModifiers\": {},\n    \"str\": {},\n    \"strModifiers\": {},\n    \"optional\": { required: false },\n    \"optionalModifiers\": {},\n  },\n  emits: [\"update:modelValue\", \"update:fn\", \"update:fnWithDefault\", \"update:str\", \"update:optional\"],\n  setup(__props, { expose: __expose }) {\n  __expose();\n\n      const modelValue = _useModel<boolean>(__props, \"modelValue\")\n      const fn = _useModel<() => void>(__props, 'fn')\n      const fnWithDefault = _useModel<() => void>(__props, 'fnWithDefault')\n      const str = _useModel<string>(__props, 'str')\n      const optional = _useModel<string>(__props, 'optional')\n      \nreturn { modelValue, fn, fnWithDefault, str, optional }\n}\n\n})\"\n`;\n\nexports[`defineModel() > w/ types, production mode, boolean + multiple types 1`] = `\n\"import { useModel as _useModel, defineComponent as _defineComponent } from 'vue'\n\nexport default /*@__PURE__*/_defineComponent({\n  props: {\n    \"modelValue\": { type: [Boolean, String, Object] },\n    \"modelModifiers\": {},\n  },\n  emits: [\"update:modelValue\"],\n  setup(__props, { expose: __expose }) {\n  __expose();\n\n      const modelValue = _useModel<boolean | string | {}>(__props, \"modelValue\")\n      \nreturn { modelValue }\n}\n\n})\"\n`;\n\nexports[`defineModel() > w/ types, production mode, function + runtime opts + multiple types 1`] = `\n\"import { useModel as _useModel, defineComponent as _defineComponent } from 'vue'\n\nexport default /*@__PURE__*/_defineComponent({\n  props: {\n    \"modelValue\": { type: [Number, Function], ...{ default: () => 1 } },\n    \"modelModifiers\": {},\n  },\n  emits: [\"update:modelValue\"],\n  setup(__props, { expose: __expose }) {\n  __expose();\n\n      const modelValue = _useModel<number | (() => number)>(__props, \"modelValue\")\n      \nreturn { modelValue }\n}\n\n})\"\n`;\n"
  },
  {
    "path": "packages/compiler-sfc/__tests__/compileScript/__snapshots__/defineOptions.spec.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`defineOptions() > basic usage 1`] = `\n\"\nexport default /*@__PURE__*/Object.assign({ name: 'FooApp' }, {\n  setup(__props, { expose: __expose }) {\n  __expose();\n\n      \n      \nreturn {  }\n}\n\n})\"\n`;\n\nexports[`defineOptions() > empty argument 1`] = `\n\"\nexport default {\n  setup(__props, { expose: __expose }) {\n  __expose();\n\n      \n      \nreturn {  }\n}\n\n}\"\n`;\n"
  },
  {
    "path": "packages/compiler-sfc/__tests__/compileScript/__snapshots__/defineProps.spec.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`defineProps > basic usage 1`] = `\n\"const bar = 1\n\nexport default {\n  props: {\n  foo: String\n},\n  setup(__props, { expose: __expose }) {\n  __expose();\n\nconst props = __props\n\nreturn { props, bar }\n}\n\n}\"\n`;\n\nexports[`defineProps > custom element retains the props type & default value & production mode 1`] = `\n\"import { defineComponent as _defineComponent } from 'vue'\ninterface Props { \n          foo?: number;\n      }\n      \nexport default /*@__PURE__*/_defineComponent({\n  __name: 'app.ce',\n  props: {\n    foo: { default: 5.5, type: Number }\n  },\n  setup(__props: any, { expose: __expose }) {\n  __expose();\n\n      const props = __props;\n      \nreturn { props }\n}\n\n})\"\n`;\n\nexports[`defineProps > custom element retains the props type & production mode 1`] = `\n\"import { defineComponent as _defineComponent } from 'vue'\n\nexport default /*@__PURE__*/_defineComponent({\n  __name: 'app.ce',\n  props: {\n    foo: {type: Number}\n  },\n  setup(__props: any, { expose: __expose }) {\n  __expose();\n\n      const props = __props\n      \nreturn { props }\n}\n\n})\"\n`;\n\nexports[`defineProps > defineProps w/ runtime options 1`] = `\n\"import { defineComponent as _defineComponent } from 'vue'\n\nexport default /*@__PURE__*/_defineComponent({\n  props: { foo: String },\n  setup(__props, { expose: __expose }) {\n  __expose();\n\nconst props = __props\n\nreturn { props }\n}\n\n})\"\n`;\n\nexports[`defineProps > destructure without enabling reactive destructure 1`] = `\n\"import { defineComponent as _defineComponent } from 'vue'\n\nexport default /*@__PURE__*/_defineComponent({\n  props: {\n    foo: { type: null, required: true }\n  },\n  setup(__props: any, { expose: __expose }) {\n  __expose();\n\n      const { foo } = __props\n      \nreturn { foo }\n}\n\n})\"\n`;\n\nexports[`defineProps > should escape names w/ special symbols 1`] = `\n\"import { defineComponent as _defineComponent } from 'vue'\n\nexport default /*@__PURE__*/_defineComponent({\n  props: {\n    \"spa ce\": { type: null, required: true },\n    \"exclamation!mark\": { type: null, required: true },\n    \"double\\\\\"quote\": { type: null, required: true },\n    \"hash#tag\": { type: null, required: true },\n    \"dollar$sign\": { type: null, required: true },\n    \"percentage%sign\": { type: null, required: true },\n    \"amper&sand\": { type: null, required: true },\n    \"single'quote\": { type: null, required: true },\n    \"round(brack)ets\": { type: null, required: true },\n    \"aste*risk\": { type: null, required: true },\n    \"pl+us\": { type: null, required: true },\n    \"com,ma\": { type: null, required: true },\n    \"do.t\": { type: null, required: true },\n    \"sla/sh\": { type: null, required: true },\n    \"co:lon\": { type: null, required: true },\n    \"semi;colon\": { type: null, required: true },\n    \"angle<brack>ets\": { type: null, required: true },\n    \"equal=sign\": { type: null, required: true },\n    \"question?mark\": { type: null, required: true },\n    \"at@sign\": { type: null, required: true },\n    \"square[brack]ets\": { type: null, required: true },\n    \"back\\\\\\\\slash\": { type: null, required: true },\n    \"ca^ret\": { type: null, required: true },\n    \"back\\`tick\": { type: null, required: true },\n    \"curly{bra}ces\": { type: null, required: true },\n    \"pi|pe\": { type: null, required: true },\n    \"til~de\": { type: null, required: true },\n    \"da-sh\": { type: null, required: true }\n  },\n  setup(__props: any, { expose: __expose }) {\n  __expose();\n\n    \n    \nreturn {  }\n}\n\n})\"\n`;\n\nexports[`defineProps > w/ TS assertion 1`] = `\n\"import { defineComponent as _defineComponent } from 'vue'\n\nexport default /*@__PURE__*/_defineComponent({\n  props: ['foo'],\n  setup(__props, { expose: __expose }) {\n  __expose();\n\n      \n    \nreturn {  }\n}\n\n})\"\n`;\n\nexports[`defineProps > w/ exported interface 1`] = `\n\"import { defineComponent as _defineComponent } from 'vue'\nexport interface Props { x?: number }\n    \nexport default /*@__PURE__*/_defineComponent({\n  props: {\n    x: { type: Number, required: false }\n  },\n  setup(__props: any, { expose: __expose }) {\n  __expose();\n\n    \n    \nreturn {  }\n}\n\n})\"\n`;\n\nexports[`defineProps > w/ exported interface in normal script 1`] = `\n\"import { defineComponent as _defineComponent } from 'vue'\n\n      export interface Props { x?: number }\n    \nexport default /*@__PURE__*/_defineComponent({\n  props: {\n    x: { type: Number, required: false }\n  },\n  setup(__props: any, { expose: __expose }) {\n  __expose();\n\n      \n    \nreturn {  }\n}\n\n})\"\n`;\n\nexports[`defineProps > w/ exported type alias 1`] = `\n\"import { defineComponent as _defineComponent } from 'vue'\nexport type Props = { x?: number }\n    \nexport default /*@__PURE__*/_defineComponent({\n  props: {\n    x: { type: Number, required: false }\n  },\n  setup(__props: any, { expose: __expose }) {\n  __expose();\n\n    \n    \nreturn {  }\n}\n\n})\"\n`;\n\nexports[`defineProps > w/ extends interface 1`] = `\n\"import { defineComponent as _defineComponent } from 'vue'\ninterface Bar extends Foo { y?: number }\n      interface Props extends Bar {\n        z: number\n        y: string\n      }\n      \n      interface Foo { x?: number }\n    \nexport default /*@__PURE__*/_defineComponent({\n  props: {\n    z: { type: Number, required: true },\n    y: { type: String, required: true },\n    x: { type: Number, required: false }\n  },\n  setup(__props: any, { expose: __expose }) {\n  __expose();\n\n      \n    \nreturn {  }\n}\n\n})\"\n`;\n\nexports[`defineProps > w/ extends intersection type 1`] = `\n\"import { defineComponent as _defineComponent } from 'vue'\ntype Foo = {\n        x?: number;\n      };\n      interface Props extends Foo {\n        z: number\n        y: string\n      }\n      \nexport default /*@__PURE__*/_defineComponent({\n  props: {\n    z: { type: Number, required: true },\n    y: { type: String, required: true },\n    x: { type: Number, required: false }\n  },\n  setup(__props: any, { expose: __expose }) {\n  __expose();\n\n      \n    \nreturn {  }\n}\n\n})\"\n`;\n\nexports[`defineProps > w/ external definition 1`] = `\n\"import { propsModel } from './props'\n    \nexport default {\n  props: propsModel,\n  setup(__props, { expose: __expose }) {\n  __expose();\n\n    const props = __props\n    \nreturn { props, get propsModel() { return propsModel } }\n}\n\n}\"\n`;\n\nexports[`defineProps > w/ interface 1`] = `\n\"import { defineComponent as _defineComponent } from 'vue'\ninterface Props { x?: number }\n    \nexport default /*@__PURE__*/_defineComponent({\n  props: {\n    x: { type: Number, required: false }\n  },\n  setup(__props: any, { expose: __expose }) {\n  __expose();\n\n    \n    \nreturn {  }\n}\n\n})\"\n`;\n\nexports[`defineProps > w/ intersection type 1`] = `\n\"import { defineComponent as _defineComponent } from 'vue'\ntype Foo = {\n        x?: number;\n      };\n      type Bar = {\n        y: string;\n      };\n      \nexport default /*@__PURE__*/_defineComponent({\n  props: {\n    x: { type: Number, required: false },\n    y: { type: String, required: true }\n  },\n  setup(__props: any, { expose: __expose }) {\n  __expose();\n\n      \n    \nreturn {  }\n}\n\n})\"\n`;\n\nexports[`defineProps > w/ leading code 1`] = `\n\"import { x } from './x'\n    \nexport default {\n  props: {},\n  setup(__props, { expose: __expose }) {\n  __expose();\nconst props = __props\n    \nreturn { props, get x() { return x } }\n}\n\n}\"\n`;\n\nexports[`defineProps > w/ type 1`] = `\n\"import { defineComponent as _defineComponent } from 'vue'\ninterface Test {}\n\n    type Alias = number[]\n\n    \nexport default /*@__PURE__*/_defineComponent({\n  props: {\n    string: { type: String, required: true },\n    number: { type: Number, required: true },\n    boolean: { type: Boolean, required: true },\n    object: { type: Object, required: true },\n    objectLiteral: { type: Object, required: true },\n    fn: { type: Function, required: true },\n    functionRef: { type: Function, required: true },\n    objectRef: { type: Object, required: true },\n    dateTime: { type: Date, required: true },\n    array: { type: Array, required: true },\n    arrayRef: { type: Array, required: true },\n    tuple: { type: Array, required: true },\n    set: { type: Set, required: true },\n    literal: { type: String, required: true },\n    optional: { type: null, required: false },\n    recordRef: { type: Object, required: true },\n    interface: { type: Object, required: true },\n    alias: { type: Array, required: true },\n    method: { type: Function, required: true },\n    symbol: { type: Symbol, required: true },\n    error: { type: Error, required: true },\n    extract: { type: Number, required: true },\n    exclude: { type: [Number, Boolean], required: true },\n    uppercase: { type: String, required: true },\n    params: { type: Array, required: true },\n    nonNull: { type: String, required: true },\n    objectOrFn: { type: [Function, Object], required: true },\n    union: { type: [String, Number], required: true },\n    literalUnion: { type: String, required: true },\n    literalUnionNumber: { type: Number, required: true },\n    literalUnionMixed: { type: [String, Number, Boolean], required: true },\n    intersection: { type: Object, required: true },\n    intersection2: { type: String, required: true },\n    foo: { type: [Function, null], required: true },\n    unknown: { type: null, required: true },\n    unknownUnion: { type: null, required: true },\n    unknownIntersection: { type: Object, required: true },\n    unknownUnionWithBoolean: { type: Boolean, required: true, skipCheck: true },\n    unknownUnionWithFunction: { type: Function, required: true, skipCheck: true }\n  },\n  setup(__props: any, { expose: __expose }) {\n  __expose();\n\n    \n    \nreturn {  }\n}\n\n})\"\n`;\n\nexports[`defineProps > w/ type alias 1`] = `\n\"import { defineComponent as _defineComponent } from 'vue'\ntype Props = { x?: number }\n    \nexport default /*@__PURE__*/_defineComponent({\n  props: {\n    x: { type: Number, required: false }\n  },\n  setup(__props: any, { expose: __expose }) {\n  __expose();\n\n    \n    \nreturn {  }\n}\n\n})\"\n`;\n\nexports[`defineProps > withDefaults (dynamic) 1`] = `\n\"import { mergeDefaults as _mergeDefaults, defineComponent as _defineComponent } from 'vue'\nimport { defaults } from './foo'\n    \nexport default /*@__PURE__*/_defineComponent({\n  props: /*@__PURE__*/_mergeDefaults({\n    foo: { type: String, required: false },\n    bar: { type: Number, required: false },\n    baz: { type: Boolean, required: true }\n  }, { ...defaults }),\n  setup(__props: any, { expose: __expose }) {\n  __expose();\n\n    const props = __props\n    \nreturn { props, get defaults() { return defaults } }\n}\n\n})\"\n`;\n\nexports[`defineProps > withDefaults (dynamic) w/ production mode 1`] = `\n\"import { mergeDefaults as _mergeDefaults, defineComponent as _defineComponent } from 'vue'\nimport { defaults } from './foo'\n    \nexport default /*@__PURE__*/_defineComponent({\n  props: /*@__PURE__*/_mergeDefaults({\n    foo: { type: Function },\n    bar: { type: Boolean },\n    baz: { type: [Boolean, Function] },\n    qux: {}\n  }, { ...defaults }),\n  setup(__props: any, { expose: __expose }) {\n  __expose();\n\n    const props = __props\n    \nreturn { props, get defaults() { return defaults } }\n}\n\n})\"\n`;\n\nexports[`defineProps > withDefaults (reference) 1`] = `\n\"import { mergeDefaults as _mergeDefaults, defineComponent as _defineComponent } from 'vue'\nimport { defaults } from './foo'\n    \nexport default /*@__PURE__*/_defineComponent({\n  props: /*@__PURE__*/_mergeDefaults({\n    foo: { type: String, required: false },\n    bar: { type: Number, required: false },\n    baz: { type: Boolean, required: true }\n  }, defaults),\n  setup(__props: any, { expose: __expose }) {\n  __expose();\n\n    const props = __props\n    \nreturn { props, get defaults() { return defaults } }\n}\n\n})\"\n`;\n\nexports[`defineProps > withDefaults (static) + normal script 1`] = `\n\"import { defineComponent as _defineComponent } from 'vue'\n\n      interface Props {\n        a?: string;\n      }\n    \nexport default /*@__PURE__*/_defineComponent({\n  props: {\n    a: { type: String, required: false, default: \"a\" }\n  },\n  setup(__props: any, { expose: __expose }) {\n  __expose();\n\n      const props = __props;\n    \nreturn { props }\n}\n\n})\"\n`;\n\nexports[`defineProps > withDefaults (static) 1`] = `\n\"import { defineComponent as _defineComponent } from 'vue'\n\nexport default /*@__PURE__*/_defineComponent({\n  props: {\n    foo: { type: String, required: false, default: 'hi' },\n    bar: { type: Number, required: false },\n    baz: { type: Boolean, required: true },\n    qux: { type: Function, required: false, default() { return 1 } },\n    quux: { type: Function, required: false, default() { } },\n    quuxx: { type: Promise, required: false, async default() { return await Promise.resolve('hi') } },\n    quuux: { type: Number, required: false, default(a, [b, ...c], {d, ...e}, ...f) { return 1 } },\n    fred: { type: String, required: false, get default() { return 'fred' } }\n  },\n  setup(__props: any, { expose: __expose }) {\n  __expose();\n\n    const props = __props\n    \nreturn { props }\n}\n\n})\"\n`;\n\nexports[`defineProps > withDefaults (static) w/ production mode 1`] = `\n\"import { defineComponent as _defineComponent } from 'vue'\n\nexport default /*@__PURE__*/_defineComponent({\n  props: {\n    foo: {},\n    bar: { type: Boolean },\n    baz: { type: [Boolean, Function], default: true },\n    qux: { default: 'hi' }\n  },\n  setup(__props: any, { expose: __expose }) {\n  __expose();\n\n    const props = __props\n    \nreturn { props }\n}\n\n})\"\n`;\n\nexports[`defineProps > withDefaults w/ dynamic object method 1`] = `\n\"import { mergeDefaults as _mergeDefaults, defineComponent as _defineComponent } from 'vue'\n\nexport default /*@__PURE__*/_defineComponent({\n  props: /*@__PURE__*/_mergeDefaults({\n    foo: { type: Function, required: false }\n  }, {\n      ['fo' + 'o']() { return 'foo' }\n    }),\n  setup(__props: any, { expose: __expose }) {\n  __expose();\n\n    const props = __props\n    \nreturn { props }\n}\n\n})\"\n`;\n"
  },
  {
    "path": "packages/compiler-sfc/__tests__/compileScript/__snapshots__/definePropsDestructure.spec.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`sfc reactive props destructure > aliasing 1`] = `\n\"import { toDisplayString as _toDisplayString } from \"vue\"\n\n\nexport default {\n  props: ['foo'],\n  setup(__props) {\n\n      \n      let x = foo\n      let y = __props.foo\n      \nreturn (_ctx, _cache) => {\n  return _toDisplayString(__props.foo + __props.foo)\n}\n}\n\n}\"\n`;\n\nexports[`sfc reactive props destructure > basic usage 1`] = `\n\"import { toDisplayString as _toDisplayString } from \"vue\"\n\n\nexport default {\n  props: ['foo'],\n  setup(__props) {\n\n      \n      console.log(__props.foo)\n      \nreturn (_ctx, _cache) => {\n  return _toDisplayString(__props.foo)\n}\n}\n\n}\"\n`;\n\nexports[`sfc reactive props destructure > computed static key 1`] = `\n\"import { toDisplayString as _toDisplayString } from \"vue\"\n\n\nexport default {\n  props: ['foo'],\n  setup(__props) {\n\n    \n    console.log(__props.foo)\n    \nreturn (_ctx, _cache) => {\n  return _toDisplayString(__props.foo)\n}\n}\n\n}\"\n`;\n\nexports[`sfc reactive props destructure > default values w/ array runtime declaration 1`] = `\n\"import { mergeDefaults as _mergeDefaults } from 'vue'\n\nexport default {\n  props: /*@__PURE__*/_mergeDefaults(['foo', 'bar', 'baz'], {\n  foo: 1,\n  bar: () => ({}),\n  func: () => {}, __skip_func: true\n}),\n  setup(__props) {\n\n      \n      \nreturn () => {}\n}\n\n}\"\n`;\n\nexports[`sfc reactive props destructure > default values w/ object runtime declaration 1`] = `\n\"import { mergeDefaults as _mergeDefaults } from 'vue'\n\nexport default {\n  props: /*@__PURE__*/_mergeDefaults({ foo: Number, bar: Object, func: Function, ext: null }, {\n  foo: 1,\n  bar: () => ({}),\n  func: () => {}, __skip_func: true,\n  ext: x, __skip_ext: true\n}),\n  setup(__props) {\n\n      \n      \nreturn () => {}\n}\n\n}\"\n`;\n\nexports[`sfc reactive props destructure > default values w/ runtime declaration & key is string 1`] = `\n\"import { mergeDefaults as _mergeDefaults } from 'vue'\n\nexport default {\n  props: /*@__PURE__*/_mergeDefaults(['foo', 'foo:bar'], {\n  foo: 1,\n  \"foo:bar\": 'foo-bar'\n}),\n  setup(__props) {\n\n      \n      \nreturn () => {}\n}\n\n}\"\n`;\n\nexports[`sfc reactive props destructure > default values w/ type declaration & key is string 1`] = `\n\"import { defineComponent as _defineComponent } from 'vue'\n\nexport default /*@__PURE__*/_defineComponent({\n  props: {\n    foo: { type: Number, required: true, default: 1 },\n    bar: { type: Number, required: true, default: 2 },\n    \"foo:bar\": { type: String, required: true, default: 'foo-bar' },\n    \"onUpdate:modelValue\": { type: Function, required: true }\n  },\n  setup(__props: any) {\n\n      \n      \nreturn () => {}\n}\n\n})\"\n`;\n\nexports[`sfc reactive props destructure > default values w/ type declaration 1`] = `\n\"import { defineComponent as _defineComponent } from 'vue'\n\nexport default /*@__PURE__*/_defineComponent({\n  props: {\n    foo: { type: Number, required: false, default: 1 },\n    bar: { type: Object, required: false, default: () => ({}) },\n    func: { type: Function, required: false, default: () => {} }\n  },\n  setup(__props: any) {\n\n      \n      \nreturn () => {}\n}\n\n})\"\n`;\n\nexports[`sfc reactive props destructure > default values w/ type declaration, prod mode 1`] = `\n\"import { defineComponent as _defineComponent } from 'vue'\n\nexport default /*@__PURE__*/_defineComponent({\n  props: {\n    foo: { default: 1 },\n    bar: { default: () => ({}) },\n    baz: {},\n    boola: { type: Boolean },\n    boolb: { type: [Boolean, Number] },\n    func: { type: Function, default: () => {} }\n  },\n  setup(__props: any) {\n\n      \n      \nreturn () => {}\n}\n\n})\"\n`;\n\nexports[`sfc reactive props destructure > defineProps/defineEmits in multi-variable declaration (full removal) 1`] = `\n\"\nexport default {\n  props: ['item'],\n  emits: ['a'],\n  setup(__props, { emit: __emit }) {\n\n    const props = __props,\n          emit = __emit;\n    \nreturn () => {}\n}\n\n}\"\n`;\n\nexports[`sfc reactive props destructure > for-of loop variable shadowing 1`] = `\n\"import { defineComponent as _defineComponent } from 'vue'\ninterface Props {\n        msg: string;\n        input: string[];\n      }\n      \nexport default /*@__PURE__*/_defineComponent({\n  props: {\n    msg: { type: String, required: true },\n    input: { type: Array, required: true }\n  },\n  setup(__props: any) {\n\n      \n      for (const msg of __props.input) {\n        console.log('MESSAGE', msg);\n      }\n      console.log('NOT FAIL', { msg: __props.msg });\n      \nreturn () => {}\n}\n\n})\"\n`;\n\nexports[`sfc reactive props destructure > handle function parameters with same name as destructured props 1`] = `\n\"\nexport default {\n  setup(__props) {\n\n    \n    function test(value) {\n      try {\n      } catch {\n      }\n    }\n    console.log(__props.value)\n    \nreturn () => {}\n}\n\n}\"\n`;\n\nexports[`sfc reactive props destructure > multi-variable declaration 1`] = `\n\"\nexport default {\n  props: ['item'],\n  setup(__props) {\n\n    const a = 1;\n    \nreturn () => {}\n}\n\n}\"\n`;\n\nexports[`sfc reactive props destructure > multi-variable declaration fix #6757  1`] = `\n\"\nexport default {\n  props: ['item'],\n  setup(__props) {\n\n    const a = 1;\n    \nreturn () => {}\n}\n\n}\"\n`;\n\nexports[`sfc reactive props destructure > multi-variable declaration fix #7422 1`] = `\n\"\nexport default {\n  props: ['item'],\n  setup(__props) {\n\n    const a = 0,\n          b = 0;\n    \nreturn () => {}\n}\n\n}\"\n`;\n\nexports[`sfc reactive props destructure > multiple variable declarations 1`] = `\n\"import { toDisplayString as _toDisplayString, openBlock as _openBlock, createElementBlock as _createElementBlock } from \"vue\"\n\n\nexport default {\n  props: ['foo'],\n  setup(__props) {\n\n      const bar = 'fish', hello = 'world'\n      \nreturn (_ctx, _cache) => {\n  return (_openBlock(), _createElementBlock(\"div\", null, _toDisplayString(__props.foo) + \" \" + _toDisplayString(hello) + \" \" + _toDisplayString(bar), 1 /* TEXT */))\n}\n}\n\n}\"\n`;\n\nexports[`sfc reactive props destructure > nested scope 1`] = `\n\"\nexport default {\n  props: ['foo', 'bar'],\n  setup(__props) {\n\n      \n      function test(foo) {\n        console.log(foo)\n        console.log(__props.bar)\n      }\n      \nreturn () => {}\n}\n\n}\"\n`;\n\nexports[`sfc reactive props destructure > non-identifier prop names 1`] = `\n\"import { toDisplayString as _toDisplayString } from \"vue\"\n\n\nexport default {\n  props: { 'foo.bar': Function },\n  setup(__props) {\n\n      \n      let x = __props[\"foo.bar\"]\n      \nreturn (_ctx, _cache) => {\n  return _toDisplayString(__props[\"foo.bar\"])\n}\n}\n\n}\"\n`;\n\nexports[`sfc reactive props destructure > regular for loop variable shadowing 1`] = `\n\"import { defineComponent as _defineComponent } from 'vue'\n\nexport default /*@__PURE__*/_defineComponent({\n  props: {\n    i: { type: Number, required: true },\n    len: { type: Number, required: true }\n  },\n  setup(__props: any) {\n\n      \n      for (let i = 0; i < __props.len; i++) {\n        console.log('INDEX', i);\n      }\n      console.log('AFTER', { i: __props.i });\n      \nreturn () => {}\n}\n\n})\"\n`;\n\nexports[`sfc reactive props destructure > rest spread 1`] = `\n\"import { createPropsRestProxy as _createPropsRestProxy } from 'vue'\n\nexport default {\n  props: ['foo', 'bar', 'baz'],\n  setup(__props) {\n\n      const rest = _createPropsRestProxy(__props, [\"foo\",\"bar\"])\n      \nreturn () => {}\n}\n\n}\"\n`;\n\nexports[`sfc reactive props destructure > rest spread non-inline 1`] = `\n\"import { createPropsRestProxy as _createPropsRestProxy } from 'vue'\n\nexport default {\n  props: ['foo', 'bar'],\n  setup(__props, { expose: __expose }) {\n  __expose();\n\n      const rest = _createPropsRestProxy(__props, [\"foo\"])\n      \nreturn { rest }\n}\n\n}\"\n`;\n\nexports[`sfc reactive props destructure > with TSInstantiationExpression 1`] = `\n\"import { defineComponent as _defineComponent } from 'vue'\ntype Foo = <T extends string | number>(data: T) => void\n      \nexport default /*@__PURE__*/_defineComponent({\n  props: {\n    value: { type: Function }\n  },\n  setup(__props: any) {\n\n      \n      const foo = __props.value<123>\n      \nreturn () => {}\n}\n\n})\"\n`;\n"
  },
  {
    "path": "packages/compiler-sfc/__tests__/compileScript/__snapshots__/defineSlots.spec.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`defineSlots() > basic usage 1`] = `\n\"import { useSlots as _useSlots, defineComponent as _defineComponent } from 'vue'\n\nexport default /*@__PURE__*/_defineComponent({\n  setup(__props, { expose: __expose }) {\n  __expose();\n\n      const slots = _useSlots()\n      \nreturn { slots }\n}\n\n})\"\n`;\n\nexports[`defineSlots() > w/o generic params 1`] = `\n\"import { useSlots as _useSlots } from 'vue'\n\nexport default {\n  setup(__props, { expose: __expose }) {\n  __expose();\n\n      const slots = _useSlots()\n      \nreturn { slots }\n}\n\n}\"\n`;\n\nexports[`defineSlots() > w/o return value 1`] = `\n\"import { defineComponent as _defineComponent } from 'vue'\n\nexport default /*@__PURE__*/_defineComponent({\n  setup(__props, { expose: __expose }) {\n  __expose();\n\n      \n      \nreturn {  }\n}\n\n})\"\n`;\n"
  },
  {
    "path": "packages/compiler-sfc/__tests__/compileScript/__snapshots__/hoistStatic.spec.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`sfc hoist static > should enable when only script setup 1`] = `\n\"\n    const foo = 'bar'\n    \nexport default {\n  setup(__props) {\n\n    const foo = 'bar'\n    \nreturn () => {}\n}\n\n}\"\n`;\n\nexports[`sfc hoist static > should hoist expressions 1`] = `\n\"const unary = !false\n    const binary = 1 + 2\n    const conditional = 1 ? 2 : 3\n    const sequence = (1, true, 'foo', 1)\n    \nexport default {\n  setup(__props) {\n\n    \nreturn () => {}\n}\n\n}\"\n`;\n\nexports[`sfc hoist static > should hoist literal value 1`] = `\n\"const string = 'default value'\n    const number = 123\n    const boolean = false\n    const nil = null\n    const bigint = 100n\n    const template = \\`str\\`\n    \nexport default {\n  setup(__props) {\n\n    \nreturn () => {}\n}\n\n}\"\n`;\n\nexports[`sfc hoist static > should hoist w/ defineProps/Emits 1`] = `\n\"const defaultValue = 'default value'\n    \nexport default {\n  props: {\n      foo: {\n        default: defaultValue\n      }\n    },\n  setup(__props) {\n\n    \n    \nreturn () => {}\n}\n\n}\"\n`;\n\nexports[`sfc hoist static > should not hoist a constant initialized to a reference value 1`] = `\n\"import { defineComponent as _defineComponent } from 'vue'\n\nexport default /*@__PURE__*/_defineComponent({\n  setup(__props) {\n\n    const KEY1 = Boolean\n    const KEY2 = [Boolean]\n    const KEY3 = [getCurrentInstance()]\n    let i = 0;\n    const KEY4 = (i++, 'foo')\n    enum KEY5 {\n      FOO = 1,\n      BAR = getCurrentInstance(),\n    }\n    const KEY6 = \\`template\\${i}\\`\n    \nreturn () => {}\n}\n\n})\"\n`;\n\nexports[`sfc hoist static > should not hoist a function or class 1`] = `\n\"\nexport default {\n  setup(__props) {\n\n    const fn = () => {}\n    function fn2() {}\n    class Foo {}\n    \nreturn () => {}\n}\n\n}\"\n`;\n\nexports[`sfc hoist static > should not hoist a object or array 1`] = `\n\"\nexport default {\n  setup(__props) {\n\n    const obj = { foo: 'bar' }\n    const arr = [1, 2, 3]\n    \nreturn () => {}\n}\n\n}\"\n`;\n\nexports[`sfc hoist static > should not hoist a variable 1`] = `\n\"\nexport default {\n  setup(__props) {\n\n    let KEY1 = 'default value'\n    var KEY2 = 123\n    const regex = /.*/g\n    const undef = undefined\n    \nreturn () => {}\n}\n\n}\"\n`;\n\nexports[`sfc hoist static > should not hoist when disabled 1`] = `\n\"\nexport default {\n  setup(__props) {\n\n    const foo = 'bar'\n    \nreturn () => {}\n}\n\n}\"\n`;\n"
  },
  {
    "path": "packages/compiler-sfc/__tests__/compileScript/__snapshots__/importUsageCheck.spec.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`TS annotations 1`] = `\n\"import { defineComponent as _defineComponent } from 'vue'\nimport { Foo, Bar, Baz, Qux, Fred } from './x'\n    const a = 1\n    \nexport default /*@__PURE__*/_defineComponent({\n  setup(__props, { expose: __expose }) {\n  __expose();\n\n    function b() {}\n    \nreturn { a, b, get Baz() { return Baz } }\n}\n\n})\"\n`;\n\nexports[`attribute expressions 1`] = `\n\"import { defineComponent as _defineComponent } from 'vue'\nimport { bar, baz } from './x'\n    const cond = true\n    \nexport default /*@__PURE__*/_defineComponent({\n  setup(__props, { expose: __expose }) {\n  __expose();\n\n    \nreturn { cond, get bar() { return bar }, get baz() { return baz } }\n}\n\n})\"\n`;\n\nexports[`components 1`] = `\n\"import { defineComponent as _defineComponent } from 'vue'\nimport { FooBar, FooBaz, FooQux, foo } from './x'\n    const fooBar: FooBar = 1\n    \nexport default /*@__PURE__*/_defineComponent({\n  setup(__props, { expose: __expose }) {\n  __expose();\n\n    \nreturn { fooBar, get FooBaz() { return FooBaz }, get FooQux() { return FooQux }, get foo() { return foo } }\n}\n\n})\"\n`;\n\nexports[`directive 1`] = `\n\"import { defineComponent as _defineComponent } from 'vue'\nimport { vMyDir } from './x'\n    \nexport default /*@__PURE__*/_defineComponent({\n  setup(__props, { expose: __expose }) {\n  __expose();\n\n    \nreturn { get vMyDir() { return vMyDir } }\n}\n\n})\"\n`;\n\nexports[`dynamic arguments 1`] = `\n\"import { defineComponent as _defineComponent } from 'vue'\nimport { FooBar, foo, bar, unused, baz, msg } from './x'\n    \nexport default /*@__PURE__*/_defineComponent({\n  setup(__props, { expose: __expose }) {\n  __expose();\n\n    \nreturn { get FooBar() { return FooBar }, get foo() { return foo }, get bar() { return bar }, get baz() { return baz }, get msg() { return msg } }\n}\n\n})\"\n`;\n\nexports[`js template string interpolations 1`] = `\n\"import { defineComponent as _defineComponent } from 'vue'\nimport { VAR, VAR2, VAR3 } from './x'\n    \nexport default /*@__PURE__*/_defineComponent({\n  setup(__props, { expose: __expose }) {\n  __expose();\n\n    \nreturn { get VAR() { return VAR }, get VAR3() { return VAR3 } }\n}\n\n})\"\n`;\n\nexports[`last tag 1`] = `\n\"import { defineComponent as _defineComponent } from 'vue'\nimport { FooBaz, Last } from './x'\n    \nexport default /*@__PURE__*/_defineComponent({\n  setup(__props, { expose: __expose }) {\n  __expose();\n\n    \nreturn { get FooBaz() { return FooBaz }, get Last() { return Last } }\n}\n\n})\"\n`;\n\nexports[`namespace / dot component usage 1`] = `\n\"import { defineComponent as _defineComponent } from 'vue'\nimport * as Foo from './foo'\n    \nexport default /*@__PURE__*/_defineComponent({\n  setup(__props, { expose: __expose }) {\n  __expose();\n\n      \nreturn { get Foo() { return Foo } }\n}\n\n})\"\n`;\n\nexports[`property access (whitespace) 1`] = `\n\"import { defineComponent as _defineComponent } from 'vue'\nimport { Foo, Bar, Baz } from './foo'\n    \nexport default /*@__PURE__*/_defineComponent({\n  setup(__props, { expose: __expose }) {\n  __expose();\n\n      \nreturn { get Foo() { return Foo } }\n}\n\n})\"\n`;\n\nexports[`property access 1`] = `\n\"import { defineComponent as _defineComponent } from 'vue'\nimport { Foo, Bar, Baz } from './foo'\n    \nexport default /*@__PURE__*/_defineComponent({\n  setup(__props, { expose: __expose }) {\n  __expose();\n\n      \nreturn { get Foo() { return Foo } }\n}\n\n})\"\n`;\n\nexports[`spread operator 1`] = `\n\"import { defineComponent as _defineComponent } from 'vue'\nimport { Foo, Bar, Baz } from './foo'\n    \nexport default /*@__PURE__*/_defineComponent({\n  setup(__props, { expose: __expose }) {\n  __expose();\n\n      \nreturn { get Foo() { return Foo } }\n}\n\n})\"\n`;\n\nexports[`template ref 1`] = `\n\"import { defineComponent as _defineComponent } from 'vue'\nimport { foo, bar, Baz } from './foo'\n    \nexport default /*@__PURE__*/_defineComponent({\n  setup(__props, { expose: __expose }) {\n  __expose();\n\n      \nreturn { get foo() { return foo }, get bar() { return bar }, get Baz() { return Baz } }\n}\n\n})\"\n`;\n\nexports[`vue interpolations 1`] = `\n\"import { defineComponent as _defineComponent } from 'vue'\nimport { x, y, z, x$y } from './x'\n  \nexport default /*@__PURE__*/_defineComponent({\n  setup(__props, { expose: __expose }) {\n  __expose();\n\n  \nreturn { get x() { return x }, get z() { return z }, get x$y() { return x$y } }\n}\n\n})\"\n`;\n"
  },
  {
    "path": "packages/compiler-sfc/__tests__/compileScript/defineEmits.spec.ts",
    "content": "import { BindingTypes } from '@vue/compiler-core'\nimport { assertCode, compileSFCScript as compile } from '../utils'\n\ndescribe('defineEmits', () => {\n  test('basic usage', () => {\n    const { content, bindings } = compile(`\n<script setup>\nconst myEmit = defineEmits(['foo', 'bar'])\n</script>\n  `)\n    assertCode(content)\n    expect(bindings).toStrictEqual({\n      myEmit: BindingTypes.SETUP_CONST,\n    })\n    // should remove defineEmits import and call\n    expect(content).not.toMatch('defineEmits')\n    // should generate correct setup signature\n    expect(content).toMatch(\n      `setup(__props, { expose: __expose, emit: __emit }) {`,\n    )\n    expect(content).toMatch('const myEmit = __emit')\n    // should include context options in default export\n    expect(content).toMatch(`export default {\n  emits: ['foo', 'bar'],`)\n  })\n\n  test('w/ runtime options', () => {\n    const { content } = compile(`\n<script setup lang=\"ts\">\nconst emit = defineEmits(['a', 'b'])\n</script>\n    `)\n    assertCode(content)\n    expect(content).toMatch(`export default /*@__PURE__*/_defineComponent({\n  emits: ['a', 'b'],\n  setup(__props, { expose: __expose, emit: __emit }) {`)\n    expect(content).toMatch('const emit = __emit')\n  })\n\n  test('w/ type', () => {\n    const { content } = compile(`\n    <script setup lang=\"ts\">\n    const emit = defineEmits<(e: 'foo' | 'bar') => void>()\n    </script>\n    `)\n    assertCode(content)\n    expect(content).toMatch(`emits: [\"foo\", \"bar\"]`)\n  })\n\n  test('w/ type (union)', () => {\n    const type = `((e: 'foo' | 'bar') => void) | ((e: 'baz', id: number) => void)`\n    const { content } = compile(`\n    <script setup lang=\"ts\">\n    const emit = defineEmits<${type}>()\n    </script>\n    `)\n    assertCode(content)\n    expect(content).toMatch(`emits: [\"foo\", \"bar\", \"baz\"]`)\n  })\n\n  test('w/ type (type literal w/ call signatures)', () => {\n    const type = `{(e: 'foo' | 'bar'): void; (e: 'baz', id: number): void;}`\n    const { content } = compile(`\n    <script setup lang=\"ts\">\n    const emit = defineEmits<${type}>()\n    </script>\n    `)\n    assertCode(content)\n    expect(content).toMatch(`emits: [\"foo\", \"bar\", \"baz\"]`)\n  })\n\n  test('w/ type (interface)', () => {\n    const { content } = compile(`\n    <script setup lang=\"ts\">\n    interface Emits { (e: 'foo' | 'bar'): void }\n    const emit = defineEmits<Emits>()\n    </script>\n    `)\n    assertCode(content)\n    expect(content).toMatch(`emits: [\"foo\", \"bar\"]`)\n  })\n\n  test('w/ type (interface w/ extends)', () => {\n    const { content } = compile(`\n    <script setup lang=\"ts\">\n    interface Base { (e: 'foo'): void }\n    interface Emits extends Base { (e: 'bar'): void }\n    const emit = defineEmits<Emits>()\n    </script>\n    `)\n    assertCode(content)\n    expect(content).toMatch(`emits: [\"bar\", \"foo\"]`)\n  })\n\n  test('w/ type (exported interface)', () => {\n    const { content } = compile(`\n    <script setup lang=\"ts\">\n    export interface Emits { (e: 'foo' | 'bar'): void }\n    const emit = defineEmits<Emits>()\n    </script>\n    `)\n    assertCode(content)\n    expect(content).toMatch(`emits: [\"foo\", \"bar\"]`)\n  })\n\n  test('w/ type from normal script', () => {\n    const { content } = compile(`\n    <script lang=\"ts\">\n      export interface Emits { (e: 'foo' | 'bar'): void }\n    </script>\n    <script setup lang=\"ts\">\n    const emit = defineEmits<Emits>()\n    </script>\n    `)\n    assertCode(content)\n    expect(content).toMatch(`emits: [\"foo\", \"bar\"]`)\n  })\n\n  test('w/ type (type alias)', () => {\n    const { content } = compile(`\n    <script setup lang=\"ts\">\n    type Emits = { (e: 'foo' | 'bar'): void }\n    const emit = defineEmits<Emits>()\n    </script>\n    `)\n    assertCode(content)\n    expect(content).toMatch(`emits: [\"foo\", \"bar\"]`)\n  })\n\n  test('w/ type (exported type alias)', () => {\n    const { content } = compile(`\n    <script setup lang=\"ts\">\n    export type Emits = { (e: 'foo' | 'bar'): void }\n    const emit = defineEmits<Emits>()\n    </script>\n    `)\n    assertCode(content)\n    expect(content).toMatch(`emits: [\"foo\", \"bar\"]`)\n  })\n\n  test('w/ type (referenced function type)', () => {\n    const { content } = compile(`\n    <script setup lang=\"ts\">\n    type Emits = (e: 'foo' | 'bar') => void\n    const emit = defineEmits<Emits>()\n    </script>\n    `)\n    assertCode(content)\n    expect(content).toMatch(`emits: [\"foo\", \"bar\"]`)\n  })\n\n  test('w/ type (referenced exported function type)', () => {\n    const { content } = compile(`\n    <script setup lang=\"ts\">\n    export type Emits = (e: 'foo' | 'bar') => void\n    const emit = defineEmits<Emits>()\n    </script>\n    `)\n    assertCode(content)\n    expect(content).toMatch(`emits: [\"foo\", \"bar\"]`)\n  })\n\n  // #5393\n  test('w/ type (interface ts type)', () => {\n    const { content } = compile(`\n    <script setup lang=\"ts\">\n    interface Emits { (e: 'foo'): void }\n    const emit: Emits = defineEmits(['foo'])\n    </script>\n    `)\n    assertCode(content)\n    expect(content).toMatch(`emits: ['foo']`)\n  })\n\n  test('w/ type (property syntax)', () => {\n    const { content } = compile(`\n    <script setup lang=\"ts\">\n    const emit = defineEmits<{ foo: [], bar: [] }>()\n    </script>\n    `)\n    expect(content).toMatch(`emits: [\"foo\", \"bar\"]`)\n    assertCode(content)\n  })\n\n  // #8040\n  test('w/ type (property syntax string literal)', () => {\n    const { content } = compile(`\n    <script setup lang=\"ts\">\n    const emit = defineEmits<{ 'foo:bar': [] }>()\n    </script>\n    `)\n    expect(content).toMatch(`emits: [\"foo:bar\"]`)\n    assertCode(content)\n  })\n\n  // #7943\n  test('w/ type (type references in union)', () => {\n    const { content } = compile(`\n    <script setup lang=\"ts\">\n    type BaseEmit = \"change\"\n    type Emit = \"some\" | \"emit\" | BaseEmit\n    const emit = defineEmits<{\n      (e: Emit): void;\n      (e: \"another\", val: string): void;\n    }>();\n    </script>\n    `)\n\n    expect(content).toMatch(`emits: [\"some\", \"emit\", \"change\", \"another\"]`)\n    assertCode(content)\n  })\n\n  describe('errors', () => {\n    test('w/ both type and non-type args', () => {\n      expect(() => {\n        compile(`<script setup lang=\"ts\">\n        defineEmits<{}>({})\n        </script>`)\n      }).toThrow(`cannot accept both type and non-type arguments`)\n    })\n\n    test('mixed usage of property / call signature', () => {\n      expect(() =>\n        compile(`<script setup lang=\"ts\">\n        defineEmits<{\n          foo: []\n          (e: 'hi'): void\n        }>()\n        </script>`),\n      ).toThrow(\n        `defineEmits() type cannot mixed call signature and property syntax.`,\n      )\n    })\n  })\n})\n"
  },
  {
    "path": "packages/compiler-sfc/__tests__/compileScript/defineExpose.spec.ts",
    "content": "import { assertCode, compileSFCScript as compile } from '../utils'\n\ntest('defineExpose()', () => {\n  const { content } = compile(`\n<script setup>\ndefineExpose({ foo: 123 })\n</script>\n`)\n  assertCode(content)\n  // should remove defineOptions import and call\n  expect(content).not.toMatch('defineExpose')\n  // should generate correct setup signature\n  expect(content).toMatch(`setup(__props, { expose: __expose }) {`)\n  // should replace callee\n  expect(content).toMatch(/\\b__expose\\(\\{ foo: 123 \\}\\)/)\n})\n\ntest('<script> after <script setup> the script content not end with `\\\\n`', () => {\n  const { content } = compile(`\n  <script setup>\n  import { x } from './x'\n  </script>\n  <script>const n = 1</script>\n  `)\n  assertCode(content)\n})\n"
  },
  {
    "path": "packages/compiler-sfc/__tests__/compileScript/defineModel.spec.ts",
    "content": "import { BindingTypes } from '@vue/compiler-core'\nimport { assertCode, compileSFCScript as compile } from '../utils'\n\ndescribe('defineModel()', () => {\n  test('basic usage', () => {\n    const { content, bindings } = compile(\n      `\n      <script setup>\n      const modelValue = defineModel({ required: true })\n      const c = defineModel('count')\n      const toString = defineModel('toString', { type: Function })\n      </script>\n      `,\n    )\n    assertCode(content)\n    expect(content).toMatch('props: {')\n    expect(content).toMatch('\"modelValue\": { required: true },')\n    expect(content).toMatch('\"count\": {},')\n    expect(content).toMatch('\"toString\": { type: Function },')\n    expect(content).toMatch(\n      'emits: [\"update:modelValue\", \"update:count\", \"update:toString\"],',\n    )\n    expect(content).toMatch(\n      `const modelValue = _useModel(__props, \"modelValue\")`,\n    )\n    expect(content).toMatch(`const c = _useModel(__props, 'count')`)\n    expect(content).toMatch(`const toString = _useModel(__props, 'toString')`)\n    expect(content).toMatch(`return { modelValue, c, toString }`)\n    expect(content).not.toMatch('defineModel')\n\n    expect(bindings).toStrictEqual({\n      modelValue: BindingTypes.SETUP_REF,\n      count: BindingTypes.PROPS,\n      c: BindingTypes.SETUP_REF,\n      toString: BindingTypes.SETUP_REF,\n    })\n  })\n\n  test('w/ defineProps and defineEmits', () => {\n    const { content, bindings } = compile(\n      `\n      <script setup>\n      defineProps({ foo: String })\n      defineEmits(['change'])\n      const count = defineModel({ default: 0 })\n      </script>\n    `,\n    )\n    assertCode(content)\n    expect(content).toMatch(`props: /*@__PURE__*/_mergeModels({ foo: String }`)\n    expect(content).toMatch(`\"modelValue\": { default: 0 }`)\n    expect(content).toMatch(`const count = _useModel(__props, \"modelValue\")`)\n    expect(content).not.toMatch('defineModel')\n    expect(bindings).toStrictEqual({\n      count: BindingTypes.SETUP_REF,\n      foo: BindingTypes.PROPS,\n      modelValue: BindingTypes.PROPS,\n    })\n  })\n\n  test('w/ array props', () => {\n    const { content, bindings } = compile(\n      `\n      <script setup>\n      defineProps(['foo', 'bar'])\n      const count = defineModel('count')\n      </script>\n    `,\n    )\n    assertCode(content)\n    expect(content).toMatch(`props: /*@__PURE__*/_mergeModels(['foo', 'bar'], {\n    \"count\": {},\n    \"countModifiers\": {},\n  })`)\n    expect(content).toMatch(`const count = _useModel(__props, 'count')`)\n    expect(content).not.toMatch('defineModel')\n    expect(bindings).toStrictEqual({\n      foo: BindingTypes.PROPS,\n      bar: BindingTypes.PROPS,\n      count: BindingTypes.SETUP_REF,\n    })\n  })\n\n  test('w/ types, basic usage', () => {\n    const { content, bindings } = compile(\n      `\n      <script setup lang=\"ts\">\n      const modelValue = defineModel<boolean | string>()\n      const count = defineModel<number>('count')\n      const disabled = defineModel<number>('disabled', { required: false })\n      const any = defineModel<any | boolean>('any')\n      </script>\n      `,\n    )\n    assertCode(content)\n    expect(content).toMatch('\"modelValue\": { type: [Boolean, String] }')\n    expect(content).toMatch('\"modelModifiers\": {}')\n    expect(content).toMatch('\"count\": { type: Number }')\n    expect(content).toMatch(\n      '\"disabled\": { type: Number, ...{ required: false } }',\n    )\n    expect(content).toMatch('\"any\": { type: Boolean, skipCheck: true }')\n    expect(content).toMatch(\n      'emits: [\"update:modelValue\", \"update:count\", \"update:disabled\", \"update:any\"]',\n    )\n\n    expect(content).toMatch(\n      `const modelValue = _useModel<boolean | string>(__props, \"modelValue\")`,\n    )\n    expect(content).toMatch(`const count = _useModel<number>(__props, 'count')`)\n    expect(content).toMatch(\n      `const disabled = _useModel<number>(__props, 'disabled')`,\n    )\n    expect(content).toMatch(\n      `const any = _useModel<any | boolean>(__props, 'any')`,\n    )\n\n    expect(bindings).toStrictEqual({\n      modelValue: BindingTypes.SETUP_REF,\n      count: BindingTypes.SETUP_REF,\n      disabled: BindingTypes.SETUP_REF,\n      any: BindingTypes.SETUP_REF,\n    })\n  })\n\n  test('w/ types, production mode', () => {\n    const { content, bindings } = compile(\n      `\n      <script setup lang=\"ts\">\n      const modelValue = defineModel<boolean>()\n      const fn = defineModel<() => void>('fn')\n      const fnWithDefault = defineModel<() => void>('fnWithDefault', { default: () => null })\n      const str = defineModel<string>('str')\n      const optional = defineModel<string>('optional', { required: false })\n      </script>\n      `,\n      { isProd: true },\n    )\n    assertCode(content)\n    expect(content).toMatch('\"modelValue\": { type: Boolean }')\n    expect(content).toMatch('\"fn\": {}')\n    expect(content).toMatch(\n      '\"fnWithDefault\": { type: Function, ...{ default: () => null } },',\n    )\n    expect(content).toMatch('\"str\": {}')\n    expect(content).toMatch('\"optional\": { required: false }')\n    expect(content).toMatch(\n      'emits: [\"update:modelValue\", \"update:fn\", \"update:fnWithDefault\", \"update:str\", \"update:optional\"]',\n    )\n    expect(content).toMatch(\n      `const modelValue = _useModel<boolean>(__props, \"modelValue\")`,\n    )\n    expect(content).toMatch(`const fn = _useModel<() => void>(__props, 'fn')`)\n    expect(content).toMatch(`const str = _useModel<string>(__props, 'str')`)\n    expect(bindings).toStrictEqual({\n      modelValue: BindingTypes.SETUP_REF,\n      fn: BindingTypes.SETUP_REF,\n      fnWithDefault: BindingTypes.SETUP_REF,\n      str: BindingTypes.SETUP_REF,\n      optional: BindingTypes.SETUP_REF,\n    })\n  })\n\n  test('w/ types, production mode, boolean + multiple types', () => {\n    const { content } = compile(\n      `\n      <script setup lang=\"ts\">\n      const modelValue = defineModel<boolean | string | {}>()\n      </script>\n      `,\n      { isProd: true },\n    )\n    assertCode(content)\n    expect(content).toMatch('\"modelValue\": { type: [Boolean, String, Object] }')\n  })\n\n  test('w/ types, production mode, function + runtime opts + multiple types', () => {\n    const { content } = compile(\n      `\n      <script setup lang=\"ts\">\n      const modelValue = defineModel<number | (() => number)>({ default: () => 1 })\n      </script>\n      `,\n      { isProd: true },\n    )\n    assertCode(content)\n    expect(content).toMatch(\n      '\"modelValue\": { type: [Number, Function], ...{ default: () => 1 } }',\n    )\n  })\n\n  test('get / set transformers', () => {\n    const { content } = compile(\n      `\n      <script setup lang=\"ts\">\n      const modelValue = defineModel({\n        get(v) { return v - 1 },\n        set: (v) => { return v + 1 },\n        required: true\n      })\n      </script>\n      `,\n    )\n    assertCode(content)\n    expect(content).toMatch(/\"modelValue\": {\\s+required: true,?\\s+}/m)\n    expect(content).toMatch(\n      `_useModel(__props, \"modelValue\", {\n        get(v) { return v - 1 },\n        set: (v) => { return v + 1 },\n        })`,\n    )\n\n    const { content: content2 } = compile(\n      `\n      <script setup lang=\"ts\">\n      const modelValue = defineModel({\n        default: 0,\n        get(v) { return v - 1 },\n        required: true,\n        set: (v) => { return v + 1 },\n      })\n      </script>\n      `,\n    )\n    assertCode(content2)\n    expect(content2).toMatch(\n      /\"modelValue\": {\\s+default: 0,\\s+required: true,?\\s+}/m,\n    )\n    expect(content2).toMatch(\n      `_useModel(__props, \"modelValue\", {\n        get(v) { return v - 1 },\n        set: (v) => { return v + 1 },\n      })`,\n    )\n  })\n\n  test('usage w/ props destructure', () => {\n    const { content } = compile(\n      `\n      <script setup lang=\"ts\">\n      const { x } = defineProps<{ x: number }>()\n      const modelValue = defineModel({\n        set: (v) => { return v + x }\n      })\n      </script>\n      `,\n      { propsDestructure: true },\n    )\n    assertCode(content)\n    expect(content).toMatch(`set: (v) => { return v + __props.x }`)\n  })\n\n  test('w/ Boolean And Function types, production mode', () => {\n    const { content, bindings } = compile(\n      `\n      <script setup lang=\"ts\">\n      const modelValue = defineModel<boolean | string>()\n      </script>\n      `,\n      { isProd: true },\n    )\n    assertCode(content)\n    expect(content).toMatch('\"modelValue\": { type: [Boolean, String] }')\n    expect(content).toMatch('emits: [\"update:modelValue\"]')\n    expect(content).toMatch(\n      `const modelValue = _useModel<boolean | string>(__props, \"modelValue\")`,\n    )\n    expect(bindings).toStrictEqual({\n      modelValue: BindingTypes.SETUP_REF,\n    })\n  })\n})\n"
  },
  {
    "path": "packages/compiler-sfc/__tests__/compileScript/defineOptions.spec.ts",
    "content": "import { assertCode, compileSFCScript as compile } from '../utils'\n\ndescribe('defineOptions()', () => {\n  test('basic usage', () => {\n    const { content } = compile(`\n      <script setup>\n      defineOptions({ name: 'FooApp' })\n      </script>\n    `)\n    assertCode(content)\n    // should remove defineOptions import and call\n    expect(content).not.toMatch('defineOptions')\n    // should include context options in default export\n    expect(content).toMatch(\n      `export default /*@__PURE__*/Object.assign({ name: 'FooApp' }, `,\n    )\n  })\n\n  test('empty argument', () => {\n    const { content } = compile(`\n      <script setup>\n      defineOptions()\n      </script>\n    `)\n    assertCode(content)\n    expect(content).toMatch(`export default {`)\n    // should remove defineOptions import and call\n    expect(content).not.toMatch('defineOptions')\n  })\n\n  it('should emit an error with two defineOptions', () => {\n    expect(() =>\n      compile(`\n      <script setup>\n      defineOptions({ name: 'FooApp' })\n      defineOptions({ name: 'BarApp' })\n      </script>\n      `),\n    ).toThrowError('[@vue/compiler-sfc] duplicate defineOptions() call')\n  })\n\n  it('should emit an error with props or emits property', () => {\n    expect(() =>\n      compile(`\n      <script setup>\n      defineOptions({ props: { foo: String } })\n      </script>\n      `),\n    ).toThrowError(\n      '[@vue/compiler-sfc] defineOptions() cannot be used to declare props. Use defineProps() instead.',\n    )\n\n    expect(() =>\n      compile(`\n      <script setup>\n      defineOptions({ emits: ['update'] })\n      </script>\n    `),\n    ).toThrowError(\n      '[@vue/compiler-sfc] defineOptions() cannot be used to declare emits. Use defineEmits() instead.',\n    )\n\n    expect(() =>\n      compile(`\n      <script setup>\n      defineOptions({ expose: ['foo'] })\n      </script>\n    `),\n    ).toThrowError(\n      '[@vue/compiler-sfc] defineOptions() cannot be used to declare expose. Use defineExpose() instead.',\n    )\n\n    expect(() =>\n      compile(`\n      <script setup>\n      defineOptions({ slots: ['foo'] })\n      </script>\n    `),\n    ).toThrowError(\n      '[@vue/compiler-sfc] defineOptions() cannot be used to declare slots. Use defineSlots() instead.',\n    )\n  })\n\n  it('should emit an error with type generic', () => {\n    expect(() =>\n      compile(`\n      <script setup lang=\"ts\">\n      defineOptions<{ name: 'FooApp' }>()\n      </script>\n      `),\n    ).toThrowError(\n      '[@vue/compiler-sfc] defineOptions() cannot accept type arguments',\n    )\n  })\n\n  it('should emit an error with type assertion', () => {\n    expect(() =>\n      compile(`\n      <script setup lang=\"ts\">\n      defineOptions({ props: [] } as any)\n      </script>\n      `),\n    ).toThrowError(\n      '[@vue/compiler-sfc] defineOptions() cannot be used to declare props. Use defineProps() instead.',\n    )\n  })\n\n  it('should emit an error with declaring props/emits/slots/expose', () => {\n    expect(() =>\n      compile(`\n        <script setup>\n        defineOptions({ props: ['foo'] })\n        </script>\n      `),\n    ).toThrowError(\n      '[@vue/compiler-sfc] defineOptions() cannot be used to declare props. Use defineProps() instead',\n    )\n\n    expect(() =>\n      compile(`\n        <script setup>\n        defineOptions({ emits: ['update'] })\n        </script>\n      `),\n    ).toThrowError(\n      '[@vue/compiler-sfc] defineOptions() cannot be used to declare emits. Use defineEmits() instead',\n    )\n\n    expect(() =>\n      compile(`\n        <script setup>\n        defineOptions({ expose: ['foo'] })\n        </script>\n      `),\n    ).toThrowError(\n      '[@vue/compiler-sfc] defineOptions() cannot be used to declare expose. Use defineExpose() instead',\n    )\n\n    expect(() =>\n      compile(`\n        <script setup lang=\"ts\">\n        defineOptions({ slots: Object })\n        </script>\n      `),\n    ).toThrowError(\n      '[@vue/compiler-sfc] defineOptions() cannot be used to declare slots. Use defineSlots() instead',\n    )\n  })\n})\n"
  },
  {
    "path": "packages/compiler-sfc/__tests__/compileScript/defineProps.spec.ts",
    "content": "import { BindingTypes } from '@vue/compiler-core'\nimport { assertCode, compileSFCScript as compile } from '../utils'\n\ndescribe('defineProps', () => {\n  test('basic usage', () => {\n    const { content, bindings } = compile(`\n<script setup>\nconst props = defineProps({\n  foo: String\n})\nconst bar = 1\n</script>\n  `)\n    // should generate working code\n    assertCode(content)\n    // should analyze bindings\n    expect(bindings).toStrictEqual({\n      foo: BindingTypes.PROPS,\n      bar: BindingTypes.LITERAL_CONST,\n      props: BindingTypes.SETUP_REACTIVE_CONST,\n    })\n\n    // should remove defineOptions import and call\n    expect(content).not.toMatch('defineProps')\n    // should generate correct setup signature\n    expect(content).toMatch(`setup(__props, { expose: __expose }) {`)\n    // should assign user identifier to it\n    expect(content).toMatch(`const props = __props`)\n    // should include context options in default export\n    expect(content).toMatch(`export default {\n  props: {\n  foo: String\n},`)\n  })\n\n  test('w/ external definition', () => {\n    const { content } = compile(`\n    <script setup>\n    import { propsModel } from './props'\n    const props = defineProps(propsModel)\n    </script>\n      `)\n    assertCode(content)\n    expect(content).toMatch(`export default {\n  props: propsModel,`)\n  })\n\n  // #4764\n  test('w/ leading code', () => {\n    const { content } = compile(`\n    <script setup>import { x } from './x'\n    const props = defineProps({})\n    </script>\n    `)\n    // props declaration should be inside setup, not moved along with the import\n    expect(content).not.toMatch(`const props = __props\\nimport`)\n    assertCode(content)\n  })\n\n  test('defineProps w/ runtime options', () => {\n    const { content } = compile(`\n<script setup lang=\"ts\">\nconst props = defineProps({ foo: String })\n</script>\n    `)\n    assertCode(content)\n    expect(content).toMatch(`export default /*@__PURE__*/_defineComponent({\n  props: { foo: String },\n  setup(__props, { expose: __expose }) {`)\n  })\n\n  test('w/ type', () => {\n    const { content, bindings } = compile(`\n    <script setup lang=\"ts\">\n    interface Test {}\n\n    type Alias = number[]\n\n    defineProps<{\n      string: string\n      number: number\n      boolean: boolean\n      object: object\n      objectLiteral: { a: number }\n      fn: (n: number) => void\n      functionRef: Function\n      objectRef: Object\n      dateTime: Date\n      array: string[]\n      arrayRef: Array<any>\n      tuple: [number, number]\n      set: Set<string>\n      literal: 'foo'\n      optional?: any\n      recordRef: Record<string, null>\n      interface: Test\n      alias: Alias\n      method(): void\n      symbol: symbol\n      error: Error\n      extract: Extract<1 | 2 | boolean, 2>\n      exclude: Exclude<1 | 2 | boolean, 2>\n      uppercase: Uppercase<'foo'>\n      params: Parameters<(foo: any) => void>\n      nonNull: NonNullable<string | null>\n      objectOrFn: {\n        (): void\n        foo: string\n      }\n\n      union: string | number\n      literalUnion: 'foo' | 'bar'\n      literalUnionNumber: 1 | 2 | 3 | 4 | 5\n      literalUnionMixed: 'foo' | 1 | boolean\n      intersection: Test & {}\n      intersection2: 'foo' & ('foo' | 'bar')\n      foo: ((item: any) => boolean) | null\n\n      unknown: UnknownType\n      unknownUnion: UnknownType | string\n      unknownIntersection: UnknownType & Object\n      unknownUnionWithBoolean: UnknownType | boolean\n      unknownUnionWithFunction: UnknownType | (() => any)\n    }>()\n    </script>`)\n    assertCode(content)\n    expect(content).toMatch(`string: { type: String, required: true }`)\n    expect(content).toMatch(`number: { type: Number, required: true }`)\n    expect(content).toMatch(`boolean: { type: Boolean, required: true }`)\n    expect(content).toMatch(`object: { type: Object, required: true }`)\n    expect(content).toMatch(`objectLiteral: { type: Object, required: true }`)\n    expect(content).toMatch(`fn: { type: Function, required: true }`)\n    expect(content).toMatch(`functionRef: { type: Function, required: true }`)\n    expect(content).toMatch(`objectRef: { type: Object, required: true }`)\n    expect(content).toMatch(`dateTime: { type: Date, required: true }`)\n    expect(content).toMatch(`array: { type: Array, required: true }`)\n    expect(content).toMatch(`arrayRef: { type: Array, required: true }`)\n    expect(content).toMatch(`tuple: { type: Array, required: true }`)\n    expect(content).toMatch(`set: { type: Set, required: true }`)\n    expect(content).toMatch(`literal: { type: String, required: true }`)\n    expect(content).toMatch(`optional: { type: null, required: false }`)\n    expect(content).toMatch(`recordRef: { type: Object, required: true }`)\n    expect(content).toMatch(`interface: { type: Object, required: true }`)\n    expect(content).toMatch(`alias: { type: Array, required: true }`)\n    expect(content).toMatch(`method: { type: Function, required: true }`)\n    expect(content).toMatch(`symbol: { type: Symbol, required: true }`)\n    expect(content).toMatch(`error: { type: Error, required: true }`)\n    expect(content).toMatch(\n      `objectOrFn: { type: [Function, Object], required: true },`,\n    )\n    expect(content).toMatch(`extract: { type: Number, required: true }`)\n    expect(content).toMatch(\n      `exclude: { type: [Number, Boolean], required: true }`,\n    )\n    expect(content).toMatch(`uppercase: { type: String, required: true }`)\n    expect(content).toMatch(`params: { type: Array, required: true }`)\n    expect(content).toMatch(`nonNull: { type: String, required: true }`)\n    expect(content).toMatch(`union: { type: [String, Number], required: true }`)\n    expect(content).toMatch(`literalUnion: { type: String, required: true }`)\n    expect(content).toMatch(\n      `literalUnionNumber: { type: Number, required: true }`,\n    )\n    expect(content).toMatch(\n      `literalUnionMixed: { type: [String, Number, Boolean], required: true }`,\n    )\n    expect(content).toMatch(`intersection: { type: Object, required: true }`)\n    expect(content).toMatch(`intersection2: { type: String, required: true }`)\n    expect(content).toMatch(`foo: { type: [Function, null], required: true }`)\n    expect(content).toMatch(`unknown: { type: null, required: true }`)\n    // uninon containing unknown type: skip check\n    expect(content).toMatch(`unknownUnion: { type: null, required: true }`)\n    // intersection containing unknown type: narrow to the known types\n    expect(content).toMatch(\n      `unknownIntersection: { type: Object, required: true },`,\n    )\n    expect(content).toMatch(\n      `unknownUnionWithBoolean: { type: Boolean, required: true, skipCheck: true },`,\n    )\n    expect(content).toMatch(\n      `unknownUnionWithFunction: { type: Function, required: true, skipCheck: true }`,\n    )\n    expect(bindings).toStrictEqual({\n      string: BindingTypes.PROPS,\n      number: BindingTypes.PROPS,\n      boolean: BindingTypes.PROPS,\n      object: BindingTypes.PROPS,\n      objectLiteral: BindingTypes.PROPS,\n      fn: BindingTypes.PROPS,\n      functionRef: BindingTypes.PROPS,\n      objectRef: BindingTypes.PROPS,\n      dateTime: BindingTypes.PROPS,\n      array: BindingTypes.PROPS,\n      arrayRef: BindingTypes.PROPS,\n      tuple: BindingTypes.PROPS,\n      set: BindingTypes.PROPS,\n      literal: BindingTypes.PROPS,\n      optional: BindingTypes.PROPS,\n      recordRef: BindingTypes.PROPS,\n      interface: BindingTypes.PROPS,\n      alias: BindingTypes.PROPS,\n      method: BindingTypes.PROPS,\n      symbol: BindingTypes.PROPS,\n      error: BindingTypes.PROPS,\n      objectOrFn: BindingTypes.PROPS,\n      extract: BindingTypes.PROPS,\n      exclude: BindingTypes.PROPS,\n      union: BindingTypes.PROPS,\n      literalUnion: BindingTypes.PROPS,\n      literalUnionNumber: BindingTypes.PROPS,\n      literalUnionMixed: BindingTypes.PROPS,\n      intersection: BindingTypes.PROPS,\n      intersection2: BindingTypes.PROPS,\n      foo: BindingTypes.PROPS,\n      uppercase: BindingTypes.PROPS,\n      params: BindingTypes.PROPS,\n      nonNull: BindingTypes.PROPS,\n      unknown: BindingTypes.PROPS,\n      unknownUnion: BindingTypes.PROPS,\n      unknownIntersection: BindingTypes.PROPS,\n      unknownUnionWithBoolean: BindingTypes.PROPS,\n      unknownUnionWithFunction: BindingTypes.PROPS,\n    })\n  })\n\n  test('w/ interface', () => {\n    const { content, bindings } = compile(`\n    <script setup lang=\"ts\">\n    interface Props { x?: number }\n    defineProps<Props>()\n    </script>\n    `)\n    assertCode(content)\n    expect(content).toMatch(`x: { type: Number, required: false }`)\n    expect(bindings).toStrictEqual({\n      x: BindingTypes.PROPS,\n    })\n  })\n\n  test('w/ extends interface', () => {\n    const { content, bindings } = compile(`\n    <script lang=\"ts\">\n      interface Foo { x?: number }\n    </script>\n    <script setup lang=\"ts\">\n      interface Bar extends Foo { y?: number }\n      interface Props extends Bar {\n        z: number\n        y: string\n      }\n      defineProps<Props>()\n    </script>\n    `)\n    assertCode(content)\n    expect(content).toMatch(`z: { type: Number, required: true }`)\n    expect(content).toMatch(`y: { type: String, required: true }`)\n    expect(content).toMatch(`x: { type: Number, required: false }`)\n    expect(bindings).toStrictEqual({\n      x: BindingTypes.PROPS,\n      y: BindingTypes.PROPS,\n      z: BindingTypes.PROPS,\n    })\n  })\n\n  test('w/ extends intersection type', () => {\n    const { content, bindings } = compile(`\n    <script setup lang=\"ts\">\n      type Foo = {\n        x?: number;\n      };\n      interface Props extends Foo {\n        z: number\n        y: string\n      }\n      defineProps<Props>()\n    </script>\n    `)\n    assertCode(content)\n    expect(content).toMatch(`z: { type: Number, required: true }`)\n    expect(content).toMatch(`y: { type: String, required: true }`)\n    expect(content).toMatch(`x: { type: Number, required: false }`)\n    expect(bindings).toStrictEqual({\n      x: BindingTypes.PROPS,\n      y: BindingTypes.PROPS,\n      z: BindingTypes.PROPS,\n    })\n  })\n\n  test('w/ intersection type', () => {\n    const { content, bindings } = compile(`\n    <script setup lang=\"ts\">\n      type Foo = {\n        x?: number;\n      };\n      type Bar = {\n        y: string;\n      };\n      defineProps<Foo & Bar>()\n    </script>\n    `)\n    assertCode(content)\n    expect(content).toMatch(`y: { type: String, required: true }`)\n    expect(content).toMatch(`x: { type: Number, required: false }`)\n    expect(bindings).toStrictEqual({\n      x: BindingTypes.PROPS,\n      y: BindingTypes.PROPS,\n    })\n  })\n\n  test('w/ exported interface', () => {\n    const { content, bindings } = compile(`\n    <script setup lang=\"ts\">\n    export interface Props { x?: number }\n    defineProps<Props>()\n    </script>\n    `)\n    assertCode(content)\n    expect(content).toMatch(`x: { type: Number, required: false }`)\n    expect(bindings).toStrictEqual({\n      x: BindingTypes.PROPS,\n    })\n  })\n\n  test('w/ exported interface in normal script', () => {\n    const { content, bindings } = compile(`\n    <script lang=\"ts\">\n      export interface Props { x?: number }\n    </script>\n    <script setup lang=\"ts\">\n      defineProps<Props>()\n    </script>\n    `)\n    assertCode(content)\n    expect(content).toMatch(`x: { type: Number, required: false }`)\n    expect(bindings).toStrictEqual({\n      x: BindingTypes.PROPS,\n    })\n  })\n\n  test('w/ type alias', () => {\n    const { content, bindings } = compile(`\n    <script setup lang=\"ts\">\n    type Props = { x?: number }\n    defineProps<Props>()\n    </script>\n    `)\n    assertCode(content)\n    expect(content).toMatch(`x: { type: Number, required: false }`)\n    expect(bindings).toStrictEqual({\n      x: BindingTypes.PROPS,\n    })\n  })\n\n  test('w/ exported type alias', () => {\n    const { content, bindings } = compile(`\n    <script setup lang=\"ts\">\n    export type Props = { x?: number }\n    defineProps<Props>()\n    </script>\n    `)\n    assertCode(content)\n    expect(content).toMatch(`x: { type: Number, required: false }`)\n    expect(bindings).toStrictEqual({\n      x: BindingTypes.PROPS,\n    })\n  })\n\n  test('w/ TS assertion', () => {\n    const { content, bindings } = compile(`\n    <script setup lang=\"ts\">\n      defineProps(['foo'])! as any\n    </script>\n  `)\n    expect(content).toMatch(`props: ['foo']`)\n    assertCode(content)\n    expect(bindings).toStrictEqual({\n      foo: BindingTypes.PROPS,\n    })\n  })\n\n  test('withDefaults (static)', () => {\n    const { content, bindings } = compile(`\n    <script setup lang=\"ts\">\n    const props = withDefaults(defineProps<{\n      foo?: string\n      bar?: number;\n      baz: boolean;\n      qux?(): number;\n      quux?(): void\n      quuxx?: Promise<string>;\n      quuux?: number;\n      fred?: string\n    }>(), {\n      foo: 'hi',\n      qux() { return 1 },\n      ['quux']() { },\n      async quuxx() { return await Promise.resolve('hi') },\n      quuux(a, [b, ...c], {d, ...e}, ...f) { return 1 },\n      get fred() { return 'fred' }\n    })\n    </script>\n    `)\n    assertCode(content)\n    expect(content).toMatch(\n      `foo: { type: String, required: false, default: 'hi' }`,\n    )\n    expect(content).toMatch(`bar: { type: Number, required: false }`)\n    expect(content).toMatch(`baz: { type: Boolean, required: true }`)\n    expect(content).toMatch(\n      `qux: { type: Function, required: false, default() { return 1 } }`,\n    )\n    expect(content).toMatch(\n      `quux: { type: Function, required: false, default() { } }`,\n    )\n    expect(content).toMatch(\n      `quuxx: { type: Promise, required: false, async default() { return await Promise.resolve('hi') } }`,\n    )\n    expect(content).toMatch(\n      `quuux: { type: Number, required: false, default(a, [b, ...c], {d, ...e}, ...f) { return 1 } }`,\n    )\n    expect(content).toMatch(\n      `fred: { type: String, required: false, get default() { return 'fred' } }`,\n    )\n    expect(content).toMatch(`const props = __props`)\n    expect(bindings).toStrictEqual({\n      foo: BindingTypes.PROPS,\n      bar: BindingTypes.PROPS,\n      baz: BindingTypes.PROPS,\n      qux: BindingTypes.PROPS,\n      quux: BindingTypes.PROPS,\n      quuxx: BindingTypes.PROPS,\n      quuux: BindingTypes.PROPS,\n      fred: BindingTypes.PROPS,\n      props: BindingTypes.SETUP_CONST,\n    })\n  })\n\n  test('withDefaults (static) + normal script', () => {\n    const { content } = compile(`\n    <script lang=\"ts\">\n      interface Props {\n        a?: string;\n      }\n    </script>\n    <script setup lang=\"ts\">\n      const props = withDefaults(defineProps<Props>(), {\n        a: \"a\",\n      });\n    </script>\n    `)\n    assertCode(content)\n  })\n\n  // #7111\n  test('withDefaults (static) w/ production mode', () => {\n    const { content } = compile(\n      `\n    <script setup lang=\"ts\">\n    const props = withDefaults(defineProps<{\n      foo: () => void\n      bar: boolean\n      baz: boolean | (() => void)\n      qux: string | number\n    }>(), {\n      baz: true,\n      qux: 'hi'\n    })\n    </script>\n    `,\n      { isProd: true },\n    )\n    assertCode(content)\n    expect(content).toMatch(`const props = __props`)\n\n    // foo has no default value, the Function can be dropped\n    expect(content).toMatch(`foo: {}`)\n    expect(content).toMatch(`bar: { type: Boolean }`)\n    expect(content).toMatch(`baz: { type: [Boolean, Function], default: true }`)\n    expect(content).toMatch(`qux: { default: 'hi' }`)\n  })\n\n  test('withDefaults (dynamic)', () => {\n    const { content } = compile(`\n    <script setup lang=\"ts\">\n    import { defaults } from './foo'\n    const props = withDefaults(defineProps<{\n      foo?: string\n      bar?: number\n      baz: boolean\n    }>(), { ...defaults })\n    </script>\n    `)\n    assertCode(content)\n    expect(content).toMatch(`import { mergeDefaults as _mergeDefaults`)\n    expect(content).toMatch(\n      `\n  _mergeDefaults({\n    foo: { type: String, required: false },\n    bar: { type: Number, required: false },\n    baz: { type: Boolean, required: true }\n  }, { ...defaults })`.trim(),\n    )\n  })\n\n  test('withDefaults (reference)', () => {\n    const { content } = compile(`\n    <script setup lang=\"ts\">\n    import { defaults } from './foo'\n    const props = withDefaults(defineProps<{\n      foo?: string\n      bar?: number\n      baz: boolean\n    }>(), defaults)\n    </script>\n    `)\n    assertCode(content)\n    expect(content).toMatch(`import { mergeDefaults as _mergeDefaults`)\n    expect(content).toMatch(\n      `\n  _mergeDefaults({\n    foo: { type: String, required: false },\n    bar: { type: Number, required: false },\n    baz: { type: Boolean, required: true }\n  }, defaults)`.trim(),\n    )\n  })\n\n  // #7111\n  test('withDefaults (dynamic) w/ production mode', () => {\n    const { content } = compile(\n      `\n    <script setup lang=\"ts\">\n    import { defaults } from './foo'\n    const props = withDefaults(defineProps<{\n      foo: () => void\n      bar: boolean\n      baz: boolean | (() => void)\n      qux: string | number\n    }>(), { ...defaults })\n    </script>\n    `,\n      { isProd: true },\n    )\n    assertCode(content)\n    expect(content).toMatch(`import { mergeDefaults as _mergeDefaults`)\n    expect(content).toMatch(\n      `\n  _mergeDefaults({\n    foo: { type: Function },\n    bar: { type: Boolean },\n    baz: { type: [Boolean, Function] },\n    qux: {}\n  }, { ...defaults })`.trim(),\n    )\n  })\n\n  test('withDefaults w/ dynamic object method', () => {\n    const { content } = compile(`\n    <script setup lang=\"ts\">\n    const props = withDefaults(defineProps<{\n      foo?: () => 'string'\n    }>(), {\n      ['fo' + 'o']() { return 'foo' }\n    })\n    </script>\n    `)\n    assertCode(content)\n    expect(content).toMatch(`import { mergeDefaults as _mergeDefaults`)\n    expect(content).toMatch(\n      `\n  _mergeDefaults({\n    foo: { type: Function, required: false }\n  }, {\n      ['fo' + 'o']() { return 'foo' }\n    })`.trim(),\n    )\n  })\n\n  test('runtime inference for Enum', () => {\n    expect(\n      compile(\n        `<script setup lang=\"ts\">\n      const enum Foo { A = 123 }\n      defineProps<{\n        foo: Foo\n      }>()\n      </script>`,\n        { hoistStatic: true },\n      ).content,\n    ).toMatch(`foo: { type: Number`)\n\n    expect(\n      compile(\n        `<script setup lang=\"ts\">\n      const enum Foo { A = '123' }\n      defineProps<{\n        foo: Foo\n      }>()\n      </script>`,\n        { hoistStatic: true },\n      ).content,\n    ).toMatch(`foo: { type: String`)\n\n    expect(\n      compile(\n        `<script setup lang=\"ts\">\n      const enum Foo { A = '123', B = 123 }\n      defineProps<{\n        foo: Foo\n      }>()\n      </script>`,\n        { hoistStatic: true },\n      ).content,\n    ).toMatch(`foo: { type: [String, Number]`)\n\n    expect(\n      compile(\n        `<script setup lang=\"ts\">\n      const enum Foo { A, B }\n      defineProps<{\n        foo: Foo\n      }>()\n      </script>`,\n        { hoistStatic: true },\n      ).content,\n    ).toMatch(`foo: { type: Number`)\n  })\n\n  // #8148\n  test('should not override local bindings', () => {\n    const { bindings } = compile(`\n    <script setup lang=\"ts\">\n    import { computed } from 'vue'\n    defineProps<{ bar: string }>()\n    const bar = computed(() => 1)\n    </script>\n  `)\n    expect(bindings).toStrictEqual({\n      bar: BindingTypes.SETUP_REF,\n      computed: BindingTypes.SETUP_CONST,\n    })\n  })\n\n  // #8289\n  test('destructure without enabling reactive destructure', () => {\n    const { content, bindings } = compile(\n      `<script setup lang=\"ts\">\n      const { foo } = defineProps<{\n        foo: Foo\n      }>()\n      </script>`,\n      {\n        propsDestructure: false,\n      },\n    )\n    expect(content).toMatch(`const { foo } = __props`)\n    expect(content).toMatch(`return { foo }`)\n    expect(bindings).toStrictEqual({\n      foo: BindingTypes.SETUP_CONST,\n    })\n    assertCode(content)\n  })\n\n  test('prohibiting reactive destructure', () => {\n    expect(() =>\n      compile(\n        `<script setup lang=\"ts\">\n      const { foo } = defineProps<{\n        foo: Foo\n      }>()\n      </script>`,\n        {\n          propsDestructure: 'error',\n        },\n      ),\n    ).toThrow()\n  })\n\n  describe('errors', () => {\n    test('w/ both type and non-type args', () => {\n      expect(() => {\n        compile(`<script setup lang=\"ts\">\n        defineProps<{}>({})\n        </script>`)\n      }).toThrow(`cannot accept both type and non-type arguments`)\n    })\n  })\n\n  test('should escape names w/ special symbols', () => {\n    const { content, bindings } = compile(`\n    <script setup lang=\"ts\">\n    defineProps<{\n      'spa ce': unknown\n      'exclamation!mark': unknown\n      'double\"quote': unknown\n      'hash#tag': unknown\n      'dollar$sign': unknown\n      'percentage%sign': unknown\n      'amper&sand': unknown\n      \"single'quote\": unknown\n      'round(brack)ets': unknown\n      'aste*risk': unknown\n      'pl+us': unknown\n      'com,ma': unknown\n      'do.t': unknown\n      'sla/sh': unknown\n      'co:lon': unknown\n      'semi;colon': unknown\n      'angle<brack>ets': unknown\n      'equal=sign': unknown\n      'question?mark': unknown\n      'at@sign': unknown\n      'square[brack]ets': unknown\n      'back\\\\\\\\slash': unknown\n      'ca^ret': unknown\n      'back\\`tick': unknown\n      'curly{bra}ces': unknown\n      'pi|pe': unknown\n      'til~de': unknown\n      'da-sh': unknown\n    }>()\n    </script>`)\n    assertCode(content)\n    expect(content).toMatch(`\"spa ce\": { type: null, required: true }`)\n    expect(content).toMatch(\n      `\"exclamation!mark\": { type: null, required: true }`,\n    )\n    expect(content).toMatch(`\"double\\\\\"quote\": { type: null, required: true }`)\n    expect(content).toMatch(`\"hash#tag\": { type: null, required: true }`)\n    expect(content).toMatch(`\"dollar$sign\": { type: null, required: true }`)\n    expect(content).toMatch(`\"percentage%sign\": { type: null, required: true }`)\n    expect(content).toMatch(`\"amper&sand\": { type: null, required: true }`)\n    expect(content).toMatch(`\"single'quote\": { type: null, required: true }`)\n    expect(content).toMatch(`\"round(brack)ets\": { type: null, required: true }`)\n    expect(content).toMatch(`\"aste*risk\": { type: null, required: true }`)\n    expect(content).toMatch(`\"pl+us\": { type: null, required: true }`)\n    expect(content).toMatch(`\"com,ma\": { type: null, required: true }`)\n    expect(content).toMatch(`\"do.t\": { type: null, required: true }`)\n    expect(content).toMatch(`\"sla/sh\": { type: null, required: true }`)\n    expect(content).toMatch(`\"co:lon\": { type: null, required: true }`)\n    expect(content).toMatch(`\"semi;colon\": { type: null, required: true }`)\n    expect(content).toMatch(`\"angle<brack>ets\": { type: null, required: true }`)\n    expect(content).toMatch(`\"equal=sign\": { type: null, required: true }`)\n    expect(content).toMatch(`\"question?mark\": { type: null, required: true }`)\n    expect(content).toMatch(`\"at@sign\": { type: null, required: true }`)\n    expect(content).toMatch(\n      `\"square[brack]ets\": { type: null, required: true }`,\n    )\n    expect(content).toMatch(`\"back\\\\\\\\slash\": { type: null, required: true }`)\n    expect(content).toMatch(`\"ca^ret\": { type: null, required: true }`)\n    expect(content).toMatch(`\"back\\`tick\": { type: null, required: true }`)\n    expect(content).toMatch(`\"curly{bra}ces\": { type: null, required: true }`)\n    expect(content).toMatch(`\"pi|pe\": { type: null, required: true }`)\n    expect(content).toMatch(`\"til~de\": { type: null, required: true }`)\n    expect(content).toMatch(`\"da-sh\": { type: null, required: true }`)\n    expect(bindings).toStrictEqual({\n      'spa ce': BindingTypes.PROPS,\n      'exclamation!mark': BindingTypes.PROPS,\n      'double\"quote': BindingTypes.PROPS,\n      'hash#tag': BindingTypes.PROPS,\n      dollar$sign: BindingTypes.PROPS,\n      'percentage%sign': BindingTypes.PROPS,\n      'amper&sand': BindingTypes.PROPS,\n      \"single'quote\": BindingTypes.PROPS,\n      'round(brack)ets': BindingTypes.PROPS,\n      'aste*risk': BindingTypes.PROPS,\n      'pl+us': BindingTypes.PROPS,\n      'com,ma': BindingTypes.PROPS,\n      'do.t': BindingTypes.PROPS,\n      'sla/sh': BindingTypes.PROPS,\n      'co:lon': BindingTypes.PROPS,\n      'semi;colon': BindingTypes.PROPS,\n      'angle<brack>ets': BindingTypes.PROPS,\n      'equal=sign': BindingTypes.PROPS,\n      'question?mark': BindingTypes.PROPS,\n      'at@sign': BindingTypes.PROPS,\n      'square[brack]ets': BindingTypes.PROPS,\n      'back\\\\slash': BindingTypes.PROPS,\n      'ca^ret': BindingTypes.PROPS,\n      'back`tick': BindingTypes.PROPS,\n      'curly{bra}ces': BindingTypes.PROPS,\n      'pi|pe': BindingTypes.PROPS,\n      'til~de': BindingTypes.PROPS,\n      'da-sh': BindingTypes.PROPS,\n    })\n  })\n\n  // #8989\n  test('custom element retains the props type & production mode', () => {\n    const { content } = compile(\n      `<script setup lang=\"ts\">\n      const props = defineProps<{ foo: number}>()\n      </script>`,\n      { isProd: true, customElement: filename => /\\.ce\\.vue$/.test(filename) },\n      { filename: 'app.ce.vue' },\n    )\n\n    expect(content).toMatch(`foo: {type: Number}`)\n    assertCode(content)\n  })\n\n  test('custom element retains the props type & default value & production mode', () => {\n    const { content } = compile(\n      `<script setup lang=\"ts\">\n      interface Props { \n          foo?: number;\n      }\n      const props = withDefaults(defineProps<Props>(), {\n          foo: 5.5,\n      });\n      </script>`,\n      { isProd: true, customElement: filename => /\\.ce\\.vue$/.test(filename) },\n      { filename: 'app.ce.vue' },\n    )\n    expect(content).toMatch(`foo: { default: 5.5, type: Number }`)\n    assertCode(content)\n  })\n})\n"
  },
  {
    "path": "packages/compiler-sfc/__tests__/compileScript/definePropsDestructure.spec.ts",
    "content": "import { BindingTypes } from '@vue/compiler-core'\nimport type { SFCScriptCompileOptions } from '../../src'\nimport { assertCode, compileSFCScript } from '../utils'\n\ndescribe('sfc reactive props destructure', () => {\n  function compile(src: string, options?: Partial<SFCScriptCompileOptions>) {\n    return compileSFCScript(src, {\n      inlineTemplate: true,\n      ...options,\n    })\n  }\n\n  test('basic usage', () => {\n    const { content, bindings } = compile(`\n      <script setup>\n      const { foo } = defineProps(['foo'])\n      console.log(foo)\n      </script>\n      <template>{{ foo }}</template>\n    `)\n    expect(content).not.toMatch(`const { foo } =`)\n    expect(content).toMatch(`console.log(__props.foo)`)\n    expect(content).toMatch(`_toDisplayString(__props.foo)`)\n    assertCode(content)\n    expect(bindings).toStrictEqual({\n      foo: BindingTypes.PROPS,\n    })\n  })\n\n  test('multiple variable declarations', () => {\n    const { content, bindings } = compile(`\n      <script setup>\n      const bar = 'fish', { foo } = defineProps(['foo']), hello = 'world'\n      </script>\n      <template><div>{{ foo }} {{ hello }} {{ bar }}</div></template>\n    `)\n    expect(content).not.toMatch(`const { foo } =`)\n    expect(content).toMatch(`const bar = 'fish', hello = 'world'`)\n    expect(content).toMatch(`_toDisplayString(hello)`)\n    expect(content).toMatch(`_toDisplayString(bar)`)\n    expect(content).toMatch(`_toDisplayString(__props.foo)`)\n    assertCode(content)\n    expect(bindings).toStrictEqual({\n      foo: BindingTypes.PROPS,\n      bar: BindingTypes.LITERAL_CONST,\n      hello: BindingTypes.LITERAL_CONST,\n    })\n  })\n\n  test('nested scope', () => {\n    const { content, bindings } = compile(`\n      <script setup>\n      const { foo, bar } = defineProps(['foo', 'bar'])\n      function test(foo) {\n        console.log(foo)\n        console.log(bar)\n      }\n      </script>\n    `)\n    expect(content).not.toMatch(`const { foo, bar } =`)\n    expect(content).toMatch(`console.log(foo)`)\n    expect(content).toMatch(`console.log(__props.bar)`)\n    assertCode(content)\n    expect(bindings).toStrictEqual({\n      foo: BindingTypes.PROPS,\n      bar: BindingTypes.PROPS,\n      test: BindingTypes.SETUP_CONST,\n    })\n  })\n\n  test('for-of loop variable shadowing', () => {\n    const { content } = compile(`\n      <script setup lang=\"ts\">\n      interface Props {\n        msg: string;\n        input: string[];\n      }\n      const { msg, input } = defineProps<Props>();\n      for (const msg of input) {\n        console.log('MESSAGE', msg);\n      }\n      console.log('NOT FAIL', { msg });\n      </script>\n    `)\n    // inside loop: should use local variable\n    expect(content).toMatch(`for (const msg of __props.input)`)\n    expect(content).toMatch(`console.log('MESSAGE', msg)`)\n    // after loop: should restore to prop reference\n    expect(content).toMatch(`console.log('NOT FAIL', { msg: __props.msg })`)\n    assertCode(content)\n  })\n\n  test('regular for loop variable shadowing', () => {\n    const { content } = compile(`\n      <script setup lang=\"ts\">\n      const { i, len } = defineProps<{ i: number; len: number }>();\n      for (let i = 0; i < len; i++) {\n        console.log('INDEX', i);\n      }\n      console.log('AFTER', { i });\n      </script>\n    `)\n    // inside loop: should use local variable\n    expect(content).toMatch(`for (let i = 0; i < __props.len; i++)`)\n    expect(content).toMatch(`console.log('INDEX', i)`)\n    // after loop: should restore to prop reference\n    expect(content).toMatch(`console.log('AFTER', { i: __props.i })`)\n    assertCode(content)\n  })\n\n  test('default values w/ array runtime declaration', () => {\n    const { content } = compile(`\n      <script setup>\n      const { foo = 1, bar = {}, func = () => {} } = defineProps(['foo', 'bar', 'baz'])\n      </script>\n    `)\n    // literals can be used as-is, non-literals are always returned from a\n    // function\n    // functions need to be marked with a skip marker\n    expect(content)\n      .toMatch(`props: /*@__PURE__*/_mergeDefaults(['foo', 'bar', 'baz'], {\n  foo: 1,\n  bar: () => ({}),\n  func: () => {}, __skip_func: true\n})`)\n    assertCode(content)\n  })\n\n  test('default values w/ object runtime declaration', () => {\n    const { content } = compile(`\n      <script setup>\n      const { foo = 1, bar = {}, func = () => {}, ext = x } = defineProps({ foo: Number, bar: Object, func: Function, ext: null })\n      </script>\n    `)\n    // literals can be used as-is, non-literals are always returned from a\n    // function\n    // functions need to be marked with a skip marker since we cannot always\n    // safely infer whether runtime type is Function (e.g. if the runtime decl\n    // is imported, or spreads another object)\n    expect(content)\n      .toMatch(`props: /*@__PURE__*/_mergeDefaults({ foo: Number, bar: Object, func: Function, ext: null }, {\n  foo: 1,\n  bar: () => ({}),\n  func: () => {}, __skip_func: true,\n  ext: x, __skip_ext: true\n})`)\n    assertCode(content)\n  })\n  test('default values w/ runtime declaration & key is string', () => {\n    const { content, bindings } = compile(`\n      <script setup>\n      const { foo = 1, 'foo:bar': fooBar = 'foo-bar' } = defineProps(['foo', 'foo:bar'])\n      </script>\n    `)\n    expect(bindings).toStrictEqual({\n      __propsAliases: {\n        fooBar: 'foo:bar',\n      },\n      foo: BindingTypes.PROPS,\n      'foo:bar': BindingTypes.PROPS,\n      fooBar: BindingTypes.PROPS_ALIASED,\n    })\n\n    expect(content).toMatch(`\n  props: /*@__PURE__*/_mergeDefaults(['foo', 'foo:bar'], {\n  foo: 1,\n  \"foo:bar\": 'foo-bar'\n}),`)\n    assertCode(content)\n  })\n\n  test('default values w/ type declaration', () => {\n    const { content } = compile(`\n      <script setup lang=\"ts\">\n      const { foo = 1, bar = {}, func = () => {} } = defineProps<{ foo?: number, bar?: object, func?: () => any }>()\n      </script>\n    `)\n    // literals can be used as-is, non-literals are always returned from a\n    // function\n    expect(content).toMatch(`props: {\n    foo: { type: Number, required: false, default: 1 },\n    bar: { type: Object, required: false, default: () => ({}) },\n    func: { type: Function, required: false, default: () => {} }\n  }`)\n    assertCode(content)\n  })\n\n  test('default values w/ type declaration & key is string', () => {\n    const { content, bindings } = compile(`\n      <script setup lang=\"ts\">\n      const { foo = 1, bar = 2, 'foo:bar': fooBar = 'foo-bar' } = defineProps<{ \n        \"foo\": number // double-quoted string\n        'bar': number // single-quoted string\n        'foo:bar': string // single-quoted string containing symbols\n        \"onUpdate:modelValue\": (val: number) => void  // double-quoted string containing symbols\n      }>()\n      </script>\n    `)\n    expect(bindings).toStrictEqual({\n      __propsAliases: {\n        fooBar: 'foo:bar',\n      },\n      foo: BindingTypes.PROPS,\n      bar: BindingTypes.PROPS,\n      'foo:bar': BindingTypes.PROPS,\n      fooBar: BindingTypes.PROPS_ALIASED,\n      'onUpdate:modelValue': BindingTypes.PROPS,\n    })\n    expect(content).toMatch(`\n  props: {\n    foo: { type: Number, required: true, default: 1 },\n    bar: { type: Number, required: true, default: 2 },\n    \"foo:bar\": { type: String, required: true, default: 'foo-bar' },\n    \"onUpdate:modelValue\": { type: Function, required: true }\n  },`)\n    assertCode(content)\n  })\n\n  test('default values w/ type declaration, prod mode', () => {\n    const { content } = compile(\n      `\n      <script setup lang=\"ts\">\n      const { foo = 1, bar = {}, func = () => {} } = defineProps<{ foo?: number, bar?: object, baz?: any, boola?: boolean, boolb?: boolean | number, func?: Function }>()\n      </script>\n    `,\n      { isProd: true },\n    )\n    assertCode(content)\n    // literals can be used as-is, non-literals are always returned from a\n    // function\n    expect(content).toMatch(`props: {\n    foo: { default: 1 },\n    bar: { default: () => ({}) },\n    baz: {},\n    boola: { type: Boolean },\n    boolb: { type: [Boolean, Number] },\n    func: { type: Function, default: () => {} }\n  }`)\n  })\n\n  test('with TSInstantiationExpression', () => {\n    const { content } = compile(\n      `\n      <script setup lang=\"ts\">\n      type Foo = <T extends string | number>(data: T) => void\n      const { value } = defineProps<{ value: Foo }>()\n      const foo = value<123>\n      </script>\n    `,\n      { isProd: true },\n    )\n    assertCode(content)\n    expect(content).toMatch(`const foo = __props.value<123>`)\n  })\n\n  test('aliasing', () => {\n    const { content, bindings } = compile(`\n      <script setup>\n      const { foo: bar } = defineProps(['foo'])\n      let x = foo\n      let y = bar\n      </script>\n      <template>{{ foo + bar }}</template>\n    `)\n    expect(content).not.toMatch(`const { foo: bar } =`)\n    expect(content).toMatch(`let x = foo`) // should not process\n    expect(content).toMatch(`let y = __props.foo`)\n    // should convert bar to __props.foo in template expressions\n    expect(content).toMatch(`_toDisplayString(__props.foo + __props.foo)`)\n    assertCode(content)\n    expect(bindings).toStrictEqual({\n      x: BindingTypes.SETUP_LET,\n      y: BindingTypes.SETUP_LET,\n      foo: BindingTypes.PROPS,\n      bar: BindingTypes.PROPS_ALIASED,\n      __propsAliases: {\n        bar: 'foo',\n      },\n    })\n  })\n\n  // #5425\n  test('non-identifier prop names', () => {\n    const { content, bindings } = compile(`\n      <script setup>\n      const { 'foo.bar': fooBar } = defineProps({ 'foo.bar': Function })\n      let x = fooBar\n      </script>\n      <template>{{ fooBar }}</template>\n    `)\n    expect(content).toMatch(`x = __props[\"foo.bar\"]`)\n    expect(content).toMatch(`toDisplayString(__props[\"foo.bar\"])`)\n    assertCode(content)\n    expect(bindings).toStrictEqual({\n      x: BindingTypes.SETUP_LET,\n      'foo.bar': BindingTypes.PROPS,\n      fooBar: BindingTypes.PROPS_ALIASED,\n      __propsAliases: {\n        fooBar: 'foo.bar',\n      },\n    })\n  })\n\n  test('rest spread', () => {\n    const { content, bindings } = compile(`\n      <script setup>\n      const { foo, bar, ...rest } = defineProps(['foo', 'bar', 'baz'])\n      </script>\n    `)\n    expect(content).toMatch(\n      `const rest = _createPropsRestProxy(__props, [\"foo\",\"bar\"])`,\n    )\n    assertCode(content)\n    expect(bindings).toStrictEqual({\n      foo: BindingTypes.PROPS,\n      bar: BindingTypes.PROPS,\n      baz: BindingTypes.PROPS,\n      rest: BindingTypes.SETUP_REACTIVE_CONST,\n    })\n  })\n\n  test('rest spread non-inline', () => {\n    const { content, bindings } = compile(\n      `\n      <script setup>\n      const { foo, ...rest } = defineProps(['foo', 'bar'])\n      </script>\n      <template>{{ rest.bar }}</template>\n    `,\n      { inlineTemplate: false },\n    )\n    expect(content).toMatch(\n      `const rest = _createPropsRestProxy(__props, [\"foo\"])`,\n    )\n    assertCode(content)\n    expect(bindings).toStrictEqual({\n      foo: BindingTypes.PROPS,\n      bar: BindingTypes.PROPS,\n      rest: BindingTypes.SETUP_REACTIVE_CONST,\n    })\n  })\n\n  // #6960\n  test('computed static key', () => {\n    const { content, bindings } = compile(`\n    <script setup>\n    const { ['foo']: foo } = defineProps(['foo'])\n    console.log(foo)\n    </script>\n    <template>{{ foo }}</template>\n  `)\n    expect(content).not.toMatch(`const { foo } =`)\n    expect(content).toMatch(`console.log(__props.foo)`)\n    expect(content).toMatch(`_toDisplayString(__props.foo)`)\n    assertCode(content)\n    expect(bindings).toStrictEqual({\n      foo: BindingTypes.PROPS,\n    })\n  })\n\n  test('multi-variable declaration', () => {\n    const { content } = compile(`\n    <script setup>\n    const { item } = defineProps(['item']),\n      a = 1;\n    </script>\n  `)\n    assertCode(content)\n    expect(content).toMatch(`const a = 1;`)\n    expect(content).toMatch(`props: ['item'],`)\n  })\n\n  // #6757\n  test('multi-variable declaration fix #6757 ', () => {\n    const { content } = compile(`\n    <script setup>\n    const a = 1,\n      { item } = defineProps(['item']);\n    </script>\n  `)\n    assertCode(content)\n    expect(content).toMatch(`const a = 1;`)\n    expect(content).toMatch(`props: ['item'],`)\n  })\n\n  // #7422\n  test('multi-variable declaration fix #7422', () => {\n    const { content } = compile(`\n    <script setup>\n    const { item } = defineProps(['item']),\n          a = 0,\n          b = 0;\n    </script>\n  `)\n    assertCode(content)\n    expect(content).toMatch(`const a = 0,`)\n    expect(content).toMatch(`b = 0;`)\n    expect(content).toMatch(`props: ['item'],`)\n  })\n\n  test('handle function parameters with same name as destructured props', () => {\n    const { content } = compile(`\n    <script setup>\n    const { value } = defineProps()\n    function test(value) {\n      try {\n      } catch {\n      }\n    }\n    console.log(value)\n    </script>\n  `)\n    assertCode(content)\n    expect(content).toMatch(`console.log(__props.value)`)\n  })\n\n  test('defineProps/defineEmits in multi-variable declaration (full removal)', () => {\n    const { content } = compile(`\n    <script setup>\n    const props = defineProps(['item']),\n          emit = defineEmits(['a']);\n    </script>\n  `)\n    assertCode(content)\n    expect(content).toMatch(`props: ['item'],`)\n    expect(content).toMatch(`emits: ['a'],`)\n  })\n\n  describe('errors', () => {\n    test('should error on deep destructure', () => {\n      expect(() =>\n        compile(\n          `<script setup>const { foo: [bar] } = defineProps(['foo'])</script>`,\n        ),\n      ).toThrow(`destructure does not support nested patterns`)\n\n      expect(() =>\n        compile(\n          `<script setup>const { foo: { bar } } = defineProps(['foo'])</script>`,\n        ),\n      ).toThrow(`destructure does not support nested patterns`)\n    })\n\n    test('should error on computed key', () => {\n      expect(() =>\n        compile(\n          `<script setup>const { [foo]: bar } = defineProps(['foo'])</script>`,\n        ),\n      ).toThrow(`destructure cannot use computed key`)\n    })\n\n    test('should warn when used with withDefaults', () => {\n      compile(\n        `<script setup lang=\"ts\">\n        const { foo } = withDefaults(defineProps<{ foo: string }>(), { foo: 'foo' })\n        </script>`,\n      )\n      expect(\n        `withDefaults() is unnecessary when using destructure`,\n      ).toHaveBeenWarned()\n    })\n\n    test('should error if destructure reference local vars', () => {\n      expect(() =>\n        compile(\n          `<script setup>\n          let x = 1\n          const {\n            foo = () => x\n          } = defineProps(['foo'])\n          </script>`,\n        ),\n      ).toThrow(`cannot reference locally declared variables`)\n    })\n\n    test('should error if assignment to destructured prop binding', () => {\n      expect(() =>\n        compile(\n          `<script setup>\n          const { foo } = defineProps(['foo'])\n          foo = 'bar'\n          </script>`,\n        ),\n      ).toThrow(`Cannot assign to destructured props`)\n\n      expect(() =>\n        compile(\n          `<script setup>\n          let { foo } = defineProps(['foo'])\n          foo = 'bar'\n          </script>`,\n        ),\n      ).toThrow(`Cannot assign to destructured props`)\n    })\n\n    test('should error when passing destructured prop into certain methods', () => {\n      expect(() =>\n        compile(\n          `<script setup>\n        import { watch } from 'vue'\n        const { foo } = defineProps(['foo'])\n        watch(foo, () => {})\n        </script>`,\n        ),\n      ).toThrow(\n        `\"foo\" is a destructured prop and should not be passed directly to watch().`,\n      )\n\n      expect(() =>\n        compile(\n          `<script setup>\n        import { watch as w } from 'vue'\n        const { foo } = defineProps(['foo'])\n        w(foo, () => {})\n        </script>`,\n        ),\n      ).toThrow(\n        `\"foo\" is a destructured prop and should not be passed directly to watch().`,\n      )\n\n      expect(() =>\n        compile(\n          `<script setup>\n        import { toRef } from 'vue'\n        const { foo } = defineProps(['foo'])\n        toRef(foo)\n        </script>`,\n        ),\n      ).toThrow(\n        `\"foo\" is a destructured prop and should not be passed directly to toRef().`,\n      )\n\n      expect(() =>\n        compile(\n          `<script setup>\n        import { toRef as r } from 'vue'\n        const { foo } = defineProps(['foo'])\n        r(foo)\n        </script>`,\n        ),\n      ).toThrow(\n        `\"foo\" is a destructured prop and should not be passed directly to toRef().`,\n      )\n    })\n\n    // not comprehensive, but should help for most common cases\n    test('should error if default value type does not match declared type', () => {\n      expect(() =>\n        compile(\n          `<script setup lang=\"ts\">\n        const { foo = 'hello' } = defineProps<{ foo?: number }>()\n        </script>`,\n        ),\n      ).toThrow(`Default value of prop \"foo\" does not match declared type.`)\n    })\n\n    // #8017\n    test('should not throw an error if the variable is not a props', () => {\n      expect(() =>\n        compile(\n          `<script setup lang='ts'>\n        import { watch } from 'vue'\n        const { userId } = defineProps({ userId: Number })\n        const { error: e, info } = useRequest();\n        watch(e, () => {});\n        watch(info, () => {});\n        </script>`,\n        ),\n      ).not.toThrowError()\n    })\n  })\n})\n"
  },
  {
    "path": "packages/compiler-sfc/__tests__/compileScript/defineSlots.spec.ts",
    "content": "import { assertCode, compileSFCScript as compile } from '../utils'\n\ndescribe('defineSlots()', () => {\n  test('basic usage', () => {\n    const { content } = compile(`\n      <script setup lang=\"ts\">\n      const slots = defineSlots<{\n        default: { msg: string }\n      }>()\n      </script>\n    `)\n    assertCode(content)\n    expect(content).toMatch(`const slots = _useSlots()`)\n    expect(content).not.toMatch('defineSlots')\n  })\n\n  test('w/o return value', () => {\n    const { content } = compile(`\n      <script setup lang=\"ts\">\n      defineSlots<{\n        default: { msg: string }\n      }>()\n      </script>\n    `)\n    assertCode(content)\n    expect(content).not.toMatch('defineSlots')\n    expect(content).not.toMatch(`_useSlots`)\n  })\n\n  test('w/o generic params', () => {\n    const { content } = compile(`\n      <script setup>\n      const slots = defineSlots()\n      </script>\n    `)\n    assertCode(content)\n    expect(content).toMatch(`const slots = _useSlots()`)\n    expect(content).not.toMatch('defineSlots')\n  })\n})\n"
  },
  {
    "path": "packages/compiler-sfc/__tests__/compileScript/hoistStatic.spec.ts",
    "content": "import { BindingTypes } from '@vue/compiler-core'\nimport type { SFCScriptCompileOptions } from '../../src'\nimport { assertCode, compileSFCScript } from '../utils'\n\ndescribe('sfc hoist static', () => {\n  function compile(src: string, options?: Partial<SFCScriptCompileOptions>) {\n    return compileSFCScript(src, {\n      inlineTemplate: true,\n      hoistStatic: true,\n      ...options,\n    })\n  }\n\n  test('should hoist literal value', () => {\n    const code = `\n    const string = 'default value'\n    const number = 123\n    const boolean = false\n    const nil = null\n    const bigint = 100n\n    const template = \\`str\\`\n    `.trim()\n    const { content, bindings } = compile(`\n    <script setup>\n    ${code}\n    </script>\n    `)\n\n    // should hoist to first line\n    expect(content.startsWith(code)).toBe(true)\n    expect(bindings).toStrictEqual({\n      string: BindingTypes.LITERAL_CONST,\n      number: BindingTypes.LITERAL_CONST,\n      boolean: BindingTypes.LITERAL_CONST,\n      nil: BindingTypes.LITERAL_CONST,\n      bigint: BindingTypes.LITERAL_CONST,\n      template: BindingTypes.LITERAL_CONST,\n    })\n    assertCode(content)\n  })\n\n  test('should hoist expressions', () => {\n    const code = `\n    const unary = !false\n    const binary = 1 + 2\n    const conditional = 1 ? 2 : 3\n    const sequence = (1, true, 'foo', 1)\n    `.trim()\n    const { content, bindings } = compile(`\n    <script setup>\n    ${code}\n    </script>\n    `)\n    // should hoist to first line\n    expect(content.startsWith(code)).toBe(true)\n    expect(bindings).toStrictEqual({\n      binary: BindingTypes.LITERAL_CONST,\n      conditional: BindingTypes.LITERAL_CONST,\n      unary: BindingTypes.LITERAL_CONST,\n      sequence: BindingTypes.LITERAL_CONST,\n    })\n    assertCode(content)\n  })\n\n  test('should hoist w/ defineProps/Emits', () => {\n    const hoistCode = `const defaultValue = 'default value'`\n    const { content, bindings } = compile(`\n    <script setup>\n    ${hoistCode}\n    defineProps({\n      foo: {\n        default: defaultValue\n      }\n    })\n    </script>\n    `)\n\n    // should hoist to first line\n    expect(content.startsWith(hoistCode)).toBe(true)\n    expect(bindings).toStrictEqual({\n      foo: BindingTypes.PROPS,\n      defaultValue: BindingTypes.LITERAL_CONST,\n    })\n    assertCode(content)\n  })\n\n  test('should not hoist a variable', () => {\n    const code = `\n    let KEY1 = 'default value'\n    var KEY2 = 123\n    const regex = /.*/g\n    const undef = undefined\n    `.trim()\n    const { content, bindings } = compile(`\n    <script setup>\n    ${code}\n    </script>\n    `)\n    expect(bindings).toStrictEqual({\n      KEY1: BindingTypes.SETUP_LET,\n      KEY2: BindingTypes.SETUP_LET,\n      regex: BindingTypes.SETUP_CONST,\n      undef: BindingTypes.SETUP_MAYBE_REF,\n    })\n    expect(content).toMatch(`setup(__props) {\\n\\n    ${code}`)\n    assertCode(content)\n  })\n\n  test('should not hoist a constant initialized to a reference value', () => {\n    const code = `\n    const KEY1 = Boolean\n    const KEY2 = [Boolean]\n    const KEY3 = [getCurrentInstance()]\n    let i = 0;\n    const KEY4 = (i++, 'foo')\n    enum KEY5 {\n      FOO = 1,\n      BAR = getCurrentInstance(),\n    }\n    const KEY6 = \\`template\\${i}\\`\n    `.trim()\n    const { content, bindings } = compile(`\n    <script setup lang=\"ts\">\n    ${code}\n    </script>\n    `)\n    expect(bindings).toStrictEqual({\n      KEY1: BindingTypes.SETUP_MAYBE_REF,\n      KEY2: BindingTypes.SETUP_CONST,\n      KEY3: BindingTypes.SETUP_CONST,\n      KEY4: BindingTypes.SETUP_CONST,\n      KEY5: BindingTypes.SETUP_CONST,\n      KEY6: BindingTypes.SETUP_CONST,\n      i: BindingTypes.SETUP_LET,\n    })\n    expect(content).toMatch(`setup(__props) {\\n\\n    ${code}`)\n    assertCode(content)\n  })\n\n  test('should not hoist a object or array', () => {\n    const code = `\n    const obj = { foo: 'bar' }\n    const arr = [1, 2, 3]\n    `.trim()\n    const { content, bindings } = compile(`\n    <script setup>\n    ${code}\n    </script>\n    `)\n    expect(bindings).toStrictEqual({\n      arr: BindingTypes.SETUP_CONST,\n      obj: BindingTypes.SETUP_CONST,\n    })\n    expect(content).toMatch(`setup(__props) {\\n\\n    ${code}`)\n    assertCode(content)\n  })\n\n  test('should not hoist a function or class', () => {\n    const code = `\n    const fn = () => {}\n    function fn2() {}\n    class Foo {}\n    `.trim()\n    const { content, bindings } = compile(`\n    <script setup>\n    ${code}\n    </script>\n    `)\n    expect(bindings).toStrictEqual({\n      Foo: BindingTypes.SETUP_CONST,\n      fn: BindingTypes.SETUP_CONST,\n      fn2: BindingTypes.SETUP_CONST,\n    })\n    expect(content).toMatch(`setup(__props) {\\n\\n    ${code}`)\n    assertCode(content)\n  })\n\n  test('should enable when only script setup', () => {\n    const { content, bindings } = compile(`\n    <script>\n    const foo = 'bar'\n    </script>\n    <script setup>\n    const foo = 'bar'\n    </script>\n    `)\n    expect(bindings).toStrictEqual({\n      foo: BindingTypes.SETUP_CONST,\n    })\n    assertCode(content)\n  })\n\n  test('should not hoist when disabled', () => {\n    const { content, bindings } = compile(\n      `\n    <script setup>\n    const foo = 'bar'\n    </script>\n    `,\n      { hoistStatic: false },\n    )\n    expect(bindings).toStrictEqual({\n      foo: BindingTypes.SETUP_CONST,\n    })\n    assertCode(content)\n  })\n\n  test('template binding access in inline mode', () => {\n    const { content } = compile(\n      `\n    <script setup>\n    const foo = 'bar'\n    </script>\n    <template>{{ foo }}</template>\n    `,\n    )\n    expect(content).toMatch('_toDisplayString(foo)')\n  })\n})\n"
  },
  {
    "path": "packages/compiler-sfc/__tests__/compileScript/importUsageCheck.spec.ts",
    "content": "import { assertCode, compileSFCScript as compile } from '../utils'\n\n// in dev mode, declared bindings are returned as an object from setup()\n// when using TS, users may import types which should not be returned as\n// values, so we need to check import usage in the template to determine\n// what to be returned.\n\ntest('components', () => {\n  const { content } = compile(`\n    <script setup lang=\"ts\">\n    import { FooBar, FooBaz, FooQux, foo } from './x'\n    const fooBar: FooBar = 1\n    </script>\n    <template>\n      <FooBaz></FooBaz>\n      <foo-qux/>\n      <foo/>\n      FooBar\n    </template>\n    `)\n  // FooBar: should not be matched by plain text or incorrect case\n  // FooBaz: used as PascalCase component\n  // FooQux: used as kebab-case component\n  // foo: lowercase component\n  expect(content).toMatch(\n    `return { fooBar, get FooBaz() { return FooBaz }, ` +\n      `get FooQux() { return FooQux }, get foo() { return foo } }`,\n  )\n  assertCode(content)\n})\n\ntest('directive', () => {\n  const { content } = compile(`\n    <script setup lang=\"ts\">\n    import { vMyDir } from './x'\n    </script>\n    <template>\n      <div v-my-dir></div>\n    </template>\n    `)\n  expect(content).toMatch(`return { get vMyDir() { return vMyDir } }`)\n  assertCode(content)\n})\n\ntest('dynamic arguments', () => {\n  const { content } = compile(`\n    <script setup lang=\"ts\">\n    import { FooBar, foo, bar, unused, baz, msg } from './x'\n    </script>\n    <template>\n      <FooBar #[foo.slotName] />\n      <FooBar #unused />\n      <div :[bar.attrName]=\"15\"></div>\n      <div unused=\"unused\"></div>\n      <div #[\\`item:\\${baz.key}\\`]=\"{ value }\"></div>\n      <FooBar :msg />\n    </template>\n    `)\n  expect(content).toMatch(\n    `return { get FooBar() { return FooBar }, get foo() { return foo }, ` +\n      `get bar() { return bar }, get baz() { return baz }, get msg() { return msg } }`,\n  )\n  assertCode(content)\n})\n\n// https://github.com/vuejs/core/issues/4599\ntest('attribute expressions', () => {\n  const { content } = compile(`\n    <script setup lang=\"ts\">\n    import { bar, baz } from './x'\n    const cond = true\n    </script>\n    <template>\n      <div :class=\"[cond ? '' : bar(), 'default']\" :style=\"baz\"></div>\n    </template>\n    `)\n  expect(content).toMatch(\n    `return { cond, get bar() { return bar }, get baz() { return baz } }`,\n  )\n  assertCode(content)\n})\n\ntest('vue interpolations', () => {\n  const { content } = compile(`\n  <script setup lang=\"ts\">\n  import { x, y, z, x$y } from './x'\n  </script>\n  <template>\n    <div :id=\"z + 'y'\">{{ x }} {{ yy }} {{ x$y }}</div>\n  </template>\n  `)\n  // x: used in interpolation\n  // y: should not be matched by {{ yy }} or 'y' in binding exps\n  // x$y: #4274 should escape special chars when creating Regex\n  expect(content).toMatch(\n    `return { get x() { return x }, get z() { return z }, get x$y() { return x$y } }`,\n  )\n  assertCode(content)\n})\n\n// #4340 interpolations in template strings\ntest('js template string interpolations', () => {\n  const { content } = compile(`\n    <script setup lang=\"ts\">\n    import { VAR, VAR2, VAR3 } from './x'\n    </script>\n    <template>\n      {{ \\`\\${VAR}VAR2\\${VAR3}\\` }}\n    </template>\n    `)\n  // VAR2 should not be matched\n  expect(content).toMatch(\n    `return { get VAR() { return VAR }, get VAR3() { return VAR3 } }`,\n  )\n  assertCode(content)\n})\n\n// edge case: last tag in template\ntest('last tag', () => {\n  const { content } = compile(`\n    <script setup lang=\"ts\">\n    import { FooBaz, Last } from './x'\n    </script>\n    <template>\n      <FooBaz></FooBaz>\n      <Last/>\n    </template>\n    `)\n  expect(content).toMatch(\n    `return { get FooBaz() { return FooBaz }, get Last() { return Last } }`,\n  )\n  assertCode(content)\n})\n\ntest('TS annotations', () => {\n  const { content } = compile(`\n    <script setup lang=\"ts\">\n    import { Foo, Bar, Baz, Qux, Fred } from './x'\n    const a = 1\n    function b() {}\n    </script>\n    <template>\n      {{ a as Foo }}\n      {{ b<Bar>() }}\n      {{ Baz }}\n      <Comp v-slot=\"{ data }: Qux\">{{ data }}</Comp>\n      <div v-for=\"{ z = x as Qux } in list as Fred\"/>\n    </template>\n    `)\n  expect(content).toMatch(`return { a, b, get Baz() { return Baz } }`)\n  assertCode(content)\n})\n\n// vuejs/vue#12591\ntest('v-on inline statement', () => {\n  // should not error\n  compile(`\n  <script setup lang=\"ts\">\n    import { foo } from './foo'\n  </script>\n  <template>\n    <div @click=\"$emit('update:a');\"></div>\n  </template>\n  `)\n})\n\ntest('template ref', () => {\n  const { content } = compile(`\n    <script setup lang=\"ts\">\n      import { foo, bar, Baz } from './foo'\n    </script>\n    <template>\n      <div ref=\"foo\"></div>\n      <div ref=\"\"></div>\n      <Baz ref=\"bar\" />\n    </template>\n    `)\n  expect(content).toMatch(\n    'return { get foo() { return foo }, get bar() { return bar }, get Baz() { return Baz } }',\n  )\n  assertCode(content)\n})\n\n// https://github.com/nuxt/nuxt/issues/22416\ntest('property access', () => {\n  const { content } = compile(`\n    <script setup lang=\"ts\">\n      import { Foo, Bar, Baz } from './foo'\n    </script>\n    <template>\n      <div>{{ Foo.Bar.Baz }}</div>\n    </template>\n    `)\n  expect(content).toMatch('return { get Foo() { return Foo } }')\n  assertCode(content)\n})\n\ntest('spread operator', () => {\n  const { content } = compile(`\n    <script setup lang=\"ts\">\n      import { Foo, Bar, Baz } from './foo'\n    </script>\n    <template>\n      <div v-bind=\"{ ...Foo.Bar.Baz }\"></div>\n    </template>\n    `)\n  expect(content).toMatch('return { get Foo() { return Foo } }')\n  assertCode(content)\n})\n\ntest('property access (whitespace)', () => {\n  const { content } = compile(`\n    <script setup lang=\"ts\">\n      import { Foo, Bar, Baz } from './foo'\n    </script>\n    <template>\n      <div>{{ Foo . Bar . Baz }}</div>\n    </template>\n    `)\n  expect(content).toMatch('return { get Foo() { return Foo } }')\n  assertCode(content)\n})\n\n// #9974\ntest('namespace / dot component usage', () => {\n  const { content } = compile(`\n    <script setup lang=\"ts\">\n      import * as Foo from './foo'\n    </script>\n    <template>\n      <Foo.Bar />\n    </template>\n    `)\n  expect(content).toMatch('return { get Foo() { return Foo } }')\n  assertCode(content)\n})\n\ntest('check when has explicit parse options', () => {\n  const { content } = compile(\n    `\n    <script setup lang=\"ts\">\n      import { x } from './x'\n    </script>\n    <template>\n      {{ x }}\n    </template>\n    `,\n    undefined,\n    { templateParseOptions: {} },\n  )\n  expect(content).toMatch('return { get x() { return x } }')\n})\n\n// #11745\ntest('shorthand binding w/ kebab-case', () => {\n  const { content } = compile(\n    `\n    <script setup lang=\"ts\">\n      import { fooBar } from \"./foo.ts\"\n    </script>\n    <template>\n      <div :foo-bar></div>\n    </template>\n    `,\n  )\n  expect(content).toMatch('return { get fooBar() { return fooBar }')\n})\n"
  },
  {
    "path": "packages/compiler-sfc/__tests__/compileScript/resolveType.spec.ts",
    "content": "import { normalize } from 'node:path'\nimport type { Identifier } from '@babel/types'\nimport { type SFCScriptCompileOptions, parse } from '../../src'\nimport { ScriptCompileContext } from '../../src/script/context'\nimport {\n  inferRuntimeType,\n  invalidateTypeCache,\n  recordImports,\n  registerTS,\n  resolveTypeElements,\n} from '../../src/script/resolveType'\nimport { UNKNOWN_TYPE } from '../../src/script/utils'\nimport ts from 'typescript'\n\nregisterTS(() => ts)\n\ndescribe('resolveType', () => {\n  test('type literal', () => {\n    const { props, calls } = resolve(`defineProps<{\n      foo: number // property\n      bar(): void // method\n      'baz': string // string literal key\n      [\\`qux\\`]: boolean // template literal key\n      123: symbol // numeric literal key\n      (e: 'foo'): void // call signature\n      (e: 'bar'): void\n    }>()`)\n    expect(props).toStrictEqual({\n      foo: ['Number'],\n      bar: ['Function'],\n      baz: ['String'],\n      qux: ['Boolean'],\n      123: ['Symbol'],\n    })\n    expect(calls?.length).toBe(2)\n  })\n\n  test('reference type', () => {\n    expect(\n      resolve(`\n    type Aliased = { foo: number }\n    defineProps<Aliased>()\n    `).props,\n    ).toStrictEqual({\n      foo: ['Number'],\n    })\n  })\n\n  test('reference exported type', () => {\n    expect(\n      resolve(`\n    export type Aliased = { foo: number }\n    defineProps<Aliased>()\n    `).props,\n    ).toStrictEqual({\n      foo: ['Number'],\n    })\n  })\n\n  test('reference interface', () => {\n    expect(\n      resolve(`\n    interface Aliased { foo: number }\n    defineProps<Aliased>()\n    `).props,\n    ).toStrictEqual({\n      foo: ['Number'],\n    })\n  })\n\n  test('reference exported interface', () => {\n    expect(\n      resolve(`\n    export interface Aliased { foo: number }\n    defineProps<Aliased>()\n    `).props,\n    ).toStrictEqual({\n      foo: ['Number'],\n    })\n  })\n\n  test('reference interface extends', () => {\n    expect(\n      resolve(`\n    export interface A { a(): void }\n    export interface B extends A { b: boolean }\n    interface C { c: string }\n    interface Aliased extends B, C { foo: number }\n    defineProps<Aliased>()\n    `).props,\n    ).toStrictEqual({\n      a: ['Function'],\n      b: ['Boolean'],\n      c: ['String'],\n      foo: ['Number'],\n    })\n  })\n\n  test('reference class', () => {\n    expect(\n      resolve(`\n    class Foo {}\n    defineProps<{ foo: Foo }>()\n    `).props,\n    ).toStrictEqual({\n      foo: ['Object'],\n    })\n  })\n\n  test('function type', () => {\n    expect(\n      resolve(`\n    defineProps<(e: 'foo') => void>()\n    `).calls?.length,\n    ).toBe(1)\n  })\n\n  test('reference function type', () => {\n    expect(\n      resolve(`\n    type Fn = (e: 'foo') => void\n    defineProps<Fn>()\n    `).calls?.length,\n    ).toBe(1)\n  })\n\n  test('intersection type', () => {\n    expect(\n      resolve(`\n    type Foo = { foo: number }\n    type Bar = { bar: string }\n    type Baz = { bar: string | boolean }\n    defineProps<{ self: any } & Foo & Bar & Baz>()\n    `).props,\n    ).toStrictEqual({\n      self: [UNKNOWN_TYPE],\n      foo: ['Number'],\n      // both Bar & Baz has 'bar', but Baz['bar] is wider so it should be\n      // preferred\n      bar: ['String', 'Boolean'],\n    })\n  })\n\n  test('intersection type with ignore', () => {\n    expect(\n      resolve(`\n    type Foo = { foo: number }\n    type Bar = { bar: string }\n    defineProps<Foo & /* @vue-ignore */ Bar>()\n    `).props,\n    ).toStrictEqual({\n      foo: ['Number'],\n    })\n  })\n\n  test('TSPropertySignature with ignore', () => {\n    expect(\n      resolve(`\n      type Foo = string\n      defineProps<{ foo: /* @vue-ignore */ Foo }>()\n    `).props,\n    ).toStrictEqual({\n      foo: ['Unknown'],\n    })\n  })\n\n  // #7553\n  test('union type', () => {\n    expect(\n      resolve(`\n    interface CommonProps {\n      size?: 'xl' | 'l' | 'm' | 's' | 'xs'\n    }\n\n    type ConditionalProps =\n      | {\n          color: 'normal' | 'primary' | 'secondary'\n          appearance: 'normal' | 'outline' | 'text'\n        }\n      | {\n          color: number\n          appearance: 'outline'\n          note: string\n        }\n\n    defineProps<CommonProps & ConditionalProps>()\n    `).props,\n    ).toStrictEqual({\n      size: ['String'],\n      color: ['String', 'Number'],\n      appearance: ['String'],\n      note: ['String'],\n    })\n  })\n\n  test('template string type', () => {\n    expect(\n      resolve(`\n    type T = 'foo' | 'bar'\n    type S = 'x' | 'y'\n    defineProps<{\n      [K in \\`_\\${T}_\\${S}_\\`]: string\n    }>()\n    `).props,\n    ).toStrictEqual({\n      _foo_x_: ['String'],\n      _foo_y_: ['String'],\n      _bar_x_: ['String'],\n      _bar_y_: ['String'],\n    })\n  })\n\n  test('mapped types w/ string manipulation', () => {\n    expect(\n      resolve(`\n    type T = 'foo' | 'bar'\n    defineProps<{ [K in T]: string | number } & {\n      [K in 'optional']?: boolean\n    } & {\n      [K in Capitalize<T>]: string\n    } & {\n      [K in Uppercase<Extract<T, 'foo'>>]: string\n    } & {\n      [K in \\`x\\${T}\\`]: string\n    }>()\n    `).props,\n    ).toStrictEqual({\n      foo: ['String', 'Number'],\n      bar: ['String', 'Number'],\n      Foo: ['String'],\n      Bar: ['String'],\n      FOO: ['String'],\n      xfoo: ['String'],\n      xbar: ['String'],\n      optional: ['Boolean'],\n    })\n  })\n\n  test('utility type: Partial', () => {\n    expect(\n      resolve(`\n    type T = { foo: number, bar: string }\n    defineProps<Partial<T>>()\n    `).raw.props,\n    ).toMatchObject({\n      foo: {\n        optional: true,\n      },\n      bar: {\n        optional: true,\n      },\n    })\n  })\n\n  test('utility type: Required', () => {\n    expect(\n      resolve(`\n    type T = { foo?: number, bar?: string }\n    defineProps<Required<T>>()\n    `).raw.props,\n    ).toMatchObject({\n      foo: {\n        optional: false,\n      },\n      bar: {\n        optional: false,\n      },\n    })\n  })\n\n  test('utility type: Pick', () => {\n    expect(\n      resolve(`\n    type T = { foo: number, bar: string, baz: boolean }\n    type K = 'foo' | 'bar'\n    defineProps<Pick<T, K>>()\n    `).props,\n    ).toStrictEqual({\n      foo: ['Number'],\n      bar: ['String'],\n    })\n  })\n\n  test('utility type: Omit', () => {\n    expect(\n      resolve(`\n    type T = { foo: number, bar: string, baz: boolean }\n    type K = 'foo' | 'bar'\n    defineProps<Omit<T, K>>()\n    `).props,\n    ).toStrictEqual({\n      baz: ['Boolean'],\n    })\n  })\n\n  test('utility type: mapped type with Omit and Pick', () => {\n    expect(\n      resolve(`\n      type Optional<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>\n      interface Test {\n        foo: string;\n        bar?: string;\n      }\n      type OptionalTest = Optional<Test, 'foo'>\n      defineProps<OptionalTest>()\n    `).props,\n    ).toStrictEqual({\n      foo: ['String'],\n      bar: ['String'],\n    })\n  })\n\n  test('utility type: ReadonlyArray', () => {\n    expect(\n      resolve(`\n    defineProps<{ foo: ReadonlyArray<string> }>()\n    `).props,\n    ).toStrictEqual({\n      foo: ['Array'],\n    })\n  })\n\n  test('utility type: ReadonlyMap & Readonly Set', () => {\n    expect(\n      resolve(`\n    defineProps<{ foo: ReadonlyMap<string, unknown>, bar: ReadonlySet<string> }>()\n    `).props,\n    ).toStrictEqual({\n      foo: ['Map'],\n      bar: ['Set'],\n    })\n  })\n\n  test('indexed access type (literal)', () => {\n    expect(\n      resolve(`\n    type T = { bar: number }\n    type S = { nested: { foo: T['bar'] }}\n    defineProps<S['nested']>()\n    `).props,\n    ).toStrictEqual({\n      foo: ['Number'],\n    })\n  })\n\n  test('indexed access type (advanced)', () => {\n    expect(\n      resolve(`\n    type K = 'foo' | 'bar'\n    type T = { foo: string, bar: number }\n    type S = { foo: { foo: T[string] }, bar: { bar: string } }\n    defineProps<S[K]>()\n    `).props,\n    ).toStrictEqual({\n      foo: ['String', 'Number'],\n      bar: ['String'],\n    })\n  })\n\n  test('indexed access type (number)', () => {\n    expect(\n      resolve(`\n    type A = (string | number)[]\n    type AA = Array<string>\n    type T = [1, 'foo']\n    type TT = [foo: 1, bar: 'foo']\n    defineProps<{ foo: A[number], bar: AA[number], tuple: T[number], namedTuple: TT[number] }>()\n    `).props,\n    ).toStrictEqual({\n      foo: ['String', 'Number'],\n      bar: ['String'],\n      tuple: ['Number', 'String'],\n      namedTuple: ['Number', 'String'],\n    })\n  })\n\n  test('namespace', () => {\n    expect(\n      resolve(`\n      type X = string\n      namespace Foo {\n        type X = number\n        export namespace Bar {\n          export type A = {\n            foo: X\n          }\n        }\n      }\n      defineProps<Foo.Bar.A>()\n    `).props,\n    ).toStrictEqual({\n      foo: ['Number'],\n    })\n  })\n\n  test('interface merging', () => {\n    expect(\n      resolve(`\n      interface Foo {\n        a: string\n      }\n      interface Foo {\n        b: number\n      }\n      defineProps<{\n        foo: Foo['a'],\n        bar: Foo['b']\n      }>()\n    `).props,\n    ).toStrictEqual({\n      foo: ['String'],\n      bar: ['Number'],\n    })\n  })\n\n  test('namespace merging', () => {\n    expect(\n      resolve(`\n      namespace Foo {\n        export type A = string\n      }\n      namespace Foo {\n        export type B = number\n      }\n      defineProps<{\n        foo: Foo.A,\n        bar: Foo.B\n      }>()\n    `).props,\n    ).toStrictEqual({\n      foo: ['String'],\n      bar: ['Number'],\n    })\n  })\n\n  test('namespace merging with other types', () => {\n    expect(\n      resolve(`\n      namespace Foo {\n        export type A = string\n      }\n      interface Foo {\n        b: number\n      }\n      defineProps<{\n        foo: Foo.A,\n        bar: Foo['b']\n      }>()\n    `).props,\n    ).toStrictEqual({\n      foo: ['String'],\n      bar: ['Number'],\n    })\n  })\n\n  test('enum merging', () => {\n    expect(\n      resolve(`\n      enum Foo {\n        A = 1\n      }\n      enum Foo {\n        B = 'hi'\n      }\n      defineProps<{\n        foo: Foo\n      }>()\n    `).props,\n    ).toStrictEqual({\n      foo: ['Number', 'String'],\n    })\n  })\n\n  test('typeof', () => {\n    expect(\n      resolve(`\n      declare const a: string\n      defineProps<{ foo: typeof a }>()\n    `).props,\n    ).toStrictEqual({\n      foo: ['String'],\n    })\n  })\n\n  test('readonly', () => {\n    expect(\n      resolve(`\n    defineProps<{ foo: readonly unknown[] }>()\n    `).props,\n    ).toStrictEqual({\n      foo: ['Array'],\n    })\n  })\n\n  test('keyof', () => {\n    const files = {\n      '/foo.ts': `export type IMP = { ${1}: 1 };`,\n    }\n\n    const { props } = resolve(\n      `\n      import { IMP } from './foo'\n      interface Foo { foo: 1, ${1}: 1 }\n      type Bar = { bar: 1 }\n      declare const obj: Bar\n      declare const set: Set<any>\n      declare const arr: Array<any>\n\n      defineProps<{\n        imp: keyof IMP,\n        foo: keyof Foo,\n        bar: keyof Bar,\n        obj: keyof typeof obj,\n        set: keyof typeof set,\n        arr: keyof typeof arr\n      }>()\n      `,\n      files,\n    )\n\n    expect(props).toStrictEqual({\n      imp: ['Number'],\n      foo: ['String', 'Number'],\n      bar: ['String'],\n      obj: ['String'],\n      set: ['String'],\n      arr: ['String', 'Number'],\n    })\n  })\n\n  test('keyof: index signature', () => {\n    const { props } = resolve(\n      `\n      declare const num: number;\n      interface Foo {\n        [key: symbol]: 1\n        [key: string]: 1\n        [key: typeof num]: 1,\n      }\n\n      type Test<T> = T\n      type Bar = {\n        [key: string]: 1\n        [key: Test<number>]: 1\n      }\n\n      defineProps<{\n        foo: keyof Foo \n        bar: keyof Bar\n      }>()\n      `,\n    )\n\n    expect(props).toStrictEqual({\n      foo: ['Symbol', 'String', 'Number'],\n      bar: ['String', 'Number'],\n    })\n  })\n\n  // #11129\n  test('keyof: intersection type', () => {\n    const { props } = resolve(`\n    type A = { name: string }\n    type B = A & { [key: number]: string }\n    defineProps<{\n      foo: keyof B\n    }>()`)\n    expect(props).toStrictEqual({\n      foo: ['String', 'Number'],\n    })\n  })\n\n  test('keyof: union type', () => {\n    const { props } = resolve(`\n    type A = { name: string }\n    type B = A | { [key: number]: string }\n    defineProps<{\n      foo: keyof B\n    }>()`)\n    expect(props).toStrictEqual({\n      foo: ['String', 'Number'],\n    })\n  })\n\n  test('keyof: utility type', () => {\n    const { props } = resolve(\n      `\n      type Foo = Record<symbol | string, any>\n      type Bar = { [key: string]: any }\n      type AnyRecord = Record<keyof any, any>\n      type Baz = { a: 1, ${1}: 2, b: 3}\n\n      defineProps<{\n        record: keyof Foo,\n        anyRecord: keyof AnyRecord \n        partial: keyof Partial<Bar>,\n        required: keyof Required<Bar>,\n        readonly: keyof Readonly<Bar>,\n        pick: keyof Pick<Baz, 'a' | 1>\n        extract: keyof Extract<keyof Baz, 'a' | 1>\n      }>()\n      `,\n    )\n\n    expect(props).toStrictEqual({\n      record: ['Symbol', 'String'],\n      anyRecord: ['String', 'Number', 'Symbol'],\n      partial: ['String'],\n      required: ['String'],\n      readonly: ['String'],\n      pick: ['String', 'Number'],\n      extract: ['String', 'Number'],\n    })\n  })\n\n  test('keyof: fallback to Unknown', () => {\n    const { props } = resolve(\n      `\n      interface Barr {}\n      interface Bar extends Barr {}\n      type Foo = keyof Bar\n      defineProps<{ foo: Foo }>()\n      `,\n    )\n\n    expect(props).toStrictEqual({\n      foo: [UNKNOWN_TYPE],\n    })\n  })\n\n  test('keyof: nested object with number', () => {\n    const { props } = resolve(\n      `\n      interface Type {\n        deep: {\n          1: any\n        }\n      }\n\n      defineProps<{\n        route: keyof Type['deep']\n      }>()`,\n    )\n\n    expect(props).toStrictEqual({\n      route: ['Number'],\n    })\n  })\n\n  test('keyof: nested object with string', () => {\n    const { props } = resolve(\n      `\n      interface Type {\n        deep: {\n          foo: any\n        }\n      }\n\n      defineProps<{\n        route: keyof Type['deep']\n      }>()`,\n    )\n\n    expect(props).toStrictEqual({\n      route: ['String'],\n    })\n  })\n\n  test('keyof: nested object with intermediate', () => {\n    const { props } = resolve(\n      `\n      interface Type {\n        deep: {\n          foo: any\n        }\n      }\n\n      type Foo = Type['deep']\n\n      defineProps<{\n        route: keyof Foo\n      }>()`,\n    )\n\n    expect(props).toStrictEqual({\n      route: ['String'],\n    })\n  })\n\n  test('ExtractPropTypes (element-plus)', () => {\n    const { props, raw } = resolve(\n      `\n      import { ExtractPropTypes } from 'vue'\n      declare const props: {\n        foo: StringConstructor,\n        bar: {\n          type: import('foo').EpPropFinalized<BooleanConstructor>,\n          required: true\n        }\n      }\n      type Props = ExtractPropTypes<typeof props>\n      defineProps<Props>()\n    `,\n    )\n    expect(props).toStrictEqual({\n      foo: ['String'],\n      bar: ['Boolean'],\n    })\n    expect(raw.props.bar.optional).toBe(false)\n  })\n\n  test('ExtractPropTypes (antd)', () => {\n    const { props } = resolve(\n      `\n      declare const props: () => {\n        foo: StringConstructor,\n        bar: { type: PropType<boolean> }\n      }\n      type Props = Partial<import('vue').ExtractPropTypes<ReturnType<typeof props>>>\n      defineProps<Props>()\n    `,\n    )\n    expect(props).toStrictEqual({\n      foo: ['String'],\n      bar: ['Boolean'],\n    })\n  })\n\n  // #11266\n  test('correctly parse type annotation for declared function', () => {\n    const { props } = resolve(`\n    import { ExtractPropTypes } from 'vue'\n    interface UploadFile<T = any> {\n      xhr?: T\n    }\n    declare function uploadProps<T = any>(): {\n      fileList: {\n        type: PropType<UploadFile<T>[]>\n        default: UploadFile<T>[]\n      }\n    }\n    type UploadProps = ExtractPropTypes<ReturnType<typeof uploadProps>>\n    defineProps<UploadProps>()`)\n    expect(props).toStrictEqual({\n      fileList: ['Array'],\n    })\n  })\n\n  test('TSMappedType with indexed access', () => {\n    const { props } = resolve(\n      `\n      type Prettify<T> = { [K in keyof T]: T[K] } & {}\n      type Side = 'top' | 'right' | 'bottom' | 'left'\n      type AlignedPlacement = \\`\\${Side}-\\${Alignment}\\`\n      type Alignment = 'start' | 'end'\n      type Placement = Prettify<Side | AlignedPlacement>\n      defineProps<{placement?: Placement}>()\n    `,\n    )\n    expect(props).toStrictEqual({\n      placement: ['String', 'Object'],\n    })\n  })\n\n  describe('type alias declaration', () => {\n    // #13240\n    test('function type', () => {\n      expect(\n        resolve(`\n      type FunFoo<O> = (item: O) => boolean;\n      type FunBar = FunFoo<number>;\n      defineProps<{\n        foo?: FunFoo<number>;\n        bar?: FunBar;\n      }>()\n      `).props,\n      ).toStrictEqual({\n        foo: ['Function'],\n        bar: ['Function'],\n      })\n    })\n\n    test('with intersection type', () => {\n      expect(\n        resolve(`\n      type Brand<T> = T & {};\n      defineProps<{\n        foo: Brand<string>;\n      }>()\n      `).props,\n      ).toStrictEqual({\n        foo: ['String', 'Object'],\n      })\n    })\n\n    test('with union type', () => {\n      expect(\n        resolve(`\n        type Wrapped<T> = T | symbol | number\n        defineProps<{foo?: Wrapped<boolean>}>()\n      `).props,\n      ).toStrictEqual({\n        foo: ['Boolean', 'Symbol', 'Number'],\n      })\n    })\n  })\n\n  describe('generics', () => {\n    test('generic with type literal', () => {\n      expect(\n        resolve(`\n        type Props<T> = T\n        defineProps<Props<{ foo: string }>>()\n      `).props,\n      ).toStrictEqual({\n        foo: ['String'],\n      })\n    })\n\n    test('generic used in intersection', () => {\n      expect(\n        resolve(`\n        type Foo = { foo: string; }\n        type Bar = { bar: number; }\n        type Props<T,U> = T & U & { baz: boolean }\n        defineProps<Props<Foo, Bar>>()\n      `).props,\n      ).toStrictEqual({\n        foo: ['String'],\n        bar: ['Number'],\n        baz: ['Boolean'],\n      })\n    })\n\n    test('generic type /w generic type alias', () => {\n      expect(\n        resolve(`\n        type Aliased<T> = Readonly<Partial<T>>\n        type Props<T> = Aliased<T>\n        type Foo = { foo: string; }\n        defineProps<Props<Foo>>()\n      `).props,\n      ).toStrictEqual({\n        foo: ['String'],\n      })\n    })\n\n    test('generic type /w aliased type literal', () => {\n      expect(\n        resolve(`\n        type Aliased<T> = { foo: T }\n        defineProps<Aliased<string>>()\n      `).props,\n      ).toStrictEqual({\n        foo: ['String'],\n      })\n    })\n\n    test('generic type /w interface', () => {\n      expect(\n        resolve(`\n        interface Props<T> {\n          foo: T\n        }\n        type Foo = string\n        defineProps<Props<Foo>>()\n      `).props,\n      ).toStrictEqual({\n        foo: ['String'],\n      })\n    })\n\n    test('generic from external-file', () => {\n      const files = {\n        '/foo.ts': 'export type P<T> = { foo: T }',\n      }\n      const { props } = resolve(\n        `\n        import { P } from './foo'\n        defineProps<P<string>>()\n      `,\n        files,\n      )\n      expect(props).toStrictEqual({\n        foo: ['String'],\n      })\n    })\n  })\n\n  describe('external type imports', () => {\n    test('relative ts', () => {\n      const files = {\n        '/foo.ts': 'export type P = { foo: number }',\n        '/bar.d.ts':\n          'type X = { bar: string }; export { X as Y };' +\n          // verify that we can parse syntax that is only valid in d.ts\n          'export const baz: boolean',\n      }\n      const { props, deps } = resolve(\n        `\n        import { P } from './foo'\n        import { Y as PP } from './bar'\n        defineProps<P & PP>()\n      `,\n        files,\n      )\n      expect(props).toStrictEqual({\n        foo: ['Number'],\n        bar: ['String'],\n      })\n      expect(deps && [...deps]).toStrictEqual(Object.keys(files))\n    })\n\n    // #10635\n    test('relative tsx', () => {\n      const files = {\n        '/foo.tsx': 'export type P = { foo: number }',\n        '/bar/index.tsx': 'export type PP = { bar: string }',\n      }\n      const { props, deps } = resolve(\n        `\n        import { P } from './foo'\n        import { PP } from './bar'\n        defineProps<P & PP>()\n        `,\n        files,\n      )\n      expect(props).toStrictEqual({\n        foo: ['Number'],\n        bar: ['String'],\n      })\n      expect(deps && [...deps]).toStrictEqual(Object.keys(files))\n    })\n\n    test.runIf(process.platform === 'win32')('relative ts on Windows', () => {\n      const files = {\n        'C:\\\\Test\\\\FolderA\\\\foo.ts': 'export type P = { foo: number }',\n        'C:\\\\Test\\\\FolderA\\\\bar.d.ts':\n          'type X = { bar: string }; export { X as Y };' +\n          // verify that we can parse syntax that is only valid in d.ts\n          'export const baz: boolean',\n        'C:\\\\Test\\\\FolderB\\\\buz.ts': 'export type Z = { buz: string }',\n      }\n      const { props, deps } = resolve(\n        `\n      import { P } from './foo'\n      import { Y as PP } from './bar'\n      import { Z as PPP } from '../FolderB/buz'\n      defineProps<P & PP & PPP>()\n    `,\n        files,\n        {},\n        'C:\\\\Test\\\\FolderA\\\\Test.vue',\n      )\n      expect(props).toStrictEqual({\n        foo: ['Number'],\n        bar: ['String'],\n        buz: ['String'],\n      })\n      expect(deps && [...deps].map(normalize)).toStrictEqual(\n        Object.keys(files).map(normalize),\n      )\n    })\n\n    // #8244\n    test('utility type in external file', () => {\n      const files = {\n        '/foo.ts': 'type A = { n?: number }; export type B = Required<A>',\n      }\n      const { props } = resolve(\n        `\n        import { B } from './foo'\n        defineProps<B>()\n      `,\n        files,\n      )\n      expect(props).toStrictEqual({\n        n: ['Number'],\n      })\n    })\n\n    test('relative vue', () => {\n      const files = {\n        '/foo.vue':\n          '<script lang=\"ts\">export type P = { foo: number }</script>',\n        '/bar.vue':\n          '<script setup lang=\"tsx\">export type P = { bar: string }</script>',\n      }\n      const { props, deps } = resolve(\n        `\n        import { P } from './foo.vue'\n        import { P as PP } from './bar.vue'\n        defineProps<P & PP>()\n      `,\n        files,\n      )\n      expect(props).toStrictEqual({\n        foo: ['Number'],\n        bar: ['String'],\n      })\n      expect(deps && [...deps]).toStrictEqual(Object.keys(files))\n    })\n\n    test('relative (chained)', () => {\n      const files = {\n        '/foo.ts': `import type { P as PP } from './nested/bar.vue'\n          export type P = { foo: number } & PP`,\n        '/nested/bar.vue':\n          '<script setup lang=\"ts\">export type P = { bar: string }</script>',\n      }\n      const { props, deps } = resolve(\n        `\n        import { P } from './foo'\n        defineProps<P>()\n      `,\n        files,\n      )\n      expect(props).toStrictEqual({\n        foo: ['Number'],\n        bar: ['String'],\n      })\n      expect(deps && [...deps]).toStrictEqual(Object.keys(files))\n    })\n\n    test('relative (chained, re-export)', () => {\n      const files = {\n        '/foo.ts': `export { P as PP } from './bar'`,\n        '/bar.ts': 'export type P = { bar: string }',\n      }\n      const { props, deps } = resolve(\n        `\n        import { PP as P } from './foo'\n        defineProps<P>()\n      `,\n        files,\n      )\n      expect(props).toStrictEqual({\n        bar: ['String'],\n      })\n      expect(deps && [...deps]).toStrictEqual(Object.keys(files))\n    })\n\n    test('relative (chained, export *)', () => {\n      const files = {\n        '/foo.ts': `export * from './bar'`,\n        '/bar.ts': 'export type P = { bar: string }',\n      }\n      const { props, deps } = resolve(\n        `\n        import { P } from './foo'\n        defineProps<P>()\n      `,\n        files,\n      )\n      expect(props).toStrictEqual({\n        bar: ['String'],\n      })\n      expect(deps && [...deps]).toStrictEqual(Object.keys(files))\n    })\n\n    test('relative (default export)', () => {\n      const files = {\n        '/foo.ts': `export default interface P { foo: string }`,\n        '/bar.ts': `type X = { bar: string }; export default X`,\n      }\n      const { props, deps } = resolve(\n        `\n        import P from './foo'\n        import X from './bar'\n        defineProps<P & X>()\n      `,\n        files,\n      )\n      expect(props).toStrictEqual({\n        foo: ['String'],\n        bar: ['String'],\n      })\n      expect(deps && [...deps]).toStrictEqual(Object.keys(files))\n    })\n\n    test('relative (default re-export)', () => {\n      const files = {\n        '/bar.ts': `export { default } from './foo'`,\n        '/foo.ts': `export default interface P { foo: string }; export interface PP { bar: number }`,\n        '/baz.ts': `export { PP as default } from './foo'`,\n      }\n      const { props, deps } = resolve(\n        `\n        import P from './bar'\n        import PP from './baz'\n        defineProps<P & PP>()\n      `,\n        files,\n      )\n      expect(props).toStrictEqual({\n        foo: ['String'],\n        bar: ['Number'],\n      })\n      expect(deps && [...deps]).toStrictEqual(Object.keys(files))\n    })\n\n    test('relative (re-export /w same source type name)', () => {\n      const files = {\n        '/foo.ts': `export default interface P { foo: string }`,\n        '/bar.ts': `export default interface PP { bar: number }`,\n        '/baz.ts': `export { default as X } from './foo'; export { default as XX } from './bar'; `,\n      }\n      const { props, deps } = resolve(\n        `import { X, XX } from './baz'\n        defineProps<X & XX>()\n      `,\n        files,\n      )\n      expect(props).toStrictEqual({\n        foo: ['String'],\n        bar: ['Number'],\n      })\n      expect(deps && [...deps]).toStrictEqual(['/baz.ts', '/foo.ts', '/bar.ts'])\n    })\n\n    test('relative (dynamic import)', () => {\n      const files = {\n        '/foo.ts': `export type P = { foo: string, bar: import('./bar').N }`,\n        '/bar.ts': 'export type N = number',\n      }\n      const { props, deps } = resolve(\n        `\n        defineProps<import('./foo').P>()\n      `,\n        files,\n      )\n      expect(props).toStrictEqual({\n        foo: ['String'],\n        bar: ['Number'],\n      })\n      expect(deps && [...deps]).toStrictEqual(Object.keys(files))\n    })\n\n    test('relative import with indexed access type', () => {\n      const files = {\n        '/foo.ts': `\n          type Booleanish = boolean | 'true' | 'false';\n          export interface InputHTMLAttributes {\n            required?: Booleanish | undefined;\n          }\n        `,\n      }\n      const { props, deps } = resolve(\n        `\n        import { InputHTMLAttributes } from './foo.ts'\n        type ImportedType = InputHTMLAttributes['required']\n        defineProps<{\n          required: ImportedType,\n        }>()\n      `,\n        files,\n      )\n      expect(props).toStrictEqual({\n        required: ['Boolean', 'String', 'Unknown'],\n      })\n      expect(deps && [...deps]).toStrictEqual(Object.keys(files))\n    })\n\n    test('relative import with indexed access type with unresolvable extends', () => {\n      const files = {\n        '/foo.ts': `\n          type EventHandlers<E> = {\n            [K in keyof E]?: E[K] extends (...args: any) => any \n            ? E[K] \n            : (payload: E[K]) => void;\n          };\n          export interface Events {\n            onCopy: ClipboardEvent;\n          }\n          type Booleanish = boolean | 'true' | 'false';\n          export interface InputHTMLAttributes extends EventHandlers<Events>{\n            required?: Booleanish | undefined;\n          }\n        `,\n      }\n      const { props, deps } = resolve(\n        `\n        import { InputHTMLAttributes } from './foo.ts'\n        type ImportedType = InputHTMLAttributes['required']\n        defineProps<{\n          required: ImportedType,\n        }>()\n      `,\n        files,\n      )\n      expect(props).toStrictEqual({\n        required: ['Boolean', 'String', 'Unknown'],\n      })\n      expect(deps && [...deps]).toStrictEqual(Object.keys(files))\n    })\n\n    // #8339\n    test('relative, .js import', () => {\n      const files = {\n        '/foo.d.ts':\n          'import { PP } from \"./bar.js\"; export type P = { foo: PP }',\n        '/bar.d.ts': 'export type PP = \"foo\" | \"bar\"',\n      }\n      const { props, deps } = resolve(\n        `\n        import { P } from './foo'\n        defineProps<P>()\n      `,\n        files,\n      )\n      expect(props).toStrictEqual({\n        foo: ['String'],\n      })\n      expect(deps && [...deps]).toStrictEqual(Object.keys(files))\n    })\n\n    test('ts module resolve', () => {\n      const files = {\n        '/node_modules/foo/package.json': JSON.stringify({\n          types: 'index.d.ts',\n        }),\n        '/node_modules/foo/index.d.ts': 'export type P = { foo: number }',\n        '/tsconfig.json': JSON.stringify({\n          compilerOptions: {\n            paths: {\n              bar: ['./pp.ts'],\n            },\n          },\n        }),\n        '/pp.ts': 'export type PP = { bar: string }',\n      }\n\n      const { props, deps } = resolve(\n        `\n        import { P } from 'foo'\n        import { PP } from 'bar'\n        defineProps<P & PP>()\n        `,\n        files,\n      )\n\n      expect(props).toStrictEqual({\n        foo: ['Number'],\n        bar: ['String'],\n      })\n      expect(deps && [...deps]).toStrictEqual([\n        '/node_modules/foo/index.d.ts',\n        '/pp.ts',\n      ])\n    })\n\n    test('ts module resolve w/ project reference & extends', () => {\n      const files = {\n        '/tsconfig.json': JSON.stringify({\n          references: [\n            {\n              path: './tsconfig.app.json',\n            },\n          ],\n        }),\n        '/tsconfig.app.json': JSON.stringify({\n          include: ['**/*.ts', '**/*.vue'],\n          extends: './tsconfig.web.json',\n        }),\n        '/tsconfig.web.json': JSON.stringify({\n          compilerOptions: {\n            composite: true,\n            paths: {\n              bar: ['./user.ts'],\n            },\n          },\n        }),\n        '/user.ts': 'export type User = { bar: string }',\n      }\n\n      const { props, deps } = resolve(\n        `\n        import { User } from 'bar'\n        defineProps<User>()\n        `,\n        files,\n      )\n\n      expect(props).toStrictEqual({\n        bar: ['String'],\n      })\n      expect(deps && [...deps]).toStrictEqual(['/user.ts'])\n    })\n\n    // #13484\n    test('ts module resolve w/ project reference & extends & ${configDir}', () => {\n      const files = {\n        '/tsconfig.json': JSON.stringify({\n          files: [],\n          references: [{ path: './tsconfig.app.json' }],\n        }),\n        '/tsconfig.app.json': JSON.stringify({\n          extends: ['./tsconfigs/base.json'],\n        }),\n        '/tsconfigs/base.json': JSON.stringify({\n          compilerOptions: {\n            paths: {\n              '@/*': ['${configDir}/src/*'],\n            },\n          },\n          include: ['${configDir}/src/**/*.ts', '${configDir}/src/**/*.vue'],\n        }),\n        '/src/types.ts':\n          'export type BaseProps = { foo?: string, bar?: string }',\n      }\n\n      const { props, deps } = resolve(\n        `\n        import { BaseProps } from '@/types.ts';\n        defineProps<BaseProps>()\n        `,\n        files,\n        {},\n        '/src/components/Foo.vue',\n      )\n\n      expect(props).toStrictEqual({\n        foo: ['String'],\n        bar: ['String'],\n      })\n      expect(deps && [...deps]).toStrictEqual(['/src/types.ts'])\n    })\n\n    test('ts module resolve w/ project reference folder', () => {\n      const files = {\n        '/tsconfig.json': JSON.stringify({\n          references: [\n            {\n              path: './web',\n            },\n            {\n              path: './empty',\n            },\n            {\n              path: './noexists-should-ignore',\n            },\n          ],\n        }),\n        '/web/tsconfig.json': JSON.stringify({\n          include: ['../**/*.ts', '../**/*.vue'],\n          compilerOptions: {\n            composite: true,\n            paths: {\n              bar: ['../user.ts'],\n            },\n          },\n        }),\n        // tsconfig with no include / paths defined, should match nothing\n        '/empty/tsconfig.json': JSON.stringify({\n          compilerOptions: {\n            composite: true,\n          },\n        }),\n        '/user.ts': 'export type User = { bar: string }',\n      }\n\n      const { props, deps } = resolve(\n        `\n        import { User } from 'bar'\n        defineProps<User>() \n        `,\n        files,\n      )\n\n      expect(props).toStrictEqual({\n        bar: ['String'],\n      })\n      expect(deps && [...deps]).toStrictEqual(['/user.ts'])\n    })\n\n    // #11382\n    test('ts module resolve circular project reference', () => {\n      const files = {\n        '/tsconfig.json': JSON.stringify({\n          exclude: ['**/*.ts', '**/*.vue'],\n          references: [\n            {\n              path: './tsconfig.web.json',\n            },\n          ],\n        }),\n        '/tsconfig.web.json': JSON.stringify({\n          include: ['**/*.ts', '**/*.vue'],\n          compilerOptions: {\n            composite: true,\n            paths: {\n              user: ['./user.ts'],\n            },\n          },\n          references: [\n            {\n              // circular reference\n              path: './tsconfig.json',\n            },\n          ],\n        }),\n        '/user.ts': 'export type User = { bar: string }',\n      }\n\n      const { props, deps } = resolve(\n        `\n        import { User } from 'user'\n        defineProps<User>() \n        `,\n        files,\n      )\n\n      expect(props).toStrictEqual({\n        bar: ['String'],\n      })\n      expect(deps && [...deps]).toStrictEqual(['/user.ts'])\n    })\n\n    test('ts module resolve w/ path aliased vue file', () => {\n      const files = {\n        '/tsconfig.json': JSON.stringify({\n          compilerOptions: {\n            include: ['**/*.ts', '**/*.vue'],\n            paths: {\n              '@/*': ['./src/*'],\n            },\n          },\n        }),\n        '/src/Foo.vue':\n          '<script lang=\"ts\">export type P = { bar: string }</script>',\n      }\n\n      const { props, deps } = resolve(\n        `\n        import { P } from '@/Foo.vue'\n        defineProps<P>()\n        `,\n        files,\n      )\n\n      expect(props).toStrictEqual({\n        bar: ['String'],\n      })\n      expect(deps && [...deps]).toStrictEqual(['/src/Foo.vue'])\n    })\n\n    test('global types', () => {\n      const files = {\n        // ambient\n        '/app.d.ts':\n          'declare namespace App { interface User { name: string } }',\n        // module - should only respect the declare global block\n        '/global.d.ts': `\n          declare type PP = { bar: number }\n          declare global {\n            type PP = { bar: string }\n          }\n          export {}\n        `,\n      }\n\n      const { props, deps } = resolve(`defineProps<App.User & PP>()`, files, {\n        globalTypeFiles: Object.keys(files),\n      })\n\n      expect(props).toStrictEqual({\n        name: ['String'],\n        bar: ['String'],\n      })\n      expect(deps && [...deps]).toStrictEqual(Object.keys(files))\n    })\n\n    test('global types with named exports', () => {\n      const files = {\n        '/global.d.ts': `\n          declare global {\n            export interface ExportedInterface { foo: number }\n            export type ExportedType = { bar: boolean }\n          }\n          export {}\n        `,\n      }\n\n      const globalTypeFiles = { globalTypeFiles: Object.keys(files) }\n\n      expect(\n        resolve(`defineProps<ExportedInterface>()`, files, globalTypeFiles)\n          .props,\n      ).toStrictEqual({\n        foo: ['Number'],\n      })\n\n      expect(\n        resolve(`defineProps<ExportedType>()`, files, globalTypeFiles).props,\n      ).toStrictEqual({\n        bar: ['Boolean'],\n      })\n    })\n\n    test('global types with ambient references', () => {\n      const files = {\n        // with references\n        '/backend.d.ts': `\n          declare namespace App.Data {\n            export type AircraftData = {\n              id: string\n              manufacturer: App.Data.Listings.ManufacturerData\n            }\n          }\n          declare namespace App.Data.Listings {\n            export type ManufacturerData = {\n              id: string\n            }\n          }\n        `,\n      }\n\n      const { props } = resolve(`defineProps<App.Data.AircraftData>()`, files, {\n        globalTypeFiles: Object.keys(files),\n      })\n\n      expect(props).toStrictEqual({\n        id: ['String'],\n        manufacturer: ['Object'],\n      })\n    })\n\n    test('declare global with indexed access type', () => {\n      const files = {\n        '/global.d.ts': `\n          declare global {\n            type Options = {\n              code: {\n                selected: boolean\n              }\n            }\n          }`,\n      }\n      const { props } = resolve(`defineProps<Options[\"code\"]>()`, files, {\n        globalTypeFiles: Object.keys(files),\n      })\n\n      expect(props).toStrictEqual({\n        selected: ['Boolean'],\n      })\n    })\n\n    // #9871\n    test('shared generics with different args', () => {\n      const files = {\n        '/foo.ts': `export interface Foo<T> { value: T }`,\n      }\n      const { props } = resolve(\n        `import type { Foo } from './foo'\n        defineProps<Foo<string>>()`,\n        files,\n        undefined,\n        `/One.vue`,\n      )\n      expect(props).toStrictEqual({\n        value: ['String'],\n      })\n      const { props: props2 } = resolve(\n        `import type { Foo } from './foo'\n        defineProps<Foo<number>>()`,\n        files,\n        undefined,\n        `/Two.vue`,\n        false /* do not invalidate cache */,\n      )\n      expect(props2).toStrictEqual({\n        value: ['Number'],\n      })\n    })\n  })\n\n  describe('errors', () => {\n    test('failed type reference', () => {\n      expect(() => resolve(`defineProps<X>()`)).toThrow(\n        `Unresolvable type reference`,\n      )\n    })\n\n    test('unsupported computed keys', () => {\n      expect(() => resolve(`defineProps<{ [Foo]: string }>()`)).toThrow(\n        `Unsupported computed key in type referenced by a macro`,\n      )\n    })\n\n    test('unsupported index type', () => {\n      expect(() => resolve(`defineProps<X[K]>()`)).toThrow(\n        `Unsupported type when resolving index type`,\n      )\n    })\n\n    test('failed import source resolve', () => {\n      expect(() =>\n        resolve(`import { X } from './foo'; defineProps<X>()`),\n      ).toThrow(`Failed to resolve import source \"./foo\"`)\n    })\n\n    test('should not error on unresolved type when inferring runtime type', () => {\n      expect(() => resolve(`defineProps<{ foo: T }>()`)).not.toThrow()\n      expect(() => resolve(`defineProps<{ foo: T['bar'] }>()`)).not.toThrow()\n      expect(() =>\n        resolve(`\n        import type P from 'unknown'\n        defineProps<{ foo: P }>()\n      `),\n      ).not.toThrow()\n    })\n\n    test('error against failed extends', () => {\n      expect(() =>\n        resolve(`\n        import type Base from 'unknown'\n        interface Props extends Base {}\n        defineProps<Props>()\n      `),\n      ).toThrow(`@vue-ignore`)\n    })\n\n    test('allow ignoring failed extends', () => {\n      let res: any\n\n      expect(\n        () =>\n          (res = resolve(`\n        import type Base from 'unknown'\n        interface Props extends /*@vue-ignore*/ Base {\n          foo: string\n        }\n        defineProps<Props>()\n      `)),\n      ).not.toThrow(`@vue-ignore`)\n\n      expect(res.props).toStrictEqual({\n        foo: ['String'],\n      })\n    })\n  })\n\n  describe('template literals', () => {\n    test('mapped types with string type', () => {\n      expect(\n        resolve(`\n      type X = 'a' | 'b'\n      defineProps<{[K in X as \\`\\${K}_foo\\`]: string}>()\n      `).props,\n      ).toStrictEqual({\n        a_foo: ['String'],\n        b_foo: ['String'],\n      })\n    })\n\n    // #10962\n    test('mapped types with generic parameters', () => {\n      const { props } = resolve(`\n      type Breakpoints = 'sm' | 'md' | 'lg'\n      type BreakpointFactory<T extends string, V> = {\n        [K in Breakpoints as \\`\\${T}\\${Capitalize<K>}\\`]: V\n      }\n      type ColsBreakpoints = BreakpointFactory<'cols', number>\n      defineProps<ColsBreakpoints>()\n      `)\n      expect(props).toStrictEqual({\n        colsSm: ['Number'],\n        colsMd: ['Number'],\n        colsLg: ['Number'],\n      })\n    })\n\n    test('allowArbitraryExtensions', () => {\n      const files = {\n        '/foo.d.vue.ts': 'export type Foo = number;',\n        '/foo.vue': '<template><div /></template>',\n        '/bar.d.css.ts': 'export type Bar = string;',\n        '/bar.css': ':root { --color: red; }',\n      }\n\n      const { props } = resolve(\n        `\n        import { Foo } from './foo.vue'\n        import { Bar } from './bar.css'\n        defineProps<{ foo: Foo; bar: Bar }>()\n        `,\n        files,\n      )\n\n      expect(props).toStrictEqual({\n        foo: ['Number'],\n        bar: ['String'],\n      })\n    })\n\n    // https://github.com/vuejs/router/issues/2611\n    test('modular js extension', () => {\n      const files = {\n        '/mts.mjs': 'export {}',\n        '/mts.d.mts': 'export type LinkProps = { activeClass: string }',\n        '/tsx.jsx': 'export {}',\n        '/tsx.d.ts': 'export type Foo = number',\n        '/mtsTyped.mjs': 'export {}',\n        '/mtsTyped.d.ts': 'export type Bar = string',\n        '/cts.cjs': 'module.exports = {}',\n        '/cts.d.cts': `export type Baz = boolean`,\n      }\n\n      let props!: Record<string, string[]>\n      expect(() => {\n        props = resolve(\n          `\n        import type { LinkProps } from './mts.mjs'\n        import { Foo } from './tsx.jsx'\n        import { Bar } from './mtsTyped.mjs'\n        import type { Baz } from './cts.cjs'\n        defineProps<LinkProps & { foo: Foo; bar: Bar; baz: Baz }>()\n        `,\n          files,\n        ).props\n      }).not.toThrow()\n      expect(props).not.toBe(undefined)\n      expect(props).toStrictEqual({\n        foo: ['Number'],\n        bar: ['String'],\n        baz: ['Boolean'],\n        activeClass: ['String'],\n      })\n    })\n\n    test('prefer .mts over .ts for .mjs import', () => {\n      const files = {\n        '/foo.mjs': 'export {}',\n        '/foo.ts': 'export type Foo = number',\n        '/foo.mts': 'export type Foo = string',\n      }\n\n      const { props } = resolve(\n        `\n        import type { Foo } from './foo.mjs'\n        defineProps<{ value: Foo }>()\n        `,\n        files,\n      )\n\n      expect(props).toStrictEqual({\n        value: ['String'],\n      })\n    })\n\n    test('prefer .d.mts over .d.ts for .mjs import', () => {\n      const files = {\n        '/foo.mjs': 'export {}',\n        '/foo.d.ts': 'export type Foo = number',\n        '/foo.d.mts': 'export type Foo = string',\n      }\n\n      const { props } = resolve(\n        `\n        import type { Foo } from './foo.mjs'\n        defineProps<{ value: Foo }>()\n        `,\n        files,\n      )\n\n      expect(props).toStrictEqual({\n        value: ['String'],\n      })\n    })\n\n    test('prefer .d.cts over .d.ts for .cjs import', () => {\n      const files = {\n        '/foo.cjs': 'module.exports = {}',\n        '/foo.d.ts': 'export type Foo = number',\n        '/foo.d.cts': 'export type Foo = boolean',\n      }\n\n      const { props } = resolve(\n        `\n        import type { Foo } from './foo.cjs'\n        defineProps<{ value: Foo }>()\n        `,\n        files,\n      )\n\n      expect(props).toStrictEqual({\n        value: ['Boolean'],\n      })\n    })\n  })\n})\n\nfunction resolve(\n  code: string,\n  files: Record<string, string> = {},\n  options?: Partial<SFCScriptCompileOptions>,\n  sourceFileName: string = '/Test.vue',\n  invalidateCache = true,\n) {\n  const { descriptor } = parse(`<script setup lang=\"ts\">\\n${code}\\n</script>`, {\n    filename: sourceFileName,\n  })\n  const ctx = new ScriptCompileContext(descriptor, {\n    id: 'test',\n    fs: {\n      fileExists(file) {\n        return !!(files[file] ?? files[normalize(file)])\n      },\n      readFile(file) {\n        return files[file] ?? files[normalize(file)]\n      },\n    },\n    ...options,\n  })\n\n  if (invalidateCache) {\n    for (const file in files) {\n      invalidateTypeCache(file)\n    }\n  }\n\n  // ctx.userImports is collected when calling compileScript(), but we are\n  // skipping that here, so need to manually register imports\n  ctx.userImports = recordImports(ctx.scriptSetupAst!.body) as any\n\n  let target: any\n  for (const s of ctx.scriptSetupAst!.body) {\n    if (\n      s.type === 'ExpressionStatement' &&\n      s.expression.type === 'CallExpression' &&\n      (s.expression.callee as Identifier).name === 'defineProps'\n    ) {\n      target = s.expression.typeParameters!.params[0]\n    }\n  }\n  const raw = resolveTypeElements(ctx, target)\n  const props: Record<string, string[]> = {}\n  for (const key in raw.props) {\n    props[key] = inferRuntimeType(ctx, raw.props[key])\n  }\n  return {\n    props,\n    calls: raw.calls,\n    deps: ctx.deps,\n    raw,\n  }\n}\n"
  },
  {
    "path": "packages/compiler-sfc/__tests__/compileScript.spec.ts",
    "content": "import { vi } from 'vitest'\nimport { BindingTypes } from '@vue/compiler-core'\nimport {\n  assertCode,\n  compileSFCScript as compile,\n  getPositionInCode,\n  mockId,\n} from './utils'\nimport { type RawSourceMap, SourceMapConsumer } from 'source-map-js'\n\nvi.mock('../src/warn', () => ({\n  warn: vi.fn(),\n  warnOnce: vi.fn(),\n}))\n\nimport { warnOnce } from '../src/warn'\n\nconst warnOnceMock = vi.mocked(warnOnce)\n\ndescribe('SFC compile <script setup>', () => {\n  test('should compile JS syntax', () => {\n    const { content } = compile(`\n      <script setup lang='js'>\n      const a = 1\n      const b = 2\n      </script>\n    `)\n    expect(content).toMatch(`return { a, b }`)\n    assertCode(content)\n  })\n\n  test('should expose top level declarations', () => {\n    const { content, bindings } = compile(`\n      <script setup>\n      import { x } from './x'\n      let a = 1\n      const b = 2\n      function c() {}\n      class d {}\n      </script>\n\n      <script>\n      import { xx } from './x'\n      let aa = 1\n      const bb = 2\n      function cc() {}\n      class dd {}\n      </script>\n      `)\n    expect(content).toMatch(\n      `return { get aa() { return aa }, set aa(v) { aa = v }, ` +\n        `bb, cc, dd, get a() { return a }, set a(v) { a = v }, b, c, d, ` +\n        `get xx() { return xx }, get x() { return x } }`,\n    )\n    expect(bindings).toStrictEqual({\n      x: BindingTypes.SETUP_MAYBE_REF,\n      a: BindingTypes.SETUP_LET,\n      b: BindingTypes.SETUP_CONST,\n      c: BindingTypes.SETUP_CONST,\n      d: BindingTypes.SETUP_CONST,\n      xx: BindingTypes.SETUP_MAYBE_REF,\n      aa: BindingTypes.SETUP_LET,\n      bb: BindingTypes.LITERAL_CONST,\n      cc: BindingTypes.SETUP_CONST,\n      dd: BindingTypes.SETUP_CONST,\n    })\n    assertCode(content)\n  })\n\n  test('binding analysis for destructure', () => {\n    const { content, bindings } = compile(`\n      <script setup>\n      const { foo, b: bar, ['x' + 'y']: baz, x: { y, zz: { z }}} = {}\n      </script>\n      `)\n    expect(content).toMatch('return { foo, bar, baz, y, z }')\n    expect(bindings).toStrictEqual({\n      foo: BindingTypes.SETUP_MAYBE_REF,\n      bar: BindingTypes.SETUP_MAYBE_REF,\n      baz: BindingTypes.SETUP_MAYBE_REF,\n      y: BindingTypes.SETUP_MAYBE_REF,\n      z: BindingTypes.SETUP_MAYBE_REF,\n    })\n    assertCode(content)\n  })\n\n  test('demote const reactive binding to let when used in v-model', () => {\n    warnOnceMock.mockClear()\n    const { content, bindings } = compile(`\n      <script setup>\n      import { reactive } from 'vue'\n      const name = reactive({ first: 'john', last: 'doe' })\n      </script>\n\n      <template>\n        <MyComponent v-model=\"name\" />\n      </template>\n    `)\n\n    expect(content).toMatch(\n      `let name = reactive({ first: 'john', last: 'doe' })`,\n    )\n    expect(bindings!.name).toBe(BindingTypes.SETUP_LET)\n    expect(warnOnceMock).toHaveBeenCalledTimes(1)\n    expect(warnOnceMock).toHaveBeenCalledWith(\n      expect.stringContaining(\n        '`v-model` cannot update a `const` reactive binding',\n      ),\n    )\n    assertCode(content)\n  })\n\n  test('demote const reactive binding to let when used in v-model (inlineTemplate)', () => {\n    warnOnceMock.mockClear()\n    const { content, bindings } = compile(\n      `\n      <script setup>\n      import { reactive } from 'vue'\n      const name = reactive({ first: 'john', last: 'doe' })\n      </script>\n\n      <template>\n        <MyComponent v-model=\"name\" />\n      </template>\n      `,\n      { inlineTemplate: true },\n    )\n\n    expect(content).toMatch(\n      `let name = reactive({ first: 'john', last: 'doe' })`,\n    )\n    expect(bindings!.name).toBe(BindingTypes.SETUP_LET)\n    expect(warnOnceMock).toHaveBeenCalledTimes(1)\n    expect(warnOnceMock).toHaveBeenCalledWith(\n      expect.stringContaining(\n        '`v-model` cannot update a `const` reactive binding',\n      ),\n    )\n    assertCode(content)\n  })\n\n  test('v-model should error on literal const bindings', () => {\n    expect(() =>\n      compile(\n        `\n        <script setup>\n        const foo = 1\n        </script>\n        <template>\n          <input v-model=\"foo\" />\n        </template>\n        `,\n        { inlineTemplate: true },\n      ),\n    ).toThrow('v-model cannot be used on a const binding')\n  })\n\n  describe('<script> and <script setup> co-usage', () => {\n    test('script first', () => {\n      const { content } = compile(`\n      <script>\n      export const n = 1\n\n      export default {}\n      </script>\n      <script setup>\n      import { x } from './x'\n      x()\n      </script>\n      `)\n      assertCode(content)\n    })\n\n    test('script setup first', () => {\n      const { content } = compile(`\n      <script setup>\n      import { x } from './x'\n      x()\n      </script>\n      <script>\n      export const n = 1\n      export default {}\n      </script>\n      `)\n      assertCode(content)\n    })\n\n    // #7805\n    test('keep original semi style', () => {\n      const { content } = compile(`\n        <script setup>\n        console.log('test')\n        const props = defineProps(['item']);\n        const emit = defineEmits(['change']);\n        (function () {})()\n        </script>\n      `)\n      assertCode(content)\n\n      expect(content).toMatch(`console.log('test')`)\n      expect(content).toMatch(`const props = __props;`)\n      expect(content).toMatch(`const emit = __emit;`)\n      expect(content).toMatch(`(function () {})()`)\n    })\n\n    test('script setup first, named default export', () => {\n      const { content } = compile(`\n      <script setup>\n      import { x } from './x'\n      x()\n      </script>\n      <script>\n      export const n = 1\n      const def = {}\n      export { def as default }\n      </script>\n      `)\n      assertCode(content)\n    })\n\n    // #4395\n    test('script setup first, lang=\"ts\", script block content export default', () => {\n      const { content } = compile(`\n      <script setup lang=\"ts\">\n      import { x } from './x'\n      x()\n      </script>\n      <script lang=\"ts\">\n      export default {\n        name: \"test\"\n      }\n      </script>\n      `)\n      // ensure __default__ is declared before used\n      expect(content).toMatch(/const __default__[\\S\\s]*\\.\\.\\.__default__/m)\n      assertCode(content)\n    })\n\n    describe('spaces in ExportDefaultDeclaration node', () => {\n      // #4371\n      test('with many spaces and newline', () => {\n        // #4371\n        const { content } = compile(`\n        <script>\n        export const n = 1\n        export        default\n        {\n          some:'option'\n        }\n        </script>\n        <script setup>\n        import { x } from './x'\n        x()\n        </script>\n        `)\n        assertCode(content)\n      })\n\n      test('with minimal spaces', () => {\n        const { content } = compile(`\n        <script>\n        export const n = 1\n        export default{\n          some:'option'\n        }\n        </script>\n        <script setup>\n        import { x } from './x'\n        x()\n        </script>\n        `)\n        assertCode(content)\n      })\n    })\n\n    test('export call expression as default', () => {\n      const { content } = compile(`\n      <script>\n      function fn() {\n        return \"hello, world\";\n      }\n      export default fn();\n      </script>\n\n      <script setup>\n      console.log('foo')\n      </script>\n      `)\n      assertCode(content)\n    })\n  })\n\n  describe('imports', () => {\n    test('should hoist and expose imports', () => {\n      assertCode(\n        compile(`<script setup>\n          import { ref } from 'vue'\n          import 'foo/css'\n        </script>`).content,\n      )\n    })\n\n    test('should extract comment for import or type declarations', () => {\n      assertCode(\n        compile(`\n        <script setup>\n        import a from 'a' // comment\n        import b from 'b'\n        </script>\n        `).content,\n      )\n    })\n\n    // #2740\n    test('should allow defineProps/Emit at the start of imports', () => {\n      assertCode(\n        compile(`<script setup>\n      import { ref } from 'vue'\n      defineProps(['foo'])\n      defineEmits(['bar'])\n      const r = ref(0)\n      </script>`).content,\n      )\n    })\n\n    test('dedupe between user & helper', () => {\n      const { content } = compile(\n        `\n      <script setup>\n      import { useCssVars, ref } from 'vue'\n      const msg = ref()\n      </script>\n\n      <style>\n      .foo {\n        color: v-bind(msg)\n      }\n      </style>\n      `,\n      )\n      assertCode(content)\n      expect(content).toMatch(\n        `import { useCssVars as _useCssVars, unref as _unref } from 'vue'`,\n      )\n      expect(content).toMatch(`import { useCssVars, ref } from 'vue'`)\n    })\n\n    test('import dedupe between <script> and <script setup>', () => {\n      const { content } = compile(`\n        <script>\n        import { x } from './x'\n        </script>\n        <script setup>\n        import { x } from './x'\n        x()\n        </script>\n        `)\n      assertCode(content)\n      expect(content.indexOf(`import { x }`)).toEqual(\n        content.lastIndexOf(`import { x }`),\n      )\n    })\n\n    describe('import ref/reactive function from other place', () => {\n      test('import directly', () => {\n        const { bindings } = compile(`\n        <script setup>\n          import { ref, reactive } from './foo'\n\n          const foo = ref(1)\n          const bar = reactive(1)\n        </script>\n      `)\n        expect(bindings).toStrictEqual({\n          ref: BindingTypes.SETUP_MAYBE_REF,\n          reactive: BindingTypes.SETUP_MAYBE_REF,\n          foo: BindingTypes.SETUP_MAYBE_REF,\n          bar: BindingTypes.SETUP_MAYBE_REF,\n        })\n      })\n\n      test('import w/ alias', () => {\n        const { bindings } = compile(`\n        <script setup>\n          import { ref as _ref, reactive as _reactive } from './foo'\n\n          const foo = ref(1)\n          const bar = reactive(1)\n        </script>\n      `)\n        expect(bindings).toStrictEqual({\n          _reactive: BindingTypes.SETUP_MAYBE_REF,\n          _ref: BindingTypes.SETUP_MAYBE_REF,\n          foo: BindingTypes.SETUP_MAYBE_REF,\n          bar: BindingTypes.SETUP_MAYBE_REF,\n        })\n      })\n\n      test('aliased usage before import site', () => {\n        const { bindings } = compile(`\n        <script setup>\n          const bar = x(1)\n          import { reactive as x } from 'vue'\n        </script>\n      `)\n        expect(bindings).toStrictEqual({\n          bar: BindingTypes.SETUP_REACTIVE_CONST,\n          x: BindingTypes.SETUP_CONST,\n        })\n      })\n    })\n\n    test('should support module string names syntax', () => {\n      const { content, bindings } = compile(`\n      <script>\n        import { \"😏\" as foo } from './foo'\n      </script>\n      <script setup>\n        import { \"😏\" as foo } from './foo'\n      </script>\n    `)\n      assertCode(content)\n      expect(bindings).toStrictEqual({\n        foo: BindingTypes.SETUP_MAYBE_REF,\n      })\n    })\n  })\n\n  describe('inlineTemplate mode', () => {\n    test('should work', () => {\n      const { content } = compile(\n        `\n        <script setup>\n        import { ref } from 'vue'\n        const count = ref(0)\n        </script>\n        <template>\n          <div>{{ count }}</div>\n          <div>static</div>\n        </template>\n        `,\n        { inlineTemplate: true },\n      )\n      // check snapshot and make sure helper imports and\n      // hoists are placed correctly.\n      assertCode(content)\n      // in inline mode, no need to call expose() since nothing is exposed\n      // anyway!\n      expect(content).not.toMatch(`expose()`)\n    })\n\n    test('with defineExpose()', () => {\n      const { content } = compile(\n        `\n        <script setup>\n        const count = ref(0)\n        defineExpose({ count })\n        </script>\n        `,\n        { inlineTemplate: true },\n      )\n      assertCode(content)\n      expect(content).toMatch(`setup(__props, { expose: __expose })`)\n      expect(content).toMatch(`expose({ count })`)\n    })\n\n    test('referencing scope components and directives', () => {\n      const { content } = compile(\n        `\n        <script setup>\n        import ChildComp from './Child.vue'\n        import SomeOtherComp from './Other.vue'\n        import vMyDir from './my-dir'\n        </script>\n        <template>\n          <div v-my-dir></div>\n          <ChildComp/>\n          <some-other-comp/>\n        </template>\n        `,\n        { inlineTemplate: true },\n      )\n      expect(content).toMatch('[_unref(vMyDir)]')\n      expect(content).toMatch('_createVNode(ChildComp)')\n      // kebab-case component support\n      expect(content).toMatch('_createVNode(SomeOtherComp)')\n      assertCode(content)\n    })\n\n    test('avoid unref() when necessary', () => {\n      // function, const, component import\n      const { content } = compile(\n        `<script setup>\n        import { ref } from 'vue'\n        import Foo, { bar } from './Foo.vue'\n        import other from './util'\n        import * as tree from './tree'\n        const count = ref(0)\n        const constant = {}\n        const maybe = foo()\n        let lett = 1\n        function fn() {}\n        </script>\n        <template>\n          <Foo>{{ bar }}</Foo>\n          <div @click=\"fn\">{{ count }} {{ constant }} {{ maybe }} {{ lett }} {{ other }}</div>\n          {{ tree.foo() }}\n        </template>\n        `,\n        { inlineTemplate: true },\n      )\n      // no need to unref vue component import\n      expect(content).toMatch(`createVNode(Foo,`)\n      // #2699 should unref named imports from .vue\n      expect(content).toMatch(`unref(bar)`)\n      // should unref other imports\n      expect(content).toMatch(`unref(other)`)\n      // no need to unref constant literals\n      expect(content).not.toMatch(`unref(constant)`)\n      // should directly use .value for known refs\n      expect(content).toMatch(`count.value`)\n      // should unref() on const bindings that may be refs\n      expect(content).toMatch(`unref(maybe)`)\n      // should unref() on let bindings\n      expect(content).toMatch(`unref(lett)`)\n      // no need to unref namespace import (this also preserves tree-shaking)\n      expect(content).toMatch(`tree.foo()`)\n      // no need to unref function declarations\n      expect(content).toMatch(`{ onClick: fn }`)\n      // no need to mark constant fns in patch flag\n      expect(content).not.toMatch(`PROPS`)\n      assertCode(content)\n    })\n\n    test('v-model codegen', () => {\n      const { content } = compile(\n        `<script setup>\n        import { ref } from 'vue'\n        const count = ref(0)\n        const maybe = foo()\n        let lett = 1\n        </script>\n        <template>\n          <input v-model=\"count\">\n          <input v-model=\"maybe\">\n          <input v-model=\"lett\">\n        </template>\n        `,\n        { inlineTemplate: true },\n      )\n      // known const ref: set value\n      expect(content).toMatch(`(count).value = $event`)\n      // const but maybe ref: assign if ref, otherwise do nothing\n      expect(content).toMatch(`_isRef(maybe) ? (maybe).value = $event : null`)\n      // let: handle both cases\n      expect(content).toMatch(\n        `_isRef(lett) ? (lett).value = $event : lett = $event`,\n      )\n      assertCode(content)\n    })\n\n    test('v-model w/ newlines codegen', () => {\n      const { content } = compile(\n        `<script setup>\n        const count = ref(0)\n        </script>\n        <template>\n          <input v-model=\"\n          count\n          \">\n        </template>\n        `,\n        { inlineTemplate: true },\n      )\n      expect(content).toMatch(`_isRef(count) ? (count).value = $event : null`)\n      assertCode(content)\n    })\n\n    test('v-model should not generate ref assignment code for non-setup bindings', () => {\n      const { content } = compile(\n        `<script setup>\n        import { ref } from 'vue'\n        const count = ref(0)\n        </script>\n        <script>\n        export default {\n          data() { return { foo: 123 } }\n        }\n        </script>\n        <template>\n          <input v-model=\"foo\">\n        </template>\n        `,\n        { inlineTemplate: true },\n      )\n      expect(content).not.toMatch(`_isRef(foo)`)\n    })\n\n    test('template assignment expression codegen', () => {\n      const { content } = compile(\n        `<script setup>\n        import { ref } from 'vue'\n        const count = ref(0)\n        const maybe = foo()\n        let lett = 1\n        let v = ref(1)\n        </script>\n        <template>\n          <div @click=\"count = 1\"/>\n          <div @click=\"maybe = count\"/>\n          <div @click=\"lett = count\"/>\n          <div @click=\"v += 1\"/>\n          <div @click=\"v -= 1\"/>\n          <div @click=\"() => {\n              let a = '' + lett\n              v = a\n           }\"/>\n           <div @click=\"() => {\n              // nested scopes\n              (()=>{\n                let x = a\n                (()=>{\n                  let z = x\n                  let z2 = z\n                })\n                let lz = z\n              })\n              v = a\n           }\"/>\n        </template>\n        `,\n        { inlineTemplate: true },\n      )\n      // known const ref: set value\n      expect(content).toMatch(`count.value = 1`)\n      // const but maybe ref: only assign after check\n      expect(content).toMatch(`maybe.value = count.value`)\n      // let: handle both cases\n      expect(content).toMatch(\n        `_isRef(lett) ? lett.value = count.value : lett = count.value`,\n      )\n      expect(content).toMatch(`_isRef(v) ? v.value += 1 : v += 1`)\n      expect(content).toMatch(`_isRef(v) ? v.value -= 1 : v -= 1`)\n      expect(content).toMatch(`_isRef(v) ? v.value = a : v = a`)\n      expect(content).toMatch(`_isRef(v) ? v.value = _ctx.a : v = _ctx.a`)\n      assertCode(content)\n    })\n\n    test('template update expression codegen', () => {\n      const { content } = compile(\n        `<script setup>\n        import { ref } from 'vue'\n        const count = ref(0)\n        const maybe = foo()\n        let lett = 1\n        </script>\n        <template>\n          <div @click=\"count++\"/>\n          <div @click=\"--count\"/>\n          <div @click=\"maybe++\"/>\n          <div @click=\"--maybe\"/>\n          <div @click=\"lett++\"/>\n          <div @click=\"--lett\"/>\n        </template>\n        `,\n        { inlineTemplate: true },\n      )\n      // known const ref: set value\n      expect(content).toMatch(`count.value++`)\n      expect(content).toMatch(`--count.value`)\n      // const but maybe ref (non-ref case ignored)\n      expect(content).toMatch(`maybe.value++`)\n      expect(content).toMatch(`--maybe.value`)\n      // let: handle both cases\n      expect(content).toMatch(`_isRef(lett) ? lett.value++ : lett++`)\n      expect(content).toMatch(`_isRef(lett) ? --lett.value : --lett`)\n      assertCode(content)\n    })\n\n    test('template destructure assignment codegen', () => {\n      const { content } = compile(\n        `<script setup>\n        import { ref } from 'vue'\n        const val = {}\n        const count = ref(0)\n        const maybe = foo()\n        let lett = 1\n        </script>\n        <template>\n          <div @click=\"({ count } = val)\"/>\n          <div @click=\"[maybe] = val\"/>\n          <div @click=\"({ lett } = val)\"/>\n        </template>\n        `,\n        { inlineTemplate: true },\n      )\n      // known const ref: set value\n      expect(content).toMatch(`({ count: count.value } = val)`)\n      // const but maybe ref (non-ref case ignored)\n      expect(content).toMatch(`[maybe.value] = val`)\n      // let: assumes non-ref\n      expect(content).toMatch(`{ lett: lett } = val`)\n      assertCode(content)\n    })\n\n    test('ssr codegen', () => {\n      const { content } = compile(\n        `\n        <script setup>\n        import { ref } from 'vue'\n        const count = ref(0)\n        const style = { color: 'red' }\n        const height = ref(0)\n        </script>\n        <template>\n          <div>{{ count }}</div>\n          <div>static</div>\n        </template>\n        <style>\n        div { color: v-bind(count) }\n        span { color: v-bind(style.color) }\n        span { color: v-bind(height + \"px\") }\n        </style>\n        `,\n        {\n          inlineTemplate: true,\n          templateOptions: {\n            ssr: true,\n          },\n        },\n      )\n      expect(content).toMatch(`\\n  __ssrInlineRender: true,\\n`)\n      expect(content).toMatch(`return (_ctx, _push`)\n      expect(content).toMatch(`ssrInterpolate`)\n      expect(content).not.toMatch(`useCssVars`)\n      expect(content).toMatch(`\":--${mockId}-count\": (count.value)`)\n      expect(content).toMatch(`\":--${mockId}-style\\\\\\\\.color\": (style.color)`)\n      expect(content).toMatch(\n        `\":--${mockId}-height\\\\\\\\ \\\\\\\\+\\\\\\\\ \\\\\\\\\\\\\"px\\\\\\\\\\\\\"\": (height.value + \"px\")`,\n      )\n      assertCode(content)\n    })\n\n    test('the v-for wrapped in parentheses can be correctly parsed & inline is false', () => {\n      expect(() =>\n        compile(\n          `\n        <script setup lang=\"ts\">\n        import { ref } from 'vue'\n        const stacks = ref([])\n        </script>\n        <template>\n            <div v-for=\"({ file: efile }) of stacks\"></div>\n        </template>\n        `,\n          {\n            inlineTemplate: false,\n          },\n        ),\n      ).not.toThrowError()\n    })\n\n    test('unref + new expression', () => {\n      const { content } = compile(\n        `\n        <script setup>\n        import Foo from './foo'\n        </script>\n        <template>\n          <div>{{ new Foo() }}</div>\n          <div>{{ new Foo.Bar() }}</div>\n        </template>\n        `,\n        { inlineTemplate: true },\n      )\n      expect(content).toMatch(`new (_unref(Foo))()`)\n      expect(content).toMatch(`new (_unref(Foo)).Bar()`)\n      assertCode(content)\n    })\n\n    // #12682\n    test('source map', () => {\n      const source = `\n      <script setup>\n        const count = ref(0)\n      </script>\n      <template>\n        <button @click=\"throw new Error(\\`msg\\`);\"></button>\n      </template>\n      `\n      const { content, map } = compile(source, { inlineTemplate: true })\n      expect(map).not.toBeUndefined()\n      const consumer = new SourceMapConsumer(map as RawSourceMap)\n      expect(\n        consumer.originalPositionFor(getPositionInCode(content, 'count')),\n      ).toMatchObject(getPositionInCode(source, `count`))\n      expect(\n        consumer.originalPositionFor(getPositionInCode(content, 'Error')),\n      ).toMatchObject(getPositionInCode(source, `Error`))\n    })\n  })\n\n  describe('with TypeScript', () => {\n    test('hoist type declarations', () => {\n      const { content } = compile(`\n      <script setup lang=\"ts\">\n        export interface Foo {}\n        type Bar = {}\n      </script>`)\n      assertCode(content)\n    })\n\n    test('runtime Enum', () => {\n      const { content, bindings } = compile(\n        `<script setup lang=\"ts\">\n        enum Foo { A = 123 }\n        </script>`,\n      )\n      assertCode(content)\n      expect(bindings).toStrictEqual({\n        Foo: BindingTypes.LITERAL_CONST,\n      })\n    })\n\n    test('runtime Enum in normal script', () => {\n      const { content, bindings } = compile(\n        `<script lang=\"ts\">\n          export enum D { D = \"D\" }\n          const enum C { C = \"C\" }\n          enum B { B = \"B\" }\n        </script>\n        <script setup lang=\"ts\">\n        enum Foo { A = 123 }\n        </script>`,\n      )\n      assertCode(content)\n      expect(bindings).toStrictEqual({\n        D: BindingTypes.LITERAL_CONST,\n        C: BindingTypes.LITERAL_CONST,\n        B: BindingTypes.LITERAL_CONST,\n        Foo: BindingTypes.LITERAL_CONST,\n      })\n    })\n\n    test('const Enum', () => {\n      const { content, bindings } = compile(\n        `<script setup lang=\"ts\">\n        const enum Foo { A = 123 }\n        </script>`,\n        { hoistStatic: true },\n      )\n      assertCode(content)\n      expect(bindings).toStrictEqual({\n        Foo: BindingTypes.LITERAL_CONST,\n      })\n    })\n\n    test('import type', () => {\n      const { content } = compile(\n        `<script setup lang=\"ts\">\n        import type { Foo } from './main.ts'\n        import { type Bar, Baz } from './main.ts'\n        </script>`,\n      )\n      expect(content).toMatch(`return { get Baz() { return Baz } }`)\n      assertCode(content)\n    })\n\n    test('with generic attribute', () => {\n      const { content } = compile(`\n      <script setup lang=\"ts\" generic=\"T extends Record<string,string>\">\n        type Bar = {}\n      </script>`)\n      assertCode(content)\n    })\n  })\n\n  describe('async/await detection', () => {\n    function assertAwaitDetection(code: string, shouldAsync = true) {\n      const { content } = compile(`<script setup>${code}</script>`)\n      if (shouldAsync) {\n        expect(content).toMatch(`let __temp, __restore`)\n      }\n      expect(content).toMatch(`${shouldAsync ? `async ` : ``}setup(`)\n      assertCode(content)\n      return content\n    }\n\n    test('expression statement', () => {\n      assertAwaitDetection(`await foo`)\n    })\n\n    test('variable', () => {\n      assertAwaitDetection(`const a = 1 + (await foo)`)\n    })\n\n    test('ref', () => {\n      assertAwaitDetection(`let a = ref(1 + (await foo))`)\n    })\n\n    // #4448\n    test('nested await', () => {\n      assertAwaitDetection(`await (await foo)`)\n      assertAwaitDetection(`await ((await foo))`)\n      assertAwaitDetection(`await (await (await foo))`)\n    })\n\n    // should prepend semicolon\n    test('nested leading await in expression statement', () => {\n      const code = assertAwaitDetection(`foo()\\nawait 1 + await 2`)\n      expect(code).toMatch(`foo()\\n;(`)\n    })\n\n    // #4596 should NOT prepend semicolon\n    test('single line conditions', () => {\n      const code = assertAwaitDetection(`if (false) await foo()`)\n      expect(code).not.toMatch(`if (false) ;(`)\n    })\n\n    test('nested statements', () => {\n      assertAwaitDetection(`if (ok) { await foo } else { await bar }`)\n    })\n\n    test('multiple `if` nested statements', () => {\n      assertAwaitDetection(`if (ok) {\n        let a = 'foo'\n        await 0 + await 1\n        await 2\n      } else if (a) {\n        await 10\n        if (b) {\n          await 0 + await 1\n        } else {\n          let a = 'foo'\n          await 2\n        }\n        if (b) {\n          await 3\n          await 4\n        }\n      } else {\n        await 5\n      }`)\n    })\n\n    test('multiple `if while` nested statements', () => {\n      assertAwaitDetection(`if (ok) {\n        while (d) {\n          await 5\n        }\n        while (d) {\n          await 5\n          await 6\n          if (c) {\n            let f = 10\n            10 + await 7\n          } else {\n            await 8\n            await 9\n          }\n        }\n      }`)\n    })\n\n    test('multiple `if for` nested statements', () => {\n      assertAwaitDetection(`if (ok) {\n        for (let a of [1,2,3]) {\n          await a\n        }\n        for (let a of [1,2,3]) {\n          await a\n          await a\n        }\n      }`)\n    })\n\n    test('should ignore await inside functions', () => {\n      // function declaration\n      assertAwaitDetection(`async function foo() { await bar }`, false)\n      // function expression\n      assertAwaitDetection(`const foo = async () => { await bar }`, false)\n      // object method\n      assertAwaitDetection(`const obj = { async method() { await bar }}`, false)\n      // class method\n      assertAwaitDetection(\n        `const cls = class Foo { async method() { await bar }}`,\n        false,\n      )\n    })\n  })\n\n  describe('errors', () => {\n    test('<script> and <script setup> must have same lang', () => {\n      expect(() =>\n        compile(`<script>foo()</script><script setup lang=\"ts\">bar()</script>`),\n      ).toThrow(`<script> and <script setup> must have the same language type`)\n\n      // #13193 must check lang before parsing with babel\n      expect(() =>\n        compile(\n          `<script lang=\"ts\">const a = 1</script><script setup lang=\"tsx\">const Comp = () => <p>test</p></script>`,\n        ),\n      ).toThrow(`<script> and <script setup> must have the same language type`)\n    })\n\n    const moduleErrorMsg = `cannot contain ES module exports`\n\n    test('non-type named exports', () => {\n      expect(() =>\n        compile(`<script setup>\n        export const a = 1\n        </script>`),\n      ).toThrow(moduleErrorMsg)\n\n      expect(() =>\n        compile(`<script setup>\n        export * from './foo'\n        </script>`),\n      ).toThrow(moduleErrorMsg)\n\n      expect(() =>\n        compile(`<script setup>\n          const bar = 1\n          export { bar as default }\n        </script>`),\n      ).toThrow(moduleErrorMsg)\n    })\n\n    test('defineProps/Emit() referencing local var', () => {\n      expect(() =>\n        compile(`<script setup>\n        let bar = 1\n        defineProps({\n          foo: {\n            default: () => bar\n          }\n        })\n        </script>`),\n      ).toThrow(`cannot reference locally declared variables`)\n\n      expect(() =>\n        compile(`<script setup>\n        let bar = 'hello'\n        defineEmits([bar])\n        </script>`),\n      ).toThrow(`cannot reference locally declared variables`)\n\n      // #4644\n      expect(() =>\n        compile(`\n        <script>const bar = 1</script>\n        <script setup>\n        defineProps({\n          foo: {\n            default: () => bar\n          }\n        })\n        </script>`),\n      ).not.toThrow(`cannot reference locally declared variables`)\n    })\n\n    test('should allow defineProps/Emit() referencing scope var', () => {\n      assertCode(\n        compile(`<script setup>\n          const bar = 1\n          defineProps({\n            foo: {\n              default: bar => bar + 1\n            }\n          })\n          defineEmits({\n            foo: bar => bar > 1\n          })\n        </script>`).content,\n      )\n    })\n\n    test('should allow defineProps/Emit() referencing imported binding', () => {\n      assertCode(\n        compile(`<script setup>\n        import { bar } from './bar'\n        defineProps({\n          foo: {\n            default: () => bar\n          }\n        })\n        defineEmits({\n          foo: () => bar > 1\n        })\n        </script>`).content,\n      )\n    })\n\n    test('defineModel() referencing local var', () => {\n      expect(() =>\n        compile(`<script setup>\n        let bar = 1\n        defineModel({\n          default: () => bar\n        })\n        </script>`),\n      ).toThrow(`cannot reference locally declared variables`)\n\n      // allow const\n      expect(() =>\n        compile(`<script setup>\n        const bar = 1\n        defineModel({\n          default: () => bar\n        })\n        </script>`),\n      ).not.toThrow(`cannot reference locally declared variables`)\n\n      // allow in get/set\n      expect(() =>\n        compile(`<script setup>\n        let bar = 1\n        defineModel({\n          get: () => bar,\n          set: () => bar\n        })\n        </script>`),\n      ).not.toThrow(`cannot reference locally declared variables`)\n    })\n  })\n})\n\ndescribe('SFC analyze <script> bindings', () => {\n  it('can parse decorators syntax in typescript block', () => {\n    const { scriptAst } = compile(`\n      <script lang=\"ts\">\n        import { Options, Vue } from 'vue-class-component';\n        @Options({\n          components: {\n            HelloWorld,\n          },\n          props: ['foo', 'bar']\n        })\n        export default class Home extends Vue {}\n      </script>\n    `)\n\n    expect(scriptAst).toBeDefined()\n  })\n\n  it('recognizes props array declaration', () => {\n    const { bindings } = compile(`\n      <script>\n        export default {\n          props: ['foo', 'bar']\n        }\n      </script>\n    `)\n    expect(bindings).toStrictEqual({\n      foo: BindingTypes.PROPS,\n      bar: BindingTypes.PROPS,\n    })\n    expect(bindings!.__isScriptSetup).toBe(false)\n  })\n\n  it('recognizes props object declaration', () => {\n    const { bindings } = compile(`\n      <script>\n        export default {\n          props: {\n            foo: String,\n            bar: {\n              type: String,\n            },\n            baz: null,\n            qux: [String, Number]\n          }\n        }\n      </script>\n    `)\n    expect(bindings).toStrictEqual({\n      foo: BindingTypes.PROPS,\n      bar: BindingTypes.PROPS,\n      baz: BindingTypes.PROPS,\n      qux: BindingTypes.PROPS,\n    })\n    expect(bindings!.__isScriptSetup).toBe(false)\n  })\n\n  it('recognizes setup return', () => {\n    const { bindings } = compile(`\n      <script>\n        const bar = 2\n        export default {\n          setup() {\n            return {\n              foo: 1,\n              bar\n            }\n          }\n        }\n      </script>\n    `)\n    expect(bindings).toStrictEqual({\n      foo: BindingTypes.SETUP_MAYBE_REF,\n      bar: BindingTypes.SETUP_MAYBE_REF,\n    })\n    expect(bindings!.__isScriptSetup).toBe(false)\n  })\n\n  it('recognizes exported vars', () => {\n    const { bindings } = compile(`\n      <script>\n        export const foo = 2\n      </script>\n      <script setup>\n        console.log(foo)\n      </script>\n    `)\n    expect(bindings).toStrictEqual({\n      foo: BindingTypes.LITERAL_CONST,\n    })\n  })\n\n  it('recognizes async setup return', () => {\n    const { bindings } = compile(`\n      <script>\n        const bar = 2\n        export default {\n          async setup() {\n            return {\n              foo: 1,\n              bar\n            }\n          }\n        }\n      </script>\n    `)\n    expect(bindings).toStrictEqual({\n      foo: BindingTypes.SETUP_MAYBE_REF,\n      bar: BindingTypes.SETUP_MAYBE_REF,\n    })\n    expect(bindings!.__isScriptSetup).toBe(false)\n  })\n\n  it('recognizes data return', () => {\n    const { bindings } = compile(`\n      <script>\n        const bar = 2\n        export default {\n          data() {\n            return {\n              foo: null,\n              bar\n            }\n          }\n        }\n      </script>\n    `)\n    expect(bindings).toStrictEqual({\n      foo: BindingTypes.DATA,\n      bar: BindingTypes.DATA,\n    })\n  })\n\n  it('recognizes methods', () => {\n    const { bindings } = compile(`\n      <script>\n        export default {\n          methods: {\n            foo() {}\n          }\n        }\n      </script>\n    `)\n    expect(bindings).toStrictEqual({ foo: BindingTypes.OPTIONS })\n  })\n\n  it('recognizes computeds', () => {\n    const { bindings } = compile(`\n      <script>\n        export default {\n          computed: {\n            foo() {},\n            bar: {\n              get() {},\n              set() {},\n            }\n          }\n        }\n      </script>\n    `)\n    expect(bindings).toStrictEqual({\n      foo: BindingTypes.OPTIONS,\n      bar: BindingTypes.OPTIONS,\n    })\n  })\n\n  it('recognizes injections array declaration', () => {\n    const { bindings } = compile(`\n      <script>\n        export default {\n          inject: ['foo', 'bar']\n        }\n      </script>\n    `)\n    expect(bindings).toStrictEqual({\n      foo: BindingTypes.OPTIONS,\n      bar: BindingTypes.OPTIONS,\n    })\n  })\n\n  it('recognizes injections object declaration', () => {\n    const { bindings } = compile(`\n      <script>\n        export default {\n          inject: {\n            foo: {},\n            bar: {},\n          }\n        }\n      </script>\n    `)\n    expect(bindings).toStrictEqual({\n      foo: BindingTypes.OPTIONS,\n      bar: BindingTypes.OPTIONS,\n    })\n  })\n\n  it('works for mixed bindings', () => {\n    const { bindings } = compile(`\n      <script>\n        export default {\n          inject: ['foo'],\n          props: {\n            bar: String,\n          },\n          setup() {\n            return {\n              baz: null,\n            }\n          },\n          data() {\n            return {\n              qux: null\n            }\n          },\n          methods: {\n            quux() {}\n          },\n          computed: {\n            quuz() {}\n          }\n        }\n      </script>\n    `)\n    expect(bindings).toStrictEqual({\n      foo: BindingTypes.OPTIONS,\n      bar: BindingTypes.PROPS,\n      baz: BindingTypes.SETUP_MAYBE_REF,\n      qux: BindingTypes.DATA,\n      quux: BindingTypes.OPTIONS,\n      quuz: BindingTypes.OPTIONS,\n    })\n  })\n\n  it('works for script setup', () => {\n    const { bindings } = compile(`\n      <script setup>\n      import { ref as r } from 'vue'\n      defineProps({\n        foo: String\n      })\n\n      const a = r(1)\n      let b = 2\n      const c = 3\n      const { d } = someFoo()\n      let { e } = someBar()\n      </script>\n    `)\n\n    expect(bindings).toStrictEqual({\n      r: BindingTypes.SETUP_CONST,\n      a: BindingTypes.SETUP_REF,\n      b: BindingTypes.SETUP_LET,\n      c: BindingTypes.LITERAL_CONST,\n      d: BindingTypes.SETUP_MAYBE_REF,\n      e: BindingTypes.SETUP_LET,\n      foo: BindingTypes.PROPS,\n    })\n  })\n\n  describe('auto name inference', () => {\n    test('basic', () => {\n      const { content } = compile(\n        `<script setup>const a = 1</script>\n        <template>{{ a }}</template>`,\n        undefined,\n        {\n          filename: 'FooBar.vue',\n        },\n      )\n      expect(content).toMatch(`export default {\n  __name: 'FooBar'`)\n      assertCode(content)\n    })\n\n    test('do not overwrite manual name (object)', () => {\n      const { content } = compile(\n        `<script>\n        export default {\n          name: 'Baz'\n        }\n        </script>\n        <script setup>const a = 1</script>\n        <template>{{ a }}</template>`,\n        undefined,\n        {\n          filename: 'FooBar.vue',\n        },\n      )\n      expect(content).not.toMatch(`name: 'FooBar'`)\n      expect(content).toMatch(`name: 'Baz'`)\n      assertCode(content)\n    })\n\n    test('do not overwrite manual name (call)', () => {\n      const { content } = compile(\n        `<script>\n        import { defineComponent } from 'vue'\n        export default defineComponent({\n          name: 'Baz'\n        })\n        </script>\n        <script setup>const a = 1</script>\n        <template>{{ a }}</template>`,\n        undefined,\n        {\n          filename: 'FooBar.vue',\n        },\n      )\n      expect(content).not.toMatch(`name: 'FooBar'`)\n      expect(content).toMatch(`name: 'Baz'`)\n      assertCode(content)\n    })\n  })\n})\n\ndescribe('SFC genDefaultAs', () => {\n  test('normal <script> only', () => {\n    const { content } = compile(\n      `<script>\n      export default {}\n      </script>`,\n      {\n        genDefaultAs: '_sfc_',\n      },\n    )\n    expect(content).not.toMatch('export default')\n    expect(content).toMatch(`const _sfc_ = {}`)\n    assertCode(content)\n  })\n\n  test('normal <script> w/ cssVars', () => {\n    const { content } = compile(\n      `<script>\n      export default {}\n      </script>\n      <style>\n      .foo { color: v-bind(x) }\n      </style>`,\n      {\n        genDefaultAs: '_sfc_',\n      },\n    )\n    expect(content).not.toMatch('export default')\n    expect(content).not.toMatch('__default__')\n    expect(content).toMatch(`const _sfc_ = {}`)\n    assertCode(content)\n  })\n\n  test('<script> + <script setup>', () => {\n    const { content } = compile(\n      `<script>\n      export default {}\n      </script>\n      <script setup>\n      const a = 1\n      </script>`,\n      {\n        genDefaultAs: '_sfc_',\n      },\n    )\n    expect(content).not.toMatch('export default')\n    expect(content).toMatch(\n      `const _sfc_ = /*@__PURE__*/Object.assign(__default__`,\n    )\n    assertCode(content)\n  })\n\n  test('<script> + <script setup>', () => {\n    const { content } = compile(\n      `<script>\n      export default {}\n      </script>\n      <script setup>\n      const a = 1\n      </script>`,\n      {\n        genDefaultAs: '_sfc_',\n      },\n    )\n    expect(content).not.toMatch('export default')\n    expect(content).toMatch(\n      `const _sfc_ = /*@__PURE__*/Object.assign(__default__`,\n    )\n    assertCode(content)\n  })\n\n  test('<script setup> only', () => {\n    const { content } = compile(\n      `<script setup>\n      const a = 1\n      </script>`,\n      {\n        genDefaultAs: '_sfc_',\n      },\n    )\n    expect(content).not.toMatch('export default')\n    expect(content).toMatch(`const _sfc_ = {\\n  setup`)\n    assertCode(content)\n  })\n\n  test('<script setup> only w/ ts', () => {\n    const { content } = compile(\n      `<script setup lang=\"ts\">\n      const a = 1\n      </script>`,\n      {\n        genDefaultAs: '_sfc_',\n      },\n    )\n    expect(content).not.toMatch('export default')\n    expect(content).toMatch(`const _sfc_ = /*@__PURE__*/_defineComponent(`)\n    assertCode(content)\n  })\n\n  test('<script> + <script setup> w/ ts', () => {\n    const { content } = compile(\n      `<script lang=\"ts\">\n      export default {}\n      </script>\n      <script setup lang=\"ts\">\n      const a = 1\n      </script>`,\n      {\n        genDefaultAs: '_sfc_',\n      },\n    )\n    expect(content).not.toMatch('export default')\n    expect(content).toMatch(\n      `const _sfc_ = /*@__PURE__*/_defineComponent({\\n  ...__default__`,\n    )\n    assertCode(content)\n  })\n\n  test('binding type for edge cases', () => {\n    const { bindings } = compile(\n      `<script setup lang=\"ts\">\n      import { toRef } from 'vue'\n      const props = defineProps<{foo: string}>()\n      const foo = toRef(() => props.foo)\n      </script>`,\n    )\n    expect(bindings).toStrictEqual({\n      toRef: BindingTypes.SETUP_CONST,\n      props: BindingTypes.SETUP_REACTIVE_CONST,\n      foo: BindingTypes.SETUP_REF,\n    })\n  })\n\n  describe('parser plugins', () => {\n    test('import attributes', () => {\n      const { content } = compile(`\n        <script setup>\n        import { foo } from './foo.js' with { type: 'foobar' }\n        </script>\n      `)\n      assertCode(content)\n\n      expect(() =>\n        compile(`\n      <script setup>\n        import { foo } from './foo.js' assert { type: 'foobar' }\n        </script>`),\n      ).toThrow()\n    })\n\n    test('import attributes (user override for deprecated syntax)', () => {\n      const { content } = compile(\n        `\n        <script setup>\n        import { foo } from './foo.js' assert { type: 'foobar' }\n        </script>\n      `,\n        {\n          babelParserPlugins: [\n            ['importAttributes', { deprecatedAssertSyntax: true }],\n          ],\n        },\n      )\n      assertCode(content)\n    })\n  })\n})\n\ndescribe('compileScript', () => {\n  test('should care about runtimeModuleName', () => {\n    const { content } = compile(\n      `\n      <script setup>\n        await Promise.resolve(1)\n      </script>\n      `,\n      {\n        templateOptions: {\n          compilerOptions: {\n            runtimeModuleName: 'npm:vue',\n          },\n        },\n      },\n    )\n    expect(content).toMatch(\n      `import { withAsyncContext as _withAsyncContext } from \"npm:vue\"\\n`,\n    )\n    assertCode(content)\n  })\n\n  test('should not compile unrecognized language', () => {\n    const { content, lang, scriptAst } = compile(\n      `<script lang=\"coffee\">\n      export default\n        data: ->\n          myVal: 0\n      </script>`,\n    )\n    expect(content).toMatch(`export default\n        data: ->\n          myVal: 0`)\n    expect(lang).toBe('coffee')\n    expect(scriptAst).not.toBeDefined()\n  })\n})\n"
  },
  {
    "path": "packages/compiler-sfc/__tests__/compileStyle.spec.ts",
    "content": "import {\n  type SFCStyleCompileOptions,\n  compileStyle,\n  compileStyleAsync,\n} from '../src/compileStyle'\nimport path from 'node:path'\n\nexport function compileScoped(\n  source: string,\n  options?: Partial<SFCStyleCompileOptions>,\n): string {\n  const res = compileStyle({\n    source,\n    filename: 'test.css',\n    id: 'data-v-test',\n    scoped: true,\n    ...options,\n  })\n  if (res.errors.length) {\n    res.errors.forEach(err => {\n      console.error(err)\n    })\n    expect(res.errors.length).toBe(0)\n  }\n  return res.code\n}\n\ndescribe('SFC scoped CSS', () => {\n  test('simple selectors', () => {\n    expect(compileScoped(`h1 { color: red; }`)).toMatch(\n      `h1[data-v-test] { color: red;`,\n    )\n    expect(compileScoped(`.foo { color: red; }`)).toMatch(\n      `.foo[data-v-test] { color: red;`,\n    )\n  })\n\n  test('descendent selector', () => {\n    expect(compileScoped(`h1 .foo { color: red; }`)).toMatch(\n      `h1 .foo[data-v-test] { color: red;`,\n    )\n\n    // #13387\n    expect(\n      compileScoped(`main {\n  width: 100%;\n  > * {\n    max-width: 200px;\n  }\n}`),\n    ).toMatchInlineSnapshot(`\n      \"main {\n&[data-v-test] {\n  width: 100%;\n}\n> *[data-v-test] {\n    max-width: 200px;\n}\n}\"`)\n  })\n\n  test('nesting selector', () => {\n    expect(compileScoped(`h1 { color: red; .foo { color: red; } }`)).toMatch(\n      `h1 {\\n&[data-v-test] { color: red;\\n}\\n.foo[data-v-test] { color: red;`,\n    )\n  })\n\n  test('nesting selector with atrule and comment', () => {\n    expect(\n      compileScoped(\n        `h1 {\ncolor: red;\n/*background-color: pink;*/\n@media only screen and (max-width: 800px) {\n  background-color: green;\n  .bar { color: white }\n}\n.foo { color: red; }\n}`,\n      ),\n    ).toMatch(\n      `h1 {\n&[data-v-test] {\ncolor: red\n/*background-color: pink;*/\n}\n@media only screen and (max-width: 800px) {\n&[data-v-test] {\n  background-color: green\n}\n.bar[data-v-test] { color: white\n}\n}\n.foo[data-v-test] { color: red;\n}\n}`,\n    )\n  })\n\n  test('multiple selectors', () => {\n    expect(compileScoped(`h1 .foo, .bar, .baz { color: red; }`)).toMatch(\n      `h1 .foo[data-v-test], .bar[data-v-test], .baz[data-v-test] { color: red;`,\n    )\n  })\n\n  test('pseudo class', () => {\n    expect(compileScoped(`.foo:after { color: red; }`)).toMatch(\n      `.foo[data-v-test]:after { color: red;`,\n    )\n  })\n\n  test('pseudo element', () => {\n    expect(compileScoped(`::selection { display: none; }`)).toMatch(\n      '[data-v-test]::selection {',\n    )\n  })\n\n  test('spaces before pseudo element', () => {\n    const code = compileScoped(`.abc, ::selection { color: red; }`)\n    expect(code).toMatch('.abc[data-v-test],')\n    expect(code).toMatch('[data-v-test]::selection {')\n  })\n\n  test('::v-deep', () => {\n    expect(compileScoped(`:deep(.foo) { color: red; }`)).toMatchInlineSnapshot(`\n      \"[data-v-test] .foo { color: red;\n      }\"\n    `)\n    expect(compileScoped(`::v-deep(.foo) { color: red; }`))\n      .toMatchInlineSnapshot(`\n      \"[data-v-test] .foo { color: red;\n      }\"\n    `)\n    expect(compileScoped(`::v-deep(.foo .bar) { color: red; }`))\n      .toMatchInlineSnapshot(`\n      \"[data-v-test] .foo .bar { color: red;\n      }\"\n    `)\n    expect(compileScoped(`.baz .qux ::v-deep(.foo .bar) { color: red; }`))\n      .toMatchInlineSnapshot(`\n      \".baz .qux[data-v-test] .foo .bar { color: red;\n      }\"\n    `)\n    expect(compileScoped(`:is(.foo :deep(.bar)) { color: red; }`))\n      .toMatchInlineSnapshot(`\n      \":is(.foo[data-v-test] .bar) { color: red;\n      }\"\n    `)\n    expect(compileScoped(`:where(.foo :deep(.bar)) { color: red; }`))\n      .toMatchInlineSnapshot(`\n      \":where(.foo[data-v-test] .bar) { color: red;\n      }\"\n    `)\n    expect(compileScoped(`:deep(.foo) { color: red; .bar { color: red; } }`))\n      .toMatchInlineSnapshot(`\n      \"[data-v-test] .foo { color: red;\n      .bar { color: red;\n      }\n      }\"\n    `)\n  })\n\n  test('::v-slotted', () => {\n    expect(compileScoped(`:slotted(.foo) { color: red; }`))\n      .toMatchInlineSnapshot(`\n    \".foo[data-v-test-s] { color: red;\n    }\"\n  `)\n    expect(compileScoped(`::v-slotted(.foo) { color: red; }`))\n      .toMatchInlineSnapshot(`\n      \".foo[data-v-test-s] { color: red;\n      }\"\n    `)\n    expect(compileScoped(`::v-slotted(.foo .bar) { color: red; }`))\n      .toMatchInlineSnapshot(`\n      \".foo .bar[data-v-test-s] { color: red;\n      }\"\n    `)\n    expect(compileScoped(`.baz .qux ::v-slotted(.foo .bar) { color: red; }`))\n      .toMatchInlineSnapshot(`\n      \".baz .qux .foo .bar[data-v-test-s] { color: red;\n      }\"\n    `)\n  })\n\n  test('::v-global', () => {\n    expect(compileScoped(`:global(.foo) { color: red; }`))\n      .toMatchInlineSnapshot(`\n    \".foo { color: red;\n    }\"\n  `)\n    expect(compileScoped(`::v-global(.foo) { color: red; }`))\n      .toMatchInlineSnapshot(`\n      \".foo { color: red;\n      }\"\n    `)\n    expect(compileScoped(`::v-global(.foo .bar) { color: red; }`))\n      .toMatchInlineSnapshot(`\n      \".foo .bar { color: red;\n      }\"\n    `)\n    // global ignores anything before it\n    expect(compileScoped(`.baz .qux ::v-global(.foo .bar) { color: red; }`))\n      .toMatchInlineSnapshot(`\n      \".foo .bar { color: red;\n      }\"\n    `)\n  })\n\n  test(':is() and :where() with multiple selectors', () => {\n    expect(compileScoped(`:is(.foo) { color: red; }`)).toMatchInlineSnapshot(`\n      \":is(.foo[data-v-test]) { color: red;\n      }\"\n    `)\n    expect(compileScoped(`:where(.foo, .bar) { color: red; }`))\n      .toMatchInlineSnapshot(`\n      \":where(.foo[data-v-test], .bar[data-v-test]) { color: red;\n      }\"\n    `)\n    expect(compileScoped(`:is(.foo, .bar) div { color: red; }`))\n      .toMatchInlineSnapshot(`\n      \":is(.foo, .bar) div[data-v-test] { color: red;\n      }\"\n    `)\n  })\n\n  // #10511\n  test(':is() and :where() in compound selectors', () => {\n    expect(\n      compileScoped(`.div { color: red; } .div:where(:hover) { color: blue; }`),\n    ).toMatchInlineSnapshot(`\n      \".div[data-v-test] { color: red;\n      }\n      .div[data-v-test]:where(:hover) { color: blue;\n      }\"\n    `)\n\n    expect(\n      compileScoped(`.div { color: red; } .div:is(:hover) { color: blue; }`),\n    ).toMatchInlineSnapshot(`\n      \".div[data-v-test] { color: red;\n      }\n      .div[data-v-test]:is(:hover) { color: blue;\n      }\"\n    `)\n\n    expect(\n      compileScoped(\n        `.div { color: red; } .div:where(.foo:hover) { color: blue; }`,\n      ),\n    ).toMatchInlineSnapshot(`\n      \".div[data-v-test] { color: red;\n      }\n      .div[data-v-test]:where(.foo:hover) { color: blue;\n      }\"\n    `)\n\n    expect(\n      compileScoped(\n        `.div { color: red; } .div:is(.foo:hover) { color: blue; }`,\n      ),\n    ).toMatchInlineSnapshot(`\n      \".div[data-v-test] { color: red;\n      }\n      .div[data-v-test]:is(.foo:hover) { color: blue;\n      }\"\n    `)\n  })\n\n  test('media query', () => {\n    expect(compileScoped(`@media print { .foo { color: red }}`))\n      .toMatchInlineSnapshot(`\n      \"@media print {\n      .foo[data-v-test] { color: red\n      }}\"\n    `)\n  })\n\n  test('supports query', () => {\n    expect(compileScoped(`@supports(display: grid) { .foo { display: grid }}`))\n      .toMatchInlineSnapshot(`\n      \"@supports(display: grid) {\n      .foo[data-v-test] { display: grid\n      }}\"\n    `)\n  })\n\n  test('scoped keyframes', () => {\n    const style = compileScoped(\n      `\n.anim {\n  animation: color 5s infinite, other 5s;\n}\n.anim-2 {\n  animation-name: color;\n  animation-duration: 5s;\n}\n.anim-3 {\n  animation: 5s color infinite, 5s other;\n}\n.anim-multiple {\n  animation: color 5s infinite, opacity 2s;\n}\n.anim-multiple-2 {\n  animation-name: color, opacity;\n  animation-duration: 5s, 2s;\n}\n\n@keyframes color {\n  from { color: red; }\n  to { color: green; }\n}\n@-webkit-keyframes color {\n  from { color: red; }\n  to { color: green; }\n}\n@keyframes opacity {\n  from { opacity: 0; }\n  to { opacity: 1; }\n}\n@-webkit-keyframes opacity {\n  from { opacity: 0; }\n  to { opacity: 1; }\n}\n    `,\n      { id: 'data-v-test' },\n    )\n\n    expect(style).toContain(\n      `.anim[data-v-test] {\\n  animation: color-test 5s infinite, other 5s;`,\n    )\n    expect(style).toContain(\n      `.anim-2[data-v-test] {\\n  animation-name: color-test`,\n    )\n    expect(style).toContain(\n      `.anim-3[data-v-test] {\\n  animation: 5s color-test infinite, 5s other;`,\n    )\n    expect(style).toContain(`@keyframes color-test {`)\n    expect(style).toContain(`@-webkit-keyframes color-test {`)\n\n    expect(style).toContain(\n      `.anim-multiple[data-v-test] {\\n  animation: color-test 5s infinite,opacity-test 2s;`,\n    )\n    expect(style).toContain(\n      `.anim-multiple-2[data-v-test] {\\n  animation-name: color-test,opacity-test;`,\n    )\n    expect(style).toContain(`@keyframes opacity-test {\\nfrom { opacity: 0;`)\n    expect(style).toContain(\n      `@-webkit-keyframes opacity-test {\\nfrom { opacity: 0;`,\n    )\n  })\n\n  // vue-loader/#1370\n  test('spaces after selector', () => {\n    expect(compileScoped(`.foo , .bar { color: red; }`)).toMatchInlineSnapshot(`\n      \".foo[data-v-test], .bar[data-v-test] { color: red;\n      }\"\n    `)\n  })\n\n  describe('deprecated syntax', () => {\n    test('::v-deep as combinator', () => {\n      expect(compileScoped(`::v-deep .foo { color: red; }`))\n        .toMatchInlineSnapshot(`\n        \"[data-v-test] .foo { color: red;\n        }\"\n      `)\n      expect(compileScoped(`.bar ::v-deep .foo { color: red; }`))\n        .toMatchInlineSnapshot(`\n        \".bar[data-v-test] .foo { color: red;\n        }\"\n      `)\n      expect(\n        `::v-deep usage as a combinator has been deprecated.`,\n      ).toHaveBeenWarned()\n    })\n\n    test('>>> (deprecated syntax)', () => {\n      const code = compileScoped(`>>> .foo { color: red; }`)\n      expect(code).toMatchInlineSnapshot(`\n        \"[data-v-test] .foo { color: red;\n        }\"\n      `)\n      expect(\n        `the >>> and /deep/ combinators have been deprecated.`,\n      ).toHaveBeenWarned()\n    })\n\n    test('/deep/ (deprecated syntax)', () => {\n      const code = compileScoped(`/deep/ .foo { color: red; }`)\n      expect(code).toMatchInlineSnapshot(`\n        \"[data-v-test] .foo { color: red;\n        }\"\n      `)\n      expect(\n        `the >>> and /deep/ combinators have been deprecated.`,\n      ).toHaveBeenWarned()\n    })\n  })\n})\n\ndescribe('SFC CSS modules', () => {\n  test('should include resulting classes object in result', async () => {\n    const result = await compileStyleAsync({\n      source: `.red { color: red }\\n.green { color: green }\\n:global(.blue) { color: blue }`,\n      filename: `test.css`,\n      id: 'test',\n      modules: true,\n    })\n    expect(result.modules).toBeDefined()\n    expect(result.modules!.red).toMatch('_red_')\n    expect(result.modules!.green).toMatch('_green_')\n    expect(result.modules!.blue).toBeUndefined()\n  })\n\n  test('postcss-modules options', async () => {\n    const result = await compileStyleAsync({\n      source: `:local(.foo-bar) { color: red }\\n.baz-qux { color: green }`,\n      filename: `test.css`,\n      id: 'test',\n      modules: true,\n      modulesOptions: {\n        scopeBehaviour: 'global',\n        generateScopedName: `[name]__[local]__[hash:base64:5]`,\n        localsConvention: 'camelCaseOnly',\n      },\n    })\n    expect(result.modules).toBeDefined()\n    expect(result.modules!.fooBar).toMatch('__foo-bar__')\n    expect(result.modules!.bazQux).toBeUndefined()\n  })\n})\n\ndescribe('SFC style preprocessors', () => {\n  test('scss @import', () => {\n    const res = compileStyle({\n      source: `\n        @import \"./import.scss\";\n      `,\n      filename: path.resolve(__dirname, './fixture/test.scss'),\n      id: '',\n      preprocessLang: 'scss',\n    })\n\n    expect([...res.dependencies]).toStrictEqual([\n      path.join(__dirname, './fixture/import.scss'),\n    ])\n  })\n\n  test('scss respect user-defined string options.additionalData', () => {\n    const res = compileStyle({\n      preprocessOptions: {\n        additionalData: `\n          @mixin square($size) {\n            width: $size;\n            height: $size;\n          }`,\n      },\n      source: `\n        .square {\n          @include square(100px);\n        }\n      `,\n      filename: path.resolve(__dirname, './fixture/test.scss'),\n      id: '',\n      preprocessLang: 'scss',\n    })\n\n    expect(res.errors.length).toBe(0)\n  })\n\n  test('scss respect user-defined function options.additionalData', () => {\n    const source = `\n        .square {\n          @include square(100px);\n        }\n      `\n    const filename = path.resolve(__dirname, './fixture/test.scss')\n    const res = compileStyle({\n      preprocessOptions: {\n        additionalData: (s: string, f: string) => {\n          expect(s).toBe(source)\n          expect(f).toBe(filename)\n          return `\n          @mixin square($size) {\n            width: $size;\n            height: $size;\n          }`\n        },\n      },\n      source,\n      filename,\n      id: '',\n      preprocessLang: 'scss',\n    })\n\n    expect(res.errors.length).toBe(0)\n  })\n\n  test('should mount scope on correct selector when have universal selector', () => {\n    expect(compileScoped(`* { color: red; }`)).toMatchInlineSnapshot(`\n      \"[data-v-test] { color: red;\n      }\"\n    `)\n    expect(compileScoped('* .foo { color: red; }')).toMatchInlineSnapshot(`\n      \".foo[data-v-test] { color: red;\n      }\"\n    `)\n    expect(compileScoped(`*.foo { color: red; }`)).toMatchInlineSnapshot(`\n      \".foo[data-v-test] { color: red;\n      }\"\n    `)\n    expect(compileScoped(`.foo * { color: red; }`)).toMatchInlineSnapshot(`\n      \".foo[data-v-test] * { color: red;\n      }\"\n    `)\n  })\n})\n"
  },
  {
    "path": "packages/compiler-sfc/__tests__/compileTemplate.spec.ts",
    "content": "import { type RawSourceMap, SourceMapConsumer } from 'source-map-js'\nimport { parse as babelParse } from '@babel/parser'\nimport {\n  type SFCTemplateCompileOptions,\n  compileTemplate,\n} from '../src/compileTemplate'\nimport { type SFCTemplateBlock, parse } from '../src/parse'\nimport { compileScript } from '../src'\nimport { getPositionInCode } from './utils'\n\nfunction compile(opts: Omit<SFCTemplateCompileOptions, 'id'>) {\n  return compileTemplate({\n    ...opts,\n    id: '',\n  })\n}\n\ntest('should work', () => {\n  const source = `<div><p>{{ render }}</p></div>`\n\n  const result = compile({ filename: 'example.vue', source })\n\n  expect(result.errors.length).toBe(0)\n  expect(result.source).toBe(source)\n  // should expose render fn\n  expect(result.code).toMatch(`export function render(`)\n})\n\n// #6807\ntest('should work with style comment', () => {\n  const source = `\n  <div style=\"\n    /* nothing */\n    width: 300px;\n    height: 100px/* nothing */\n    \">{{ render }}</div>\n  `\n\n  const result = compile({ filename: 'example.vue', source })\n  expect(result.errors.length).toBe(0)\n  expect(result.source).toBe(source)\n  expect(result.code).toMatch(`{\"width\":\"300px\",\"height\":\"100px\"}`)\n})\n\ntest('preprocess pug', () => {\n  const template = parse(\n    `\n<template lang=\"pug\">\nbody\n  h1 Pug Examples\n  div.container\n    p Cool Pug example!\n</template>\n`,\n    { filename: 'example.vue', sourceMap: true },\n  ).descriptor.template as SFCTemplateBlock\n\n  const result = compile({\n    filename: 'example.vue',\n    source: template.content,\n    preprocessLang: template.lang,\n  })\n\n  expect(result.errors.length).toBe(0)\n})\n\ntest('preprocess pug with indents and blank lines', () => {\n  const template = parse(\n    `\n<template lang=\"pug\">\n  body\n    h1 The next line contains four spaces.\n\n    div.container\n      p The next line is empty.\n    p This is the last line.\n</template>\n`,\n    { filename: 'example.vue', sourceMap: true },\n  ).descriptor.template as SFCTemplateBlock\n\n  const result = compile({\n    filename: 'example.vue',\n    source: template.content,\n    preprocessLang: template.lang,\n  })\n\n  expect(result.errors.length).toBe(0)\n  expect(result.source).toBe(\n    '<body><h1>The next line contains four spaces.</h1><div class=\"container\"><p>The next line is empty.</p></div><p>This is the last line.</p></body>',\n  )\n})\n\ntest('warn missing preprocessor', () => {\n  const template = parse(`<template lang=\"unknownLang\">hi</template>\\n`, {\n    filename: 'example.vue',\n    sourceMap: true,\n  }).descriptor.template as SFCTemplateBlock\n\n  const result = compile({\n    filename: 'example.vue',\n    source: template.content,\n    preprocessLang: template.lang,\n  })\n\n  expect(result.errors.length).toBe(1)\n})\n\ntest('transform asset url options', () => {\n  const input = { source: `<foo bar=\"~baz\"/>`, filename: 'example.vue' }\n  // Object option\n  const { code: code1 } = compile({\n    ...input,\n    transformAssetUrls: {\n      tags: { foo: ['bar'] },\n    },\n  })\n  expect(code1).toMatch(`import _imports_0 from 'baz'\\n`)\n\n  // legacy object option (direct tags config)\n  const { code: code2 } = compile({\n    ...input,\n    transformAssetUrls: {\n      foo: ['bar'],\n    },\n  })\n  expect(code2).toMatch(`import _imports_0 from 'baz'\\n`)\n\n  // false option\n  const { code: code3 } = compile({\n    ...input,\n    transformAssetUrls: false,\n  })\n  expect(code3).not.toMatch(`import _imports_0 from 'baz'\\n`)\n})\n\ntest('source map', () => {\n  const template = parse(\n    `\n<template>\n  <div><p>{{ foobar }}</p></div>\n</template>\n`,\n    { filename: 'example.vue', sourceMap: true },\n  ).descriptor.template!\n\n  const { code, map } = compile({\n    filename: 'example.vue',\n    source: template.content,\n  })\n\n  expect(map!.sources).toEqual([`example.vue`])\n  expect(map!.sourcesContent).toEqual([template.content])\n\n  const consumer = new SourceMapConsumer(map as RawSourceMap)\n  expect(\n    consumer.originalPositionFor(getPositionInCode(code, 'foobar')),\n  ).toMatchObject(getPositionInCode(template.content, `foobar`))\n})\n\ntest('source map: v-if generated comment should not have original position', () => {\n  const template = parse(\n    `\n      <template>\n        <div v-if=\"true\"></div>\n      </template>\n    `,\n    { filename: 'example.vue', sourceMap: true },\n  ).descriptor.template!\n\n  const { code, map } = compile({\n    filename: 'example.vue',\n    source: template.content,\n  })\n\n  expect(map!.sources).toEqual([`example.vue`])\n  expect(map!.sourcesContent).toEqual([template.content])\n\n  const consumer = new SourceMapConsumer(map as RawSourceMap)\n  const commentNode = code.match(/_createCommentVNode\\(\"v-if\", true\\)/)\n  expect(commentNode).not.toBeNull()\n  const commentPosition = getPositionInCode(code, commentNode![0])\n  const originalPosition = consumer.originalPositionFor(commentPosition)\n  // the comment node should not be mapped to the original source\n  expect(originalPosition.column).toBeNull()\n  expect(originalPosition.line).toBeNull()\n  expect(originalPosition.source).toBeNull()\n})\n\ntest('should work w/ AST from descriptor', () => {\n  const source = `\n  <template>\n    <div><p>{{ foobar }}</p></div>\n  </template>\n  `\n  const template = parse(source, {\n    filename: 'example.vue',\n    sourceMap: true,\n  }).descriptor.template!\n\n  expect(template.ast!.source).toBe(source)\n\n  const { code, map } = compile({\n    filename: 'example.vue',\n    source: template.content,\n    ast: template.ast,\n  })\n\n  expect(map!.sources).toEqual([`example.vue`])\n  // when reusing AST from SFC parse for template compile,\n  // the source corresponds to the entire SFC\n  expect(map!.sourcesContent).toEqual([source])\n\n  const consumer = new SourceMapConsumer(map as RawSourceMap)\n  expect(\n    consumer.originalPositionFor(getPositionInCode(code, 'foobar')),\n  ).toMatchObject(getPositionInCode(source, `foobar`))\n\n  expect(code).toBe(\n    compile({\n      filename: 'example.vue',\n      source: template.content,\n    }).code,\n  )\n})\n\ntest('should work w/ AST from descriptor in SSR mode', () => {\n  const source = `\n  <template>\n    <div><p>{{ foobar }}</p></div>\n  </template>\n  `\n  const template = parse(source, {\n    filename: 'example.vue',\n    sourceMap: true,\n  }).descriptor.template!\n\n  expect(template.ast!.source).toBe(source)\n\n  const { code, map } = compile({\n    filename: 'example.vue',\n    source: '', // make sure it's actually using the AST instead of source\n    ast: template.ast,\n    ssr: true,\n  })\n\n  expect(map!.sources).toEqual([`example.vue`])\n  // when reusing AST from SFC parse for template compile,\n  // the source corresponds to the entire SFC\n  expect(map!.sourcesContent).toEqual([source])\n\n  const consumer = new SourceMapConsumer(map as RawSourceMap)\n  expect(\n    consumer.originalPositionFor(getPositionInCode(code, 'foobar')),\n  ).toMatchObject(getPositionInCode(source, `foobar`))\n\n  expect(code).toBe(\n    compile({\n      filename: 'example.vue',\n      source: template.content,\n      ssr: true,\n    }).code,\n  )\n})\n\ntest('should not reuse AST if using custom compiler', () => {\n  const source = `\n  <template>\n    <div><p>{{ foobar }}</p></div>\n  </template>\n  `\n  const template = parse(source, {\n    filename: 'example.vue',\n    sourceMap: true,\n  }).descriptor.template!\n\n  const { code } = compile({\n    filename: 'example.vue',\n    source: template.content,\n    ast: template.ast,\n    compiler: {\n      parse: () => null as any,\n      // @ts-expect-error\n      compile: input => ({ code: input }),\n    },\n  })\n\n  // what we really want to assert is that the `input` received by the custom\n  // compiler is the source string, not the AST.\n  expect(code).toBe(template.content)\n})\n\ntest('should force re-parse on already transformed AST', () => {\n  const source = `\n  <template>\n    <div><p>{{ foobar }}</p></div>\n  </template>\n  `\n  const template = parse(source, {\n    filename: 'example.vue',\n    sourceMap: true,\n  }).descriptor.template!\n\n  // force set to empty, if this is reused then it won't generate proper code\n  template.ast!.children = []\n  template.ast!.transformed = true\n\n  const { code } = compile({\n    filename: 'example.vue',\n    source: '',\n    ast: template.ast,\n  })\n\n  expect(code).toBe(\n    compile({\n      filename: 'example.vue',\n      source: template.content,\n    }).code,\n  )\n})\n\ntest('should force re-parse with correct compiler in SSR mode', () => {\n  const source = `\n  <template>\n    <div><p>{{ foobar }}</p></div>\n  </template>\n  `\n  const template = parse(source, {\n    filename: 'example.vue',\n    sourceMap: true,\n  }).descriptor.template!\n\n  // force set to empty, if this is reused then it won't generate proper code\n  template.ast!.children = []\n  template.ast!.transformed = true\n\n  const { code } = compile({\n    filename: 'example.vue',\n    source: '',\n    ast: template.ast,\n    ssr: true,\n  })\n\n  expect(code).toBe(\n    compile({\n      filename: 'example.vue',\n      source: template.content,\n      ssr: true,\n    }).code,\n  )\n})\n\ntest('template errors', () => {\n  const result = compile({\n    filename: 'example.vue',\n    source: `<div\n      :bar=\"a[\" v-model=\"baz\"/>`,\n  })\n  expect(result.errors).toMatchSnapshot()\n})\n\ntest('preprocessor errors', () => {\n  const template = parse(\n    `\n<template lang=\"pug\">\n  div(class='class)\n</template>\n`,\n    { filename: 'example.vue', sourceMap: true },\n  ).descriptor.template as SFCTemplateBlock\n\n  const result = compile({\n    filename: 'example.vue',\n    source: template.content,\n    preprocessLang: template.lang,\n  })\n\n  expect(result.errors.length).toBe(1)\n  const message = result.errors[0].toString()\n  expect(message).toMatch(`Error: example.vue:3:1`)\n  expect(message).toMatch(\n    `The end of the string reached with no closing bracket ) found.`,\n  )\n})\n\n// #3447\ntest('should generate the correct imports expression', () => {\n  const { code } = compile({\n    filename: 'example.vue',\n    source: `\n      <img src=\"./foo.svg\"/>\n      <Comp>\n        <img src=\"./bar.svg\"/>\n      </Comp>\n    `,\n    ssr: true,\n  })\n  expect(code).toMatch(`_ssrRenderAttr(\\\"src\\\", _imports_1)`)\n  expect(code).toMatch(`_createVNode(\\\"img\\\", { src: _imports_1 })`)\n})\n\n// #3874\ntest('should not hoist srcset URLs in SSR mode', () => {\n  const { code } = compile({\n    filename: 'example.vue',\n    source: `\n    <picture>\n      <source srcset=\"./img/foo.svg\"/>\n      <img src=\"./img/foo.svg\"/>\n    </picture>\n    <router-link>\n      <picture>\n        <source srcset=\"./img/bar.svg\"/>\n        <img src=\"./img/bar.svg\"/>\n      </picture>\n    </router-link>\n    `,\n    ssr: true,\n  })\n  expect(code).toMatchSnapshot()\n})\n\n// #6742\ntest('dynamic v-on + static v-on should merged', () => {\n  const source = `<input @blur=\"onBlur\" @[validateEvent]=\"onValidateEvent\">`\n\n  const result = compile({ filename: 'example.vue', source })\n\n  expect(result.code).toMatchSnapshot()\n})\n\n// #9853 regression found in Nuxt tests\n// walkIdentifiers can get called multiple times on the same node\n// due to #9729 calling it during SFC template usage check.\n// conditions needed:\n// 1. `<script setup lang=\"ts\">`\n// 2. Has import\n// 3. inlineTemplate: false\n// 4. AST being reused\ntest('prefixing edge case for reused AST', () => {\n  const src = `\n  <script setup lang=\"ts\">\n    import { Foo } from './foo'\n  </script>\n  <template>\n    {{ list.map((t, index) => ({ t: t })) }}\n  </template>\n  `\n  const { descriptor } = parse(src)\n  // compileScript triggers importUsageCheck\n  compileScript(descriptor, { id: 'xxx' })\n  const { code } = compileTemplate({\n    id: 'xxx',\n    filename: 'test.vue',\n    ast: descriptor.template!.ast,\n    source: descriptor.template!.content,\n  })\n  expect(code).not.toMatch(`_ctx.t`)\n})\n\ntest('prefixing edge case for reused AST ssr mode', () => {\n  const src = `\n  <script setup lang=\"ts\">\n    import { Foo } from './foo'\n  </script>\n  <template>\n    <Bar>\n      <template #option=\"{ foo }\"></template>\n    </Bar>\n  </template>\n  `\n  const { descriptor } = parse(src)\n  // compileScript triggers importUsageCheck\n  compileScript(descriptor, { id: 'xxx' })\n  expect(() =>\n    compileTemplate({\n      id: 'xxx',\n      filename: 'test.vue',\n      ast: descriptor.template!.ast,\n      source: descriptor.template!.content,\n      ssr: true,\n    }),\n  ).not.toThrowError()\n})\n\n// #10852\ntest('non-identifier expression in legacy filter syntax', () => {\n  const src = `\n  <template>\n    <div>\n      Today is\n      {{ new Date() | formatDate }}\n    </div>\n  </template>\n  `\n\n  const { descriptor } = parse(src)\n  const compilationResult = compileTemplate({\n    id: 'xxx',\n    filename: 'test.vue',\n    ast: descriptor.template!.ast,\n    source: descriptor.template!.content,\n    ssr: false,\n    compilerOptions: {\n      compatConfig: {\n        MODE: 2,\n      },\n    },\n  })\n\n  expect(() => {\n    babelParse(compilationResult.code, { sourceType: 'module' })\n  }).not.toThrow()\n})\n\ntest('prefixing props edge case in inline mode', () => {\n  const src = `\n  <script setup lang=\"ts\">\n    defineProps<{ Foo: { Bar: unknown } }>()\n  </script>\n  <template>\n    <Foo.Bar/>\n  </template>\n  `\n  const { descriptor } = parse(src)\n  const { content } = compileScript(descriptor, {\n    id: 'xxx',\n    inlineTemplate: true,\n  })\n\n  expect(content).toMatchSnapshot()\n  expect(content).toMatch(`__props[\"Foo\"]).Bar`)\n})\n"
  },
  {
    "path": "packages/compiler-sfc/__tests__/cssVars.spec.ts",
    "content": "import { compileStyle, parse } from '../src'\nimport { assertCode, compileSFCScript, mockId } from './utils'\n\ndescribe('CSS vars injection', () => {\n  test('generating correct code for nested paths', () => {\n    const { content } = compileSFCScript(\n      `<script>const a = 1</script>\\n` +\n        `<style>div{\n          color: v-bind(color);\n          font-size: v-bind('font.size');\n        }</style>`,\n    )\n    expect(content).toMatch(`_useCssVars(_ctx => ({\n  \"${mockId}-color\": (_ctx.color),\n  \"${mockId}-font\\\\.size\": (_ctx.font.size)\n})`)\n    assertCode(content)\n  })\n\n  test('w/ normal <script> binding analysis', () => {\n    const { content } = compileSFCScript(\n      `<script>\n      export default {\n        setup() {\n          return {\n            size: ref('100px')\n          }\n        }\n      }\n      </script>\\n` +\n        `<style>\n          div {\n            font-size: v-bind(size);\n          }\n        </style>`,\n    )\n    expect(content).toMatch(`_useCssVars(_ctx => ({\n  \"${mockId}-size\": (_ctx.size)\n})`)\n    expect(content).toMatch(`import { useCssVars as _useCssVars } from 'vue'`)\n    assertCode(content)\n  })\n\n  test('w/ <script setup> binding analysis', () => {\n    const { content } = compileSFCScript(\n      `<script setup>\n        import { defineProps, ref } from 'vue'\n        const color = 'red'\n        const size = ref('10px')\n        defineProps({\n          foo: String\n        })\n        </script>\\n` +\n        `<style>\n          div {\n            color: v-bind(color);\n            font-size: v-bind(size);\n            border: v-bind(foo);\n          }\n        </style>`,\n    )\n    // should handle:\n    // 1. local const bindings\n    // 2. local potential ref bindings\n    // 3. props bindings (analyzed)\n    expect(content).toMatch(`_useCssVars(_ctx => ({\n  \"${mockId}-color\": (color),\n  \"${mockId}-size\": (size.value),\n  \"${mockId}-foo\": (__props.foo)\n})`)\n    expect(content).toMatch(\n      `import { useCssVars as _useCssVars, unref as _unref } from 'vue'`,\n    )\n    assertCode(content)\n  })\n\n  test('should rewrite CSS vars in compileStyle', () => {\n    const { code } = compileStyle({\n      source: `.foo {\n        color: v-bind(color);\n        font-size: v-bind('font.size');\n\n        font-weight: v-bind(_φ);\n        font-size: v-bind(1-字号);\n        font-family: v-bind(フォント);\n      }`,\n      filename: 'test.css',\n      id: 'data-v-test',\n    })\n    expect(code).toMatchInlineSnapshot(`\n      \".foo {\n              color: var(--test-color);\n              font-size: var(--test-font\\\\.size);\n\n              font-weight: var(--test-_φ);\n              font-size: var(--test-1-字号);\n              font-family: var(--test-フォント);\n      }\"\n    `)\n  })\n\n  test('prod mode', () => {\n    const { content } = compileSFCScript(\n      `<script>const a = 1</script>\\n` +\n        `<style>div{\n          color: v-bind(color);\n          font-size: v-bind('font.size');\n        }</style>`,\n      { isProd: true },\n    )\n    expect(content).toMatch(`_useCssVars(_ctx => ({\n  \"v4003f1a6\": (_ctx.color),\n  \"v41b6490a\": (_ctx.font.size)\n}))}`)\n\n    const { code } = compileStyle({\n      source: `.foo {\n        color: v-bind(color);\n        font-size: v-bind('font.size');\n      }`,\n      filename: 'test.css',\n      id: mockId,\n      isProd: true,\n    })\n    expect(code).toMatchInlineSnapshot(`\n      \".foo {\n              color: var(--v4003f1a6);\n              font-size: var(--v41b6490a);\n      }\"\n    `)\n  })\n\n  describe('codegen', () => {\n    test('<script> w/ no default export', () => {\n      assertCode(\n        compileSFCScript(\n          `<script>const a = 1</script>\\n` +\n            `<style>div{ color: v-bind(color); }</style>`,\n        ).content,\n      )\n    })\n\n    test('<script> w/ default export', () => {\n      assertCode(\n        compileSFCScript(\n          `<script>export default { setup() {} }</script>\\n` +\n            `<style>div{ color: v-bind(color); }</style>`,\n        ).content,\n      )\n    })\n\n    test('<script> w/ default export in strings/comments', () => {\n      assertCode(\n        compileSFCScript(\n          `<script>\n          // export default {}\n          export default {}\n        </script>\\n` + `<style>div{ color: v-bind(color); }</style>`,\n        ).content,\n      )\n    })\n\n    test('w/ <script setup>', () => {\n      assertCode(\n        compileSFCScript(\n          `<script setup>const color = 'red'</script>\\n` +\n            `<style>div{ color: v-bind(color); }</style>`,\n        ).content,\n      )\n    })\n\n    //#4185\n    test('should ignore comments', () => {\n      const { content } = compileSFCScript(\n        `<script setup>const color = 'red';const width = 100</script>\\n` +\n          `<style>\n            /* comment **/\n            div{ /* color: v-bind(color); */ width:20; }\n            div{ width: v-bind(width); }\n            /* comment */\n          </style>`,\n      )\n\n      expect(content).not.toMatch(`\"${mockId}-color\": (color)`)\n      expect(content).toMatch(`\"${mockId}-width\": (width)`)\n      assertCode(content)\n    })\n\n    test('w/ <script setup> using the same var multiple times', () => {\n      const { content } = compileSFCScript(\n        `<script setup>\n        const color = 'red'\n        </script>\\n` +\n          `<style>\n          div {\n            color: v-bind(color);\n          }\n          p {\n            color: v-bind(color);\n          }\n        </style>`,\n      )\n      // color should only be injected once, even if it is twice in style\n      expect(content).toMatch(`_useCssVars(_ctx => ({\n  \"${mockId}-color\": (color)\n})`)\n      assertCode(content)\n    })\n\n    test('should work with w/ complex expression', () => {\n      const { content } = compileSFCScript(\n        `<script setup>\n        let a = 100\n        let b = 200\n        let foo = 300\n        </script>\\n` +\n          `<style>\n          p{\n            width: calc(v-bind(foo) - 3px);\n            height: calc(v-bind('foo') - 3px);\n            top: calc(v-bind(foo + 'px') - 3px);\n          }\n          div {\n            color: v-bind((a + b) / 2 + 'px' );\n          }\n          div {\n            color: v-bind    ((a + b) / 2 + 'px' );\n          }\n          p {\n            color: v-bind(((a + b)) / (2 * a));\n          }\n        </style>`,\n      )\n      expect(content).toMatch(`_useCssVars(_ctx => ({\n  \"${mockId}-foo\": (_unref(foo)),\n  \"${mockId}-foo\\\\ \\\\+\\\\ \\\\'px\\\\'\": (_unref(foo) + 'px'),\n  \"${mockId}-\\\\(a\\\\ \\\\+\\\\ b\\\\)\\\\ \\\\/\\\\ 2\\\\ \\\\+\\\\ \\\\'px\\\\'\": ((_unref(a) + _unref(b)) / 2 + 'px'),\n  \"${mockId}-\\\\(\\\\(a\\\\ \\\\+\\\\ b\\\\)\\\\)\\\\ \\\\/\\\\ \\\\(2\\\\ \\\\*\\\\ a\\\\)\": (((_unref(a) + _unref(b))) / (2 * _unref(a)))\n}))`)\n      assertCode(content)\n    })\n\n    // #6022\n    test('should be able to parse incomplete expressions', () => {\n      const {\n        descriptor: { cssVars },\n      } = parse(\n        `<script setup>let xxx = 1</script>\n        <style scoped>\n        label {\n          font-weight: v-bind(\"count.toString(\");\n          font-weight: v-bind(xxx);\n        }\n        </style>`,\n      )\n      expect(cssVars).toMatchObject([`count.toString(`, `xxx`])\n    })\n\n    // #7759\n    test('It should correctly parse the case where there is no space after the script tag', () => {\n      const { content } = compileSFCScript(\n        `<script setup>import { ref as _ref } from 'vue';\n                let background = _ref('red')\n             </script>\n             <style>\n             label {\n               background: v-bind(background);\n             }\n             </style>`,\n      )\n      expect(content).toMatch(\n        `export default {\\n  setup(__props, { expose: __expose }) {\\n  __expose();\\n\\n_useCssVars(_ctx => ({\\n  \"xxxxxxxx-background\": (_unref(background))\\n}))`,\n      )\n    })\n\n    describe('skip codegen in SSR', () => {\n      test('script setup, inline', () => {\n        const { content } = compileSFCScript(\n          `<script setup>\n          let size = 1\n          </script>\\n` +\n            `<style>\n              div {\n                font-size: v-bind(size);\n              }\n            </style>`,\n          {\n            inlineTemplate: true,\n            templateOptions: {\n              ssr: true,\n            },\n          },\n        )\n        expect(content).not.toMatch(`_useCssVars`)\n      })\n\n      // #6926\n      test('script, non-inline', () => {\n        const { content } = compileSFCScript(\n          `<script setup>\n          let size = 1\n          </script>\\n` +\n            `<style>\n              div {\n                font-size: v-bind(size);\n              }\n            </style>`,\n          {\n            inlineTemplate: false,\n            templateOptions: {\n              ssr: true,\n            },\n          },\n        )\n        expect(content).not.toMatch(`_useCssVars`)\n      })\n\n      test('normal script', () => {\n        const { content } = compileSFCScript(\n          `<script>\n          export default {\n            setup() {\n              return {\n                size: ref('100px')\n              }\n            }\n          }\n          </script>\\n` +\n            `<style>\n              div {\n                font-size: v-bind(size);\n              }\n            </style>`,\n          {\n            templateOptions: {\n              ssr: true,\n            },\n          },\n        )\n        expect(content).not.toMatch(`_useCssVars`)\n      })\n    })\n  })\n})\n"
  },
  {
    "path": "packages/compiler-sfc/__tests__/fixture/import.scss",
    "content": "div {\n  color: red;\n}\n"
  },
  {
    "path": "packages/compiler-sfc/__tests__/parse.spec.ts",
    "content": "import { parse } from '../src'\nimport {\n  ElementTypes,\n  NodeTypes,\n  baseCompile,\n  createRoot,\n} from '@vue/compiler-core'\nimport { SourceMapConsumer } from 'source-map-js'\n\ndescribe('compiler:sfc', () => {\n  describe('source map', () => {\n    test('style block', () => {\n      // Padding determines how many blank lines will there be before the style block\n      const padding = Math.round(Math.random() * 10)\n      const src =\n        `${'\\n'.repeat(padding)}` +\n        `<style>\n.css {\ncolor: red;\n}\n</style>\n\n<style module>\n.css-module {\ncolor: red;\n}\n</style>\n\n<style scoped>\n.css-scoped {\ncolor: red;\n}\n</style>\n\n<style scoped>\n.css-scoped-nested {\ncolor: red;\n.dummy {\ncolor: green;\n}\nfont-weight: bold;\n}\n</style>`\n      const {\n        descriptor: { styles },\n      } = parse(src)\n\n      expect(styles[0].map).not.toBeUndefined()\n      const consumer = new SourceMapConsumer(styles[0].map!)\n      const lineOffset =\n        src.slice(0, src.indexOf(`<style>`)).split('\\n').length - 1\n      consumer.eachMapping(mapping => {\n        expect(mapping.generatedLine + lineOffset).toBe(mapping.originalLine)\n      })\n\n      expect(styles[1].map).not.toBeUndefined()\n      const consumer1 = new SourceMapConsumer(styles[1].map!)\n      const lineOffset1 =\n        src.slice(0, src.indexOf(`<style module>`)).split('\\n').length - 1\n      consumer1.eachMapping(mapping => {\n        expect(mapping.generatedLine + lineOffset1).toBe(mapping.originalLine)\n      })\n\n      expect(styles[2].map).not.toBeUndefined()\n      const consumer2 = new SourceMapConsumer(styles[2].map!)\n      const lineOffset2 =\n        src.slice(0, src.indexOf(`<style scoped>`)).split('\\n').length - 1\n      consumer2.eachMapping(mapping => {\n        expect(mapping.generatedLine + lineOffset2).toBe(mapping.originalLine)\n      })\n    })\n\n    test('script block', () => {\n      // Padding determines how many blank lines will there be before the style block\n      const padding = Math.round(Math.random() * 10)\n      const script = parse(\n        `${'\\n'.repeat(padding)}<script>\\nconsole.log(1)\\n }\\n</script>\\n`,\n      ).descriptor.script\n\n      expect(script!.map).not.toBeUndefined()\n\n      const consumer = new SourceMapConsumer(script!.map!)\n      consumer.eachMapping(mapping => {\n        expect(mapping.originalLine! - mapping.generatedLine).toBe(padding)\n      })\n    })\n\n    test('template block with lang + indent', () => {\n      // Padding determines how many blank lines will there be before the style block\n      const padding = Math.round(Math.random() * 10)\n      const template = parse(\n        `${'\\n'.repeat(padding)}<template lang=\"pug\">\n  h1 foo\n    div bar\n    span baz\n</template>\\n`,\n      ).descriptor.template!\n\n      expect(template.map).not.toBeUndefined()\n\n      const consumer = new SourceMapConsumer(template.map!)\n      consumer.eachMapping(mapping => {\n        expect(mapping.originalLine! - mapping.generatedLine).toBe(padding)\n        expect(mapping.originalColumn! - mapping.generatedColumn).toBe(2)\n      })\n    })\n\n    test('custom block', () => {\n      const padding = Math.round(Math.random() * 10)\n      const custom = parse(\n        `${'\\n'.repeat(padding)}<i18n>\\n{\\n  \"greeting\": \"hello\"\\n}\\n</i18n>\\n`,\n      ).descriptor.customBlocks[0]\n\n      expect(custom!.map).not.toBeUndefined()\n\n      const consumer = new SourceMapConsumer(custom!.map!)\n      consumer.eachMapping(mapping => {\n        expect(mapping.originalLine! - mapping.generatedLine).toBe(padding)\n      })\n    })\n  })\n\n  test('pad content', () => {\n    const content = `\n<template>\n<div></div>\n</template>\n<script>\nexport default {}\n</script>\n<style>\nh1 { color: red }\n</style>\n<i18n>\n{ \"greeting\": \"hello\" }\n</i18n>\n`\n    const padFalse = parse(content.trim(), { pad: false }).descriptor\n    expect(padFalse.template!.content).toBe('\\n<div></div>\\n')\n    expect(padFalse.script!.content).toBe('\\nexport default {}\\n')\n    expect(padFalse.styles[0].content).toBe('\\nh1 { color: red }\\n')\n    expect(padFalse.customBlocks[0].content).toBe('\\n{ \"greeting\": \"hello\" }\\n')\n\n    const padTrue = parse(content.trim(), { pad: true }).descriptor\n    expect(padTrue.script!.content).toBe(\n      Array(3 + 1).join('//\\n') + '\\nexport default {}\\n',\n    )\n    expect(padTrue.styles[0].content).toBe(\n      Array(6 + 1).join('\\n') + '\\nh1 { color: red }\\n',\n    )\n    expect(padTrue.customBlocks[0].content).toBe(\n      Array(9 + 1).join('\\n') + '\\n{ \"greeting\": \"hello\" }\\n',\n    )\n\n    const padLine = parse(content.trim(), { pad: 'line' }).descriptor\n    expect(padLine.script!.content).toBe(\n      Array(3 + 1).join('//\\n') + '\\nexport default {}\\n',\n    )\n    expect(padLine.styles[0].content).toBe(\n      Array(6 + 1).join('\\n') + '\\nh1 { color: red }\\n',\n    )\n    expect(padLine.customBlocks[0].content).toBe(\n      Array(9 + 1).join('\\n') + '\\n{ \"greeting\": \"hello\" }\\n',\n    )\n\n    const padSpace = parse(content.trim(), { pad: 'space' }).descriptor\n    expect(padSpace.script!.content).toBe(\n      `<template>\\n<div></div>\\n</template>\\n<script>`.replace(/./g, ' ') +\n        '\\nexport default {}\\n',\n    )\n    expect(padSpace.styles[0].content).toBe(\n      `<template>\\n<div></div>\\n</template>\\n<script>\\nexport default {}\\n</script>\\n<style>`.replace(\n        /./g,\n        ' ',\n      ) + '\\nh1 { color: red }\\n',\n    )\n    expect(padSpace.customBlocks[0].content).toBe(\n      `<template>\\n<div></div>\\n</template>\\n<script>\\nexport default {}\\n</script>\\n<style>\\nh1 { color: red }\\n</style>\\n<i18n>`.replace(\n        /./g,\n        ' ',\n      ) + '\\n{ \"greeting\": \"hello\" }\\n',\n    )\n  })\n\n  test('should parse correct range for root level self closing tag', () => {\n    const content = `\\n  <div/>\\n`\n    const { descriptor } = parse(`<template>${content}</template>`)\n    expect(descriptor.template).toBeTruthy()\n    expect(descriptor.template!.content).toBe(content)\n    expect(descriptor.template!.loc).toMatchObject({\n      start: { line: 1, column: 11, offset: 10 },\n      end: {\n        line: 3,\n        column: 1,\n        offset: 10 + content.length,\n      },\n    })\n  })\n\n  test('should parse correct range for blocks with no content (self closing)', () => {\n    const { descriptor } = parse(`<template/>`)\n    expect(descriptor.template).toBeTruthy()\n    expect(descriptor.template!.content).toBeFalsy()\n    expect(descriptor.template!.loc).toMatchObject({\n      start: { line: 1, column: 12, offset: 11 },\n      end: { line: 1, column: 12, offset: 11 },\n    })\n  })\n\n  test('should parse correct range for blocks with no content (explicit)', () => {\n    const { descriptor } = parse(`<template></template>`)\n    expect(descriptor.template).toBeTruthy()\n    expect(descriptor.template!.content).toBeFalsy()\n    expect(descriptor.template!.loc).toMatchObject({\n      start: { line: 1, column: 11, offset: 10 },\n      end: { line: 1, column: 11, offset: 10 },\n    })\n  })\n\n  test('should ignore other nodes with no content', () => {\n    expect(parse(`<script/>`).descriptor.script).toBe(null)\n    expect(parse(`<script> \\n\\t  </script>`).descriptor.script).toBe(null)\n    expect(parse(`<style/>`).descriptor.styles.length).toBe(0)\n    expect(parse(`<style> \\n\\t </style>`).descriptor.styles.length).toBe(0)\n    expect(parse(`<custom/>`).descriptor.customBlocks.length).toBe(0)\n    expect(\n      parse(`<custom> \\n\\t </custom>`).descriptor.customBlocks.length,\n    ).toBe(0)\n  })\n\n  test('handle empty nodes with src attribute', () => {\n    const { descriptor } = parse(`<script src=\"com\"/>`)\n    expect(descriptor.script).toBeTruthy()\n    expect(descriptor.script!.content).toBeFalsy()\n    expect(descriptor.script!.attrs['src']).toBe('com')\n  })\n\n  test('should not expose ast on template node if has src import', () => {\n    const { descriptor } = parse(`<template src=\"./foo.html\"/>`)\n    expect(descriptor.template!.ast).toBeUndefined()\n  })\n\n  test('ignoreEmpty: false', () => {\n    const { descriptor } = parse(\n      `<script></script>\\n<script setup>\\n</script>`,\n      {\n        ignoreEmpty: false,\n      },\n    )\n    expect(descriptor.script).toBeTruthy()\n    expect(descriptor.script!.loc).toMatchObject({\n      start: { line: 1, column: 9, offset: 8 },\n      end: { line: 1, column: 9, offset: 8 },\n    })\n\n    expect(descriptor.scriptSetup).toBeTruthy()\n    expect(descriptor.scriptSetup!.loc).toMatchObject({\n      start: { line: 2, column: 15, offset: 32 },\n      end: { line: 3, column: 1, offset: 33 },\n    })\n  })\n\n  test('nested templates', () => {\n    const content = `\n    <template v-if=\"ok\">ok</template>\n    <div><div></div></div>\n    `\n    const { descriptor } = parse(`<template>${content}</template>`)\n    expect(descriptor.template!.content).toBe(content)\n  })\n\n  test('treat empty lang attribute as the html', () => {\n    const content = `<div><template v-if=\"ok\">ok</template></div>`\n    const { descriptor, errors } = parse(\n      `<template lang=\"\">${content}</template>`,\n    )\n    expect(descriptor.template!.content).toBe(content)\n    expect(errors.length).toBe(0)\n  })\n\n  // #1120\n  test('template with preprocessor lang should be treated as plain text', () => {\n    const content = `p(v-if=\"1 < 2\") test <div/>`\n    const { descriptor, errors } = parse(\n      `<template lang=\"pug\">` + content + `</template>`,\n    )\n    expect(errors.length).toBe(0)\n    expect(descriptor.template!.content).toBe(content)\n    // should not attempt to parse the content\n    expect(descriptor.template!.ast!.children.length).toBe(1)\n  })\n\n  //#2566\n  test('div lang should not be treated as plain text', () => {\n    const { errors } = parse(`\n    <template lang=\"pug\">\n      <div lang=\"\">\n        <div></div>\n      </div>\n    </template>\n    `)\n    expect(errors.length).toBe(0)\n  })\n\n  test('slotted detection', async () => {\n    expect(parse(`<template>hi</template>`).descriptor.slotted).toBe(false)\n    expect(\n      parse(`<template>hi</template><style>h1{color:red;}</style>`).descriptor\n        .slotted,\n    ).toBe(false)\n    expect(\n      parse(\n        `<template>hi</template><style scoped>:slotted(h1){color:red;}</style>`,\n      ).descriptor.slotted,\n    ).toBe(true)\n    expect(\n      parse(\n        `<template>hi</template><style scoped>::v-slotted(h1){color:red;}</style>`,\n      ).descriptor.slotted,\n    ).toBe(true)\n  })\n\n  test('error tolerance', () => {\n    const { errors } = parse(`<template>`)\n    expect(errors.length).toBe(1)\n  })\n\n  test('should parse as DOM by default', () => {\n    const { errors } = parse(`<template><input></template>`)\n    expect(errors.length).toBe(0)\n  })\n\n  test('custom compiler', () => {\n    const { errors } = parse(`<template><input></template>`, {\n      compiler: {\n        parse: (_, options) => {\n          options.onError!(new Error('foo') as any)\n          return createRoot([])\n        },\n        compile: baseCompile,\n      },\n    })\n    expect(errors.length).toBe(2)\n    // error thrown by the custom parse\n    expect(errors[0].message).toBe('foo')\n    // error thrown based on the returned root\n    expect(errors[1].message).toMatch('At least one')\n  })\n\n  test('treat custom blocks as raw text', () => {\n    const { errors, descriptor } = parse(\n      `<template><input></template><foo> <-& </foo>`,\n    )\n    expect(errors.length).toBe(0)\n    expect(descriptor.customBlocks[0].content).toBe(` <-& `)\n  })\n\n  test('should accept parser options', () => {\n    const { errors, descriptor } = parse(`<template><hello/></template>`, {\n      templateParseOptions: {\n        isCustomElement: t => t === 'hello',\n      },\n    })\n    expect(errors.length).toBe(0)\n    expect(descriptor.template!.ast!.children[0]).toMatchObject({\n      type: NodeTypes.ELEMENT,\n      tag: 'hello',\n      tagType: ElementTypes.ELEMENT,\n    })\n\n    // test cache invalidation on different options\n    const { descriptor: d2 } = parse(`<template><hello/></template>`, {\n      templateParseOptions: {\n        isCustomElement: t => t !== 'hello',\n      },\n    })\n    expect(d2.template!.ast!.children[0]).toMatchObject({\n      type: NodeTypes.ELEMENT,\n      tag: 'hello',\n      tagType: ElementTypes.COMPONENT,\n    })\n  })\n\n  describe('warnings', () => {\n    function assertWarning(errors: Error[], msg: string) {\n      expect(errors.some(e => e.message.match(msg))).toBe(true)\n    }\n\n    test('should only allow single template element', () => {\n      assertWarning(\n        parse(`<template><div/></template><template><div/></template>`).errors,\n        `Single file component can contain only one <template> element`,\n      )\n    })\n\n    test('should only allow single script element', () => {\n      assertWarning(\n        parse(`<script>console.log(1)</script><script>console.log(1)</script>`)\n          .errors,\n        `Single file component can contain only one <script> element`,\n      )\n    })\n\n    test('should only allow single script setup element', () => {\n      assertWarning(\n        parse(\n          `<script setup>console.log(1)</script><script setup>console.log(1)</script>`,\n        ).errors,\n        `Single file component can contain only one <script setup> element`,\n      )\n    })\n\n    test('should not warn script & script setup', () => {\n      expect(\n        parse(\n          `<script setup>console.log(1)</script><script>console.log(1)</script>`,\n        ).errors.length,\n      ).toBe(0)\n    })\n\n    // # 6676\n    test('should throw error if no <template> or <script> is present', () => {\n      assertWarning(\n        parse(`import { ref } from 'vue'`).errors,\n        `At least one <template> or <script> is required in a single file component`,\n      )\n    })\n\n    test('should throw error if template functional is given', () => {\n      assertWarning(\n        parse(`<template functional></template>`).errors,\n        `<template functional> is no longer supported in Vue 3, since ` +\n          `functional components no longer have significant performance ` +\n          `difference from stateful ones. Just use a normal <template> ` +\n          `instead.`,\n      )\n    })\n  })\n})\n"
  },
  {
    "path": "packages/compiler-sfc/__tests__/rewriteDefault.spec.ts",
    "content": "import { rewriteDefault } from '../src'\n\ndescribe('compiler sfc: rewriteDefault', () => {\n  test('without export default', () => {\n    expect(rewriteDefault(`export const a = {}`, 'script'))\n      .toMatchInlineSnapshot(`\n      \"export const a = {}\n      const script = {}\"\n    `)\n  })\n\n  test('rewrite export default', () => {\n    expect(\n      rewriteDefault(`export  default {}`, 'script'),\n    ).toMatchInlineSnapshot(`\"const script = {}\"`)\n  })\n\n  test('rewrite variable value default', () => {\n    expect(rewriteDefault(`export const foo = 'default'`, 'script'))\n      .toMatchInlineSnapshot(`\n      \"export const foo = 'default'\n      const script = {}\"\n    `)\n  })\n\n  test('rewrite export named default', () => {\n    expect(\n      rewriteDefault(\n        `const a = 1 \\n export { a as b, a as default, a as c}`,\n        'script',\n      ),\n    ).toMatchInlineSnapshot(`\n      \"const a = 1 \n       export { a as b,  a as c}\n      const script = a\"\n    `)\n\n    expect(\n      rewriteDefault(\n        `const a = 1 \\n export { a as b, a as default    , a as c}`,\n        'script',\n      ),\n    ).toMatchInlineSnapshot(`\n      \"const a = 1 \n       export { a as b,  a as c}\n      const script = a\"\n    `)\n\n    expect(\n      rewriteDefault(\n        `const a = 1 \\n export { a as b } \\n export { a as default, a as c }`,\n        'script',\n      ),\n    ).toMatchInlineSnapshot(`\n      \"const a = 1 \n       export { a as b } \n       export {  a as c }\n      const script = a\"\n    `)\n  })\n\n  test('w/ comments', async () => {\n    expect(rewriteDefault(`// export default\\nexport default {}`, 'script'))\n      .toMatchInlineSnapshot(`\n      \"// export default\n      const script = {}\"\n    `)\n  })\n\n  test('export named default multiline', () => {\n    expect(\n      rewriteDefault(`let App = {}\\n export {\\nApp as default\\n}`, '_sfc_main'),\n    ).toMatchInlineSnapshot(`\n      \"let App = {}\n       export {\n\n      }\n      const _sfc_main = App\"\n    `)\n  })\n\n  test('export named default multiline /w comments', () => {\n    expect(\n      rewriteDefault(\n        `const a = 1 \\n export {\\n a as b,\\n a as default,\\n a as c}\\n` +\n          `// export { myFunction as default }`,\n        'script',\n      ),\n    ).toMatchInlineSnapshot(`\n      \"const a = 1 \n       export {\n       a as b,\n       \n       a as c}\n      // export { myFunction as default }\n      const script = a\"\n    `)\n\n    expect(\n      rewriteDefault(\n        `const a = 1 \\n export {\\n a as b,\\n a as default      ,\\n a as c}\\n` +\n          `// export { myFunction as default }`,\n        'script',\n      ),\n    ).toMatchInlineSnapshot(`\n      \"const a = 1 \n       export {\n       a as b,\n       \n       a as c}\n      // export { myFunction as default }\n      const script = a\"\n    `)\n  })\n\n  test(`export { default } from '...'`, async () => {\n    expect(\n      rewriteDefault(`export { default, foo } from './index.js'`, 'script'),\n    ).toMatchInlineSnapshot(`\n      \"import { default as __VUE_DEFAULT__ } from './index.js'\n      export {  foo } from './index.js'\n      const script = __VUE_DEFAULT__\"\n    `)\n\n    expect(\n      rewriteDefault(`export { default    , foo } from './index.js'`, 'script'),\n    ).toMatchInlineSnapshot(`\n      \"import { default as __VUE_DEFAULT__ } from './index.js'\n      export {  foo } from './index.js'\n      const script = __VUE_DEFAULT__\"\n    `)\n\n    expect(\n      rewriteDefault(`export { foo,   default } from './index.js'`, 'script'),\n    ).toMatchInlineSnapshot(`\n      \"import { default as __VUE_DEFAULT__ } from './index.js'\n      export { foo,    } from './index.js'\n      const script = __VUE_DEFAULT__\"\n    `)\n\n    expect(\n      rewriteDefault(\n        `export { foo as default, bar } from './index.js'`,\n        'script',\n      ),\n    ).toMatchInlineSnapshot(`\n      \"import { foo as __VUE_DEFAULT__ } from './index.js'\n      export {  bar } from './index.js'\n      const script = __VUE_DEFAULT__\"\n    `)\n\n    expect(\n      rewriteDefault(\n        `export { foo as default     , bar } from './index.js'`,\n        'script',\n      ),\n    ).toMatchInlineSnapshot(`\n      \"import { foo as __VUE_DEFAULT__ } from './index.js'\n      export {  bar } from './index.js'\n      const script = __VUE_DEFAULT__\"\n    `)\n\n    expect(\n      rewriteDefault(\n        `export { bar,   foo as default } from './index.js'`,\n        'script',\n      ),\n    ).toMatchInlineSnapshot(`\n      \"import { foo as __VUE_DEFAULT__ } from './index.js'\n      export { bar,    } from './index.js'\n      const script = __VUE_DEFAULT__\"\n    `)\n\n    expect(\n      rewriteDefault(\n        `export { foo as default } from './index.js' \\n const foo = 1`,\n        'script',\n      ),\n    ).toMatchInlineSnapshot(`\n      \"import { foo as __VUE_DEFAULT__ } from './index.js'\n      export {  } from './index.js' \n       const foo = 1\n      const script = __VUE_DEFAULT__\"\n    `)\n\n    expect(\n      rewriteDefault(\n        `const a = 1 \\nexport { a as default } from 'xxx'`,\n        'script',\n      ),\n    ).toMatchInlineSnapshot(`\n      \"import { a as __VUE_DEFAULT__ } from 'xxx'\n      const a = 1 \n      export {  } from 'xxx'\n      const script = __VUE_DEFAULT__\"\n    `)\n  })\n\n  test('export default class', async () => {\n    expect(rewriteDefault(`export default class Foo {}`, 'script'))\n      .toMatchInlineSnapshot(`\n        \" class Foo {}\n        const script = Foo\"\n      `)\n  })\n\n  test('export default class w/ comments', async () => {\n    expect(\n      rewriteDefault(\n        `// export default\\nexport default class Foo {}`,\n        'script',\n      ),\n    ).toMatchInlineSnapshot(`\n      \"// export default\n       class Foo {}\n      const script = Foo\"\n    `)\n  })\n\n  test('export default class w/ comments 2', async () => {\n    expect(\n      rewriteDefault(\n        `export default {}\\n` + `// export default class Foo {}`,\n        'script',\n      ),\n    ).toMatchInlineSnapshot(`\n      \"const script = {}\n      // export default class Foo {}\"\n    `)\n  })\n\n  test('export default class w/ comments 3', async () => {\n    expect(\n      rewriteDefault(\n        `/*\\nexport default class Foo {}*/\\n` + `export default class Bar {}`,\n        'script',\n      ),\n    ).toMatchInlineSnapshot(`\n      \"/*\n      export default class Foo {}*/\n       class Bar {}\n      const script = Bar\"\n    `)\n  })\n\n  test('@Component\\nexport default class', async () => {\n    expect(\n      rewriteDefault(`@Component\\nexport default class Foo {}`, 'script', [\n        'decorators-legacy',\n      ]),\n    ).toMatchInlineSnapshot(`\n      \"@Component class Foo {}\n      const script = Foo\"\n    `)\n  })\n\n  test('@Component\\nexport default class w/ comments', async () => {\n    expect(\n      rewriteDefault(\n        `// export default\\n@Component\\nexport default class Foo {}`,\n        'script',\n        ['decorators-legacy'],\n      ),\n    ).toMatchInlineSnapshot(`\n      \"// export default\n      @Component class Foo {}\n      const script = Foo\"\n    `)\n  })\n\n  test('@Component\\nexport default class w/ comments 2', async () => {\n    expect(\n      rewriteDefault(\n        `export default {}\\n` + `// @Component\\n// export default class Foo {}`,\n        'script',\n      ),\n    ).toMatchInlineSnapshot(`\n      \"const script = {}\n      // @Component\n      // export default class Foo {}\"\n    `)\n  })\n\n  test('@Component\\nexport default class w/ comments 3', async () => {\n    expect(\n      rewriteDefault(\n        `/*\\n@Component\\nexport default class Foo {}*/\\n` +\n          `export default class Bar {}`,\n        'script',\n      ),\n    ).toMatchInlineSnapshot(`\n      \"/*\n      @Component\n      export default class Foo {}*/\n       class Bar {}\n      const script = Bar\"\n    `)\n  })\n})\n"
  },
  {
    "path": "packages/compiler-sfc/__tests__/templateTransformAssetUrl.spec.ts",
    "content": "import {\n  type TransformOptions,\n  baseParse,\n  generate,\n  transform,\n} from '@vue/compiler-core'\nimport {\n  type AssetURLOptions,\n  createAssetUrlTransformWithOptions,\n  normalizeOptions,\n  transformAssetUrl,\n} from '../src/template/transformAssetUrl'\nimport { transformElement } from '../../compiler-core/src/transforms/transformElement'\nimport { transformBind } from '../../compiler-core/src/transforms/vBind'\nimport { stringifyStatic } from '../../compiler-dom/src/transforms/stringifyStatic'\n\nfunction compileWithAssetUrls(\n  template: string,\n  options?: AssetURLOptions,\n  transformOptions?: TransformOptions,\n) {\n  const ast = baseParse(template)\n  const t = options\n    ? createAssetUrlTransformWithOptions(normalizeOptions(options))\n    : transformAssetUrl\n  transform(ast, {\n    nodeTransforms: [t, transformElement],\n    directiveTransforms: {\n      bind: transformBind,\n    },\n    ...transformOptions,\n  })\n  return generate(ast, { mode: 'module' })\n}\n\ndescribe('compiler sfc: transform asset url', () => {\n  test('transform assetUrls', () => {\n    const result = compileWithAssetUrls(`\n\t\t\t<img src=\"./logo.png\"/>\n\t\t\t<img src=\"~fixtures/logo.png\"/>\n\t\t\t<img src=\"~/fixtures/logo.png\"/>\n\t\t\t<img src=\"http://example.com/fixtures/logo.png\"/>\n\t\t\t<img src=\"//example.com/fixtures/logo.png\"/>\n\t\t\t<img src=\"/fixtures/logo.png\"/>\n\t\t\t<img src=\"data:image/png;base64,i\"/>\n\t\t`)\n\n    expect(result.code).toMatchSnapshot()\n  })\n\n  /**\n   * vuejs/component-compiler-utils#22 Support uri fragment in transformed require\n   */\n  test('support uri fragment', () => {\n    const result = compileWithAssetUrls(\n      '<use href=\"~@svg/file.svg#fragment\"></use>' +\n        '<use href=\"~@svg/file.svg#fragment\"></use>',\n      {},\n      {\n        hoistStatic: true,\n      },\n    )\n    expect(result.code).toMatchSnapshot()\n  })\n\n  /**\n   * vuejs/component-compiler-utils#22 Support uri fragment in transformed require\n   */\n  test('support uri is empty', () => {\n    const result = compileWithAssetUrls('<use href=\"~\"></use>')\n\n    expect(result.code).toMatchSnapshot()\n  })\n\n  test('with explicit base', () => {\n    const { code } = compileWithAssetUrls(\n      `<img src=\"./bar.png\"></img>` + // -> /foo/bar.png\n        `<img src=\"bar.png\"></img>` + // -> bar.png (untouched)\n        `<img src=\"~bar.png\"></img>` + // -> still converts to import\n        `<img src=\"@theme/bar.png\"></img>`, // -> still converts to import\n      {\n        base: '/foo',\n      },\n    )\n    expect(code).toMatch(`import _imports_0 from 'bar.png'`)\n    expect(code).toMatch(`import _imports_1 from '@theme/bar.png'`)\n    expect(code).toMatchSnapshot()\n  })\n\n  test('with includeAbsolute: true', () => {\n    const { code } = compileWithAssetUrls(\n      `<img src=\"./bar.png\"/>` +\n        `<img src=\"/bar.png\"/>` +\n        `<img src=\"https://foo.bar/baz.png\"/>` +\n        `<img src=\"//foo.bar/baz.png\"/>`,\n      {\n        includeAbsolute: true,\n      },\n    )\n    expect(code).toMatchSnapshot()\n  })\n\n  // vitejs/vite#298\n  test('should not transform hash fragments', () => {\n    const { code } = compileWithAssetUrls(\n      `<svg viewBox=\"0 0 10 10\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n        <defs>\n          <circle id=\"myCircle\" cx=\"0\" cy=\"0\" r=\"5\" />\n        </defs>\n        <use x=\"5\" y=\"5\" xlink:href=\"#myCircle\" />\n      </svg>`,\n    )\n    // should not remove it\n    expect(code).toMatch(`\"xlink:href\": \"#myCircle\"`)\n  })\n\n  test('should allow for full base URLs, with paths', () => {\n    const { code } = compileWithAssetUrls(`<img src=\"./logo.png\" />`, {\n      base: 'http://localhost:3000/src/',\n    })\n\n    expect(code).toMatchSnapshot()\n  })\n\n  test('should allow for full base URLs, without paths', () => {\n    const { code } = compileWithAssetUrls(`<img src=\"./logo.png\" />`, {\n      base: 'http://localhost:3000',\n    })\n\n    expect(code).toMatchSnapshot()\n  })\n\n  test('should allow for full base URLs, without port', () => {\n    const { code } = compileWithAssetUrls(`<img src=\"./logo.png\" />`, {\n      base: 'http://localhost',\n    })\n\n    expect(code).toMatchSnapshot()\n  })\n\n  test('should allow for full base URLs, without protocol', () => {\n    const { code } = compileWithAssetUrls(`<img src=\"./logo.png\" />`, {\n      base: '//localhost',\n    })\n\n    expect(code).toMatchSnapshot()\n  })\n\n  test('transform with stringify', () => {\n    const { code } = compileWithAssetUrls(\n      `<div>` +\n        `<img src=\"./bar.png\"/>` +\n        `<img src=\"/bar.png\"/>` +\n        `<img src=\"https://foo.bar/baz.png\"/>` +\n        `<img src=\"//foo.bar/baz.png\"/>` +\n        `<img src=\"./bar.png\"/>` +\n        `</div>`,\n      {\n        includeAbsolute: true,\n      },\n      {\n        hoistStatic: true,\n        transformHoist: stringifyStatic,\n      },\n    )\n    expect(code).toMatch(`_createStaticVNode`)\n    expect(code).toMatchSnapshot()\n  })\n\n  test('transform with stringify with space in absolute filename', () => {\n    const { code } = compileWithAssetUrls(\n      `<div><img src=\"/foo bar.png\"/></div>`,\n      {\n        includeAbsolute: true,\n      },\n      {\n        hoistStatic: true,\n        transformHoist: stringifyStatic,\n      },\n    )\n    expect(code).toMatch(`_createElementVNode`)\n    expect(code).toContain(`import _imports_0 from '/foo bar.png'`)\n  })\n\n  test('transform with stringify with space in relative filename', () => {\n    const { code } = compileWithAssetUrls(\n      `<div><img src=\"./foo bar.png\"/></div>`,\n      {\n        includeAbsolute: true,\n      },\n      {\n        hoistStatic: true,\n        transformHoist: stringifyStatic,\n      },\n    )\n    expect(code).toMatch(`_createElementVNode`)\n    expect(code).toContain(`import _imports_0 from './foo bar.png'`)\n  })\n})\n"
  },
  {
    "path": "packages/compiler-sfc/__tests__/templateTransformSrcset.spec.ts",
    "content": "import {\n  type TransformOptions,\n  baseParse,\n  generate,\n  transform,\n} from '@vue/compiler-core'\nimport {\n  createSrcsetTransformWithOptions,\n  transformSrcset,\n} from '../src/template/transformSrcset'\nimport { transformElement } from '../../compiler-core/src/transforms/transformElement'\nimport { transformBind } from '../../compiler-core/src/transforms/vBind'\nimport {\n  type AssetURLOptions,\n  normalizeOptions,\n} from '../src/template/transformAssetUrl'\nimport { stringifyStatic } from '../../compiler-dom/src/transforms/stringifyStatic'\n\nfunction compileWithSrcset(\n  template: string,\n  options?: AssetURLOptions,\n  transformOptions?: TransformOptions,\n) {\n  const ast = baseParse(template)\n  const srcsetTransform = options\n    ? createSrcsetTransformWithOptions(normalizeOptions(options))\n    : transformSrcset\n  transform(ast, {\n    hoistStatic: true,\n    nodeTransforms: [srcsetTransform, transformElement],\n    directiveTransforms: {\n      bind: transformBind,\n    },\n    ...transformOptions,\n  })\n  return generate(ast, { mode: 'module' })\n}\n\nconst src = `\n<img src=\"./logo.png\" srcset=\"\"/>\n<img src=\"./logo.png\" srcset=\"./logo.png\"/>\n<img src=\"./logo.png\" srcset=\"./logo.png 2x\"/>\n<img src=\"./logo.png\" srcset=\"./logo.png 2x\"/>\n<img src=\"./logo.png\" srcset=\"./logo.png, ./logo.png 2x\"/>\n<img src=\"./logo.png\" srcset=\"./logo.png 2x, ./logo.png\"/>\n<img src=\"./logo.png\" srcset=\"./logo.png 2x, ./logo.png 3x\"/>\n<img src=\"./logo.png\" srcset=\"./logo.png, ./logo.png 2x, ./logo.png 3x\"/>\n<img src=\"/logo.png\" srcset=\"/logo.png, /logo.png 2x\"/>\n<img src=\"https://example.com/logo.png\" srcset=\"https://example.com/logo.png, https://example.com/logo.png 2x\"/>\n<img src=\"/logo.png\" srcset=\"/logo.png, ./logo.png 2x\"/>\n<img src=\"data:image/png;base64,i\" srcset=\"data:image/png;base64,i 1x, data:image/png;base64,i 2x\"/>\n`\n\ndescribe('compiler sfc: transform srcset', () => {\n  test('transform srcset', () => {\n    expect(compileWithSrcset(src).code).toMatchSnapshot()\n  })\n\n  test('transform srcset w/ base', () => {\n    expect(\n      compileWithSrcset(src, {\n        base: '/foo',\n      }).code,\n    ).toMatchSnapshot()\n  })\n\n  test('transform srcset w/ includeAbsolute: true', () => {\n    expect(\n      compileWithSrcset(src, {\n        includeAbsolute: true,\n      }).code,\n    ).toMatchSnapshot()\n  })\n\n  test('transform empty srcset w/ includeAbsolute: true', () => {\n    expect(\n      compileWithSrcset(`<img srcset=\" \" />`, {\n        includeAbsolute: true,\n      }).code,\n    ).toMatchSnapshot()\n  })\n\n  test('transform srcset w/ stringify', () => {\n    const code = compileWithSrcset(\n      `<div>${src}</div>`,\n      {\n        includeAbsolute: true,\n      },\n      {\n        hoistStatic: true,\n        transformHoist: stringifyStatic,\n      },\n    ).code\n    expect(code).toMatch(`_createStaticVNode`)\n    expect(code).toMatchSnapshot()\n  })\n\n  test('srcset w/ explicit base option', () => {\n    const code = compileWithSrcset(\n      `\n      <img srcset=\"@/logo.png, @/logo.png 2x\"/>\n      <img srcset=\"@/logo.png 1x, ./logo.png 2x\"/>\n    `,\n      { base: '/foo/' },\n      { hoistStatic: true },\n    ).code\n    expect(code).toMatchSnapshot()\n  })\n})\n"
  },
  {
    "path": "packages/compiler-sfc/__tests__/templateUtils.spec.ts",
    "content": "import {\n  isDataUrl,\n  isExternalUrl,\n  isRelativeUrl,\n} from '../src/template/templateUtils'\n\ndescribe('compiler sfc:templateUtils isRelativeUrl', () => {\n  test('should return true when The first character of the string path is .', () => {\n    const url = './**.vue'\n    const result = isRelativeUrl(url)\n    expect(result).toBe(true)\n  })\n\n  test('should return true when The first character of the string path is ~', () => {\n    const url = '~/xx.vue'\n    const result = isRelativeUrl(url)\n    expect(result).toBe(true)\n  })\n\n  test('should return true when The first character of the string path is @', () => {\n    const url = '@/xx.vue'\n    const result = isRelativeUrl(url)\n    expect(result).toBe(true)\n  })\n})\n\ndescribe('compiler sfc:templateUtils isExternalUrl', () => {\n  test('should return true when String starts with http://', () => {\n    const url = 'http://vuejs.org/'\n    const result = isExternalUrl(url)\n    expect(result).toBe(true)\n  })\n\n  test('should return true when String starts with https://', () => {\n    const url = 'https://vuejs.org/'\n    const result = isExternalUrl(url)\n    expect(result).toBe(true)\n  })\n\n  test('should return true when String starts with //', () => {\n    const url = '//vuejs.org/'\n    const result = isExternalUrl(url)\n    expect(result).toBe(true)\n  })\n})\n\ndescribe('compiler sfc:templateUtils isDataUrl', () => {\n  test('should return true w/ hasn`t media type and encode', () => {\n    expect(isDataUrl('data:,i')).toBe(true)\n  })\n\n  test('should return true w/ media type + encode', () => {\n    expect(isDataUrl('data:image/png;base64,i')).toBe(true)\n  })\n\n  test('should return true w/ media type + hasn`t encode', () => {\n    expect(isDataUrl('data:image/png,i')).toBe(true)\n  })\n})\n"
  },
  {
    "path": "packages/compiler-sfc/__tests__/utils.ts",
    "content": "import {\n  type SFCParseOptions,\n  type SFCScriptBlock,\n  type SFCScriptCompileOptions,\n  compileScript,\n  parse,\n} from '../src'\nimport { parse as babelParse } from '@babel/parser'\n\nexport const mockId = 'xxxxxxxx'\n\nexport function compileSFCScript(\n  src: string,\n  options?: Partial<SFCScriptCompileOptions>,\n  parseOptions?: SFCParseOptions,\n): SFCScriptBlock {\n  const { descriptor, errors } = parse(src, parseOptions)\n  if (errors.length) {\n    console.warn(errors[0])\n  }\n  return compileScript(descriptor, {\n    ...options,\n    id: mockId,\n  })\n}\n\nexport function assertCode(code: string): void {\n  // parse the generated code to make sure it is valid\n  try {\n    babelParse(code, {\n      sourceType: 'module',\n      plugins: [\n        'typescript',\n        ['importAttributes', { deprecatedAssertSyntax: true }],\n      ],\n    })\n  } catch (e: any) {\n    console.log(code)\n    throw e\n  }\n  expect(code).toMatchSnapshot()\n}\n\ninterface Pos {\n  line: number\n  column: number\n  name?: string\n}\n\nexport function getPositionInCode(\n  code: string,\n  token: string,\n  expectName: string | boolean = false,\n): Pos {\n  const generatedOffset = code.indexOf(token)\n  let line = 1\n  let lastNewLinePos = -1\n  for (let i = 0; i < generatedOffset; i++) {\n    if (code.charCodeAt(i) === 10 /* newline char code */) {\n      line++\n      lastNewLinePos = i\n    }\n  }\n  const res: Pos = {\n    line,\n    column:\n      lastNewLinePos === -1\n        ? generatedOffset\n        : generatedOffset - lastNewLinePos - 1,\n  }\n  if (expectName) {\n    res.name = typeof expectName === 'string' ? expectName : token\n  }\n  return res\n}\n"
  },
  {
    "path": "packages/compiler-sfc/package.json",
    "content": "{\n  \"name\": \"@vue/compiler-sfc\",\n  \"version\": \"3.5.30\",\n  \"description\": \"@vue/compiler-sfc\",\n  \"main\": \"dist/compiler-sfc.cjs.js\",\n  \"module\": \"dist/compiler-sfc.esm-browser.js\",\n  \"types\": \"dist/compiler-sfc.d.ts\",\n  \"files\": [\n    \"dist\"\n  ],\n  \"exports\": {\n    \".\": {\n      \"types\": \"./dist/compiler-sfc.d.ts\",\n      \"node\": \"./dist/compiler-sfc.cjs.js\",\n      \"module\": \"./dist/compiler-sfc.esm-browser.js\",\n      \"import\": \"./dist/compiler-sfc.esm-browser.js\",\n      \"require\": \"./dist/compiler-sfc.cjs.js\"\n    },\n    \"./*\": \"./*\"\n  },\n  \"buildOptions\": {\n    \"name\": \"VueCompilerSFC\",\n    \"formats\": [\n      \"cjs\",\n      \"esm-browser\"\n    ],\n    \"prod\": false,\n    \"enableNonBrowserBranches\": true\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/vuejs/core.git\",\n    \"directory\": \"packages/compiler-sfc\"\n  },\n  \"keywords\": [\n    \"vue\"\n  ],\n  \"author\": \"Evan You\",\n  \"license\": \"MIT\",\n  \"bugs\": {\n    \"url\": \"https://github.com/vuejs/core/issues\"\n  },\n  \"homepage\": \"https://github.com/vuejs/core/tree/main/packages/compiler-sfc#readme\",\n  \"dependencies\": {\n    \"@babel/parser\": \"catalog:\",\n    \"@vue/compiler-core\": \"workspace:*\",\n    \"@vue/compiler-dom\": \"workspace:*\",\n    \"@vue/compiler-ssr\": \"workspace:*\",\n    \"@vue/shared\": \"workspace:*\",\n    \"estree-walker\": \"catalog:\",\n    \"magic-string\": \"catalog:\",\n    \"postcss\": \"^8.5.8\",\n    \"source-map-js\": \"catalog:\"\n  },\n  \"devDependencies\": {\n    \"@babel/types\": \"catalog:\",\n    \"@vue/consolidate\": \"^1.0.0\",\n    \"hash-sum\": \"^2.0.0\",\n    \"lru-cache\": \"10.1.0\",\n    \"merge-source-map\": \"^1.1.0\",\n    \"minimatch\": \"~10.2.4\",\n    \"postcss-modules\": \"^6.0.1\",\n    \"postcss-selector-parser\": \"^7.1.1\",\n    \"pug\": \"^3.0.3\",\n    \"sass\": \"^1.97.3\"\n  }\n}\n"
  },
  {
    "path": "packages/compiler-sfc/src/cache.ts",
    "content": "import { LRUCache } from 'lru-cache'\n\nexport function createCache<T extends {}>(\n  max = 500,\n): Map<string, T> | LRUCache<string, T> {\n  /* v8 ignore next 3 */\n  if (__GLOBAL__ || __ESM_BROWSER__) {\n    return new Map<string, T>()\n  }\n  return new LRUCache({ max })\n}\n"
  },
  {
    "path": "packages/compiler-sfc/src/compileScript.ts",
    "content": "import {\n  BindingTypes,\n  UNREF,\n  isFunctionType,\n  unwrapTSNode,\n  walkIdentifiers,\n} from '@vue/compiler-dom'\nimport {\n  DEFAULT_FILENAME,\n  type SFCDescriptor,\n  type SFCScriptBlock,\n} from './parse'\nimport type { ParserPlugin } from '@babel/parser'\nimport { generateCodeFrame } from '@vue/shared'\nimport type {\n  ArrayPattern,\n  CallExpression,\n  Declaration,\n  ExportSpecifier,\n  Identifier,\n  LVal,\n  Node,\n  ObjectPattern,\n  Statement,\n} from '@babel/types'\nimport { walk } from 'estree-walker'\nimport {\n  type RawSourceMap,\n  SourceMapConsumer,\n  SourceMapGenerator,\n} from 'source-map-js'\nimport {\n  normalScriptDefaultVar,\n  processNormalScript,\n} from './script/normalScript'\nimport { CSS_VARS_HELPER, genCssVarsCode } from './style/cssVars'\nimport {\n  type SFCTemplateCompileOptions,\n  compileTemplate,\n} from './compileTemplate'\nimport { warnOnce } from './warn'\nimport { transformDestructuredProps } from './script/definePropsDestructure'\nimport { ScriptCompileContext } from './script/context'\nimport {\n  DEFINE_PROPS,\n  WITH_DEFAULTS,\n  genRuntimeProps,\n  processDefineProps,\n} from './script/defineProps'\nimport {\n  DEFINE_EMITS,\n  genRuntimeEmits,\n  processDefineEmits,\n} from './script/defineEmits'\nimport { DEFINE_EXPOSE, processDefineExpose } from './script/defineExpose'\nimport { DEFINE_OPTIONS, processDefineOptions } from './script/defineOptions'\nimport { DEFINE_SLOTS, processDefineSlots } from './script/defineSlots'\nimport { DEFINE_MODEL, processDefineModel } from './script/defineModel'\nimport {\n  getImportedName,\n  isCallOf,\n  isJS,\n  isLiteralNode,\n  isTS,\n} from './script/utils'\nimport { analyzeScriptBindings } from './script/analyzeScriptBindings'\nimport {\n  isImportUsed,\n  resolveTemplateVModelIdentifiers,\n} from './script/importUsageCheck'\nimport { processAwait } from './script/topLevelAwait'\n\nexport interface SFCScriptCompileOptions {\n  /**\n   * Scope ID for prefixing injected CSS variables.\n   * This must be consistent with the `id` passed to `compileStyle`.\n   */\n  id: string\n  /**\n   * Production mode. Used to determine whether to generate hashed CSS variables\n   */\n  isProd?: boolean\n  /**\n   * Enable/disable source map. Defaults to true.\n   */\n  sourceMap?: boolean\n  /**\n   * https://babeljs.io/docs/en/babel-parser#plugins\n   */\n  babelParserPlugins?: ParserPlugin[]\n  /**\n   * A list of files to parse for global types to be made available for type\n   * resolving in SFC macros. The list must be fully resolved file system paths.\n   */\n  globalTypeFiles?: string[]\n  /**\n   * Compile the template and inline the resulting render function\n   * directly inside setup().\n   * - Only affects `<script setup>`\n   * - This should only be used in production because it prevents the template\n   * from being hot-reloaded separately from component state.\n   */\n  inlineTemplate?: boolean\n  /**\n   * Generate the final component as a variable instead of default export.\n   * This is useful in e.g. @vitejs/plugin-vue where the script needs to be\n   * placed inside the main module.\n   */\n  genDefaultAs?: string\n  /**\n   * Options for template compilation when inlining. Note these are options that\n   * would normally be passed to `compiler-sfc`'s own `compileTemplate()`, not\n   * options passed to `compiler-dom`.\n   */\n  templateOptions?: Partial<SFCTemplateCompileOptions>\n  /**\n   * Hoist <script setup> static constants.\n   * - Only enables when one `<script setup>` exists.\n   * @default true\n   */\n  hoistStatic?: boolean\n  /**\n   * Set to `false` to disable reactive destructure for `defineProps` (pre-3.5\n   * behavior), or set to `'error'` to throw hard error on props destructures.\n   * @default true\n   */\n  propsDestructure?: boolean | 'error'\n  /**\n   * File system access methods to be used when resolving types\n   * imported in SFC macros. Defaults to ts.sys in Node.js, can be overwritten\n   * to use a virtual file system for use in browsers (e.g. in REPLs)\n   */\n  fs?: {\n    fileExists(file: string): boolean\n    readFile(file: string): string | undefined\n    realpath?(file: string): string\n  }\n  /**\n   * Transform Vue SFCs into custom elements.\n   */\n  customElement?: boolean | ((filename: string) => boolean)\n}\n\nexport interface ImportBinding {\n  isType: boolean\n  imported: string\n  local: string\n  source: string\n  isFromSetup: boolean\n  isUsedInTemplate: boolean\n}\n\nconst MACROS = [\n  DEFINE_PROPS,\n  DEFINE_EMITS,\n  DEFINE_EXPOSE,\n  DEFINE_OPTIONS,\n  DEFINE_SLOTS,\n  DEFINE_MODEL,\n  WITH_DEFAULTS,\n]\n\n/**\n * Compile `<script setup>`\n * It requires the whole SFC descriptor because we need to handle and merge\n * normal `<script>` + `<script setup>` if both are present.\n */\nexport function compileScript(\n  sfc: SFCDescriptor,\n  options: SFCScriptCompileOptions,\n): SFCScriptBlock {\n  if (!options.id) {\n    warnOnce(\n      `compileScript now requires passing the \\`id\\` option.\\n` +\n        `Upgrade your vite or vue-loader version for compatibility with ` +\n        `the latest experimental proposals.`,\n    )\n  }\n\n  const { script, scriptSetup, source, filename } = sfc\n  const hoistStatic = options.hoistStatic !== false && !script\n  const scopeId = options.id ? options.id.replace(/^data-v-/, '') : ''\n  const scriptLang = script && script.lang\n  const scriptSetupLang = scriptSetup && scriptSetup.lang\n  const isJSOrTS =\n    isJS(scriptLang, scriptSetupLang) || isTS(scriptLang, scriptSetupLang)\n\n  if (script && scriptSetup && scriptLang !== scriptSetupLang) {\n    throw new Error(\n      `[@vue/compiler-sfc] <script> and <script setup> must have the same ` +\n        `language type.`,\n    )\n  }\n\n  if (!scriptSetup) {\n    if (!script) {\n      throw new Error(`[@vue/compiler-sfc] SFC contains no <script> tags.`)\n    }\n\n    // normal <script> only\n    if (script.lang && !isJSOrTS) {\n      // do not process non js/ts script blocks\n      return script\n    }\n\n    const ctx = new ScriptCompileContext(sfc, options)\n    return processNormalScript(ctx, scopeId)\n  }\n\n  if (scriptSetupLang && !isJSOrTS) {\n    // do not process non js/ts script blocks\n    return scriptSetup\n  }\n\n  const ctx = new ScriptCompileContext(sfc, options)\n\n  // metadata that needs to be returned\n  // const ctx.bindingMetadata: BindingMetadata = {}\n  const scriptBindings: Record<string, BindingTypes> = Object.create(null)\n  const setupBindings: Record<string, BindingTypes> = Object.create(null)\n\n  let defaultExport: Node | undefined\n  let hasAwait = false\n  let hasInlinedSsrRenderFn = false\n\n  // string offsets\n  const startOffset = ctx.startOffset!\n  const endOffset = ctx.endOffset!\n  const scriptStartOffset = script && script.loc.start.offset\n  const scriptEndOffset = script && script.loc.end.offset\n\n  function hoistNode(node: Statement) {\n    const start = node.start! + startOffset\n    let end = node.end! + startOffset\n    // locate comment\n    if (node.trailingComments && node.trailingComments.length > 0) {\n      const lastCommentNode =\n        node.trailingComments[node.trailingComments.length - 1]\n      end = lastCommentNode.end! + startOffset\n    }\n    // locate the end of whitespace between this statement and the next\n    while (end <= source.length) {\n      if (!/\\s/.test(source.charAt(end))) {\n        break\n      }\n      end++\n    }\n    ctx.s.move(start, end, 0)\n  }\n\n  function registerUserImport(\n    source: string,\n    local: string,\n    imported: string,\n    isType: boolean,\n    isFromSetup: boolean,\n    needTemplateUsageCheck: boolean,\n  ) {\n    // template usage check is only needed in non-inline mode, so we can skip\n    // the work if inlineTemplate is true.\n    let isUsedInTemplate = needTemplateUsageCheck\n    if (\n      needTemplateUsageCheck &&\n      ctx.isTS &&\n      sfc.template &&\n      !sfc.template.src &&\n      !sfc.template.lang\n    ) {\n      isUsedInTemplate = isImportUsed(local, sfc)\n    }\n\n    ctx.userImports[local] = {\n      isType,\n      imported,\n      local,\n      source,\n      isFromSetup,\n      isUsedInTemplate,\n    }\n  }\n\n  function checkInvalidScopeReference(node: Node | undefined, method: string) {\n    if (!node) return\n    walkIdentifiers(node, id => {\n      const binding = setupBindings[id.name]\n      if (binding && binding !== BindingTypes.LITERAL_CONST) {\n        ctx.error(\n          `\\`${method}()\\` in <script setup> cannot reference locally ` +\n            `declared variables because it will be hoisted outside of the ` +\n            `setup() function. If your component options require initialization ` +\n            `in the module scope, use a separate normal <script> to export ` +\n            `the options instead.`,\n          id,\n        )\n      }\n    })\n  }\n\n  const scriptAst = ctx.scriptAst\n  const scriptSetupAst = ctx.scriptSetupAst!\n\n  // 1.1 walk import declarations of <script>\n  if (scriptAst) {\n    for (const node of scriptAst.body) {\n      if (node.type === 'ImportDeclaration') {\n        // record imports for dedupe\n        for (const specifier of node.specifiers) {\n          const imported = getImportedName(specifier)\n          registerUserImport(\n            node.source.value,\n            specifier.local.name,\n            imported,\n            node.importKind === 'type' ||\n              (specifier.type === 'ImportSpecifier' &&\n                specifier.importKind === 'type'),\n            false,\n            !options.inlineTemplate,\n          )\n        }\n      }\n    }\n  }\n\n  // 1.2 walk import declarations of <script setup>\n  for (const node of scriptSetupAst.body) {\n    if (node.type === 'ImportDeclaration') {\n      // import declarations are moved to top\n      hoistNode(node)\n\n      // dedupe imports\n      let removed = 0\n      const removeSpecifier = (i: number) => {\n        const removeLeft = i > removed\n        removed++\n        const current = node.specifiers[i]\n        const next = node.specifiers[i + 1]\n        ctx.s.remove(\n          removeLeft\n            ? node.specifiers[i - 1].end! + startOffset\n            : current.start! + startOffset,\n          next && !removeLeft\n            ? next.start! + startOffset\n            : current.end! + startOffset,\n        )\n      }\n\n      for (let i = 0; i < node.specifiers.length; i++) {\n        const specifier = node.specifiers[i]\n        const local = specifier.local.name\n        const imported = getImportedName(specifier)\n        const source = node.source.value\n        const existing = ctx.userImports[local]\n        if (source === 'vue' && MACROS.includes(imported)) {\n          if (local === imported) {\n            warnOnce(\n              `\\`${imported}\\` is a compiler macro and no longer needs to be imported.`,\n            )\n          } else {\n            ctx.error(\n              `\\`${imported}\\` is a compiler macro and cannot be aliased to ` +\n                `a different name.`,\n              specifier,\n            )\n          }\n          removeSpecifier(i)\n        } else if (existing) {\n          if (existing.source === source && existing.imported === imported) {\n            // already imported in <script setup>, dedupe\n            removeSpecifier(i)\n          } else {\n            ctx.error(\n              `different imports aliased to same local name.`,\n              specifier,\n            )\n          }\n        } else {\n          registerUserImport(\n            source,\n            local,\n            imported,\n            node.importKind === 'type' ||\n              (specifier.type === 'ImportSpecifier' &&\n                specifier.importKind === 'type'),\n            true,\n            !options.inlineTemplate,\n          )\n        }\n      }\n      if (node.specifiers.length && removed === node.specifiers.length) {\n        ctx.s.remove(node.start! + startOffset, node.end! + startOffset)\n      }\n    }\n  }\n\n  // 1.3 resolve possible user import alias of `ref` and `reactive`\n  const vueImportAliases: Record<string, string> = {}\n  for (const key in ctx.userImports) {\n    const { source, imported, local } = ctx.userImports[key]\n    if (source === 'vue') vueImportAliases[imported] = local\n  }\n\n  // 2.1 process normal <script> body\n  if (script && scriptAst) {\n    for (const node of scriptAst.body) {\n      if (node.type === 'ExportDefaultDeclaration') {\n        // export default\n        defaultExport = node\n\n        // check if user has manually specified `name` or 'render` option in\n        // export default\n        // if has name, skip name inference\n        // if has render and no template, generate return object instead of\n        // empty render function (#4980)\n        let optionProperties\n        if (defaultExport.declaration.type === 'ObjectExpression') {\n          optionProperties = defaultExport.declaration.properties\n        } else if (\n          defaultExport.declaration.type === 'CallExpression' &&\n          defaultExport.declaration.arguments[0] &&\n          defaultExport.declaration.arguments[0].type === 'ObjectExpression'\n        ) {\n          optionProperties = defaultExport.declaration.arguments[0].properties\n        }\n        if (optionProperties) {\n          for (const p of optionProperties) {\n            if (\n              p.type === 'ObjectProperty' &&\n              p.key.type === 'Identifier' &&\n              p.key.name === 'name'\n            ) {\n              ctx.hasDefaultExportName = true\n            }\n            if (\n              (p.type === 'ObjectMethod' || p.type === 'ObjectProperty') &&\n              p.key.type === 'Identifier' &&\n              p.key.name === 'render'\n            ) {\n              // TODO warn when we provide a better way to do it?\n              ctx.hasDefaultExportRender = true\n            }\n          }\n        }\n\n        // export default { ... } --> const __default__ = { ... }\n        const start = node.start! + scriptStartOffset!\n        const end = node.declaration.start! + scriptStartOffset!\n        ctx.s.overwrite(start, end, `const ${normalScriptDefaultVar} = `)\n      } else if (node.type === 'ExportNamedDeclaration') {\n        const defaultSpecifier = node.specifiers.find(\n          s =>\n            s.exported.type === 'Identifier' && s.exported.name === 'default',\n        ) as ExportSpecifier\n        if (defaultSpecifier) {\n          defaultExport = node\n          // 1. remove specifier\n          if (node.specifiers.length > 1) {\n            ctx.s.remove(\n              defaultSpecifier.start! + scriptStartOffset!,\n              defaultSpecifier.end! + scriptStartOffset!,\n            )\n          } else {\n            ctx.s.remove(\n              node.start! + scriptStartOffset!,\n              node.end! + scriptStartOffset!,\n            )\n          }\n          if (node.source) {\n            // export { x as default } from './x'\n            // rewrite to `import { x as __default__ } from './x'` and\n            // add to top\n            ctx.s.prepend(\n              `import { ${defaultSpecifier.local.name} as ${normalScriptDefaultVar} } from '${node.source.value}'\\n`,\n            )\n          } else {\n            // export { x as default }\n            // rewrite to `const __default__ = x` and move to end\n            ctx.s.appendLeft(\n              scriptEndOffset!,\n              `\\nconst ${normalScriptDefaultVar} = ${defaultSpecifier.local.name}\\n`,\n            )\n          }\n        }\n        if (node.declaration) {\n          walkDeclaration(\n            'script',\n            node.declaration,\n            scriptBindings,\n            vueImportAliases,\n            hoistStatic,\n          )\n        }\n      } else if (\n        (node.type === 'VariableDeclaration' ||\n          node.type === 'FunctionDeclaration' ||\n          node.type === 'ClassDeclaration' ||\n          node.type === 'TSEnumDeclaration') &&\n        !node.declare\n      ) {\n        walkDeclaration(\n          'script',\n          node,\n          scriptBindings,\n          vueImportAliases,\n          hoistStatic,\n        )\n      }\n    }\n\n    // <script> after <script setup>\n    // we need to move the block up so that `const __default__` is\n    // declared before being used in the actual component definition\n    if (scriptStartOffset! > startOffset) {\n      // if content doesn't end with newline, add one\n      if (!/\\n$/.test(script.content.trim())) {\n        ctx.s.appendLeft(scriptEndOffset!, `\\n`)\n      }\n      ctx.s.move(scriptStartOffset!, scriptEndOffset!, 0)\n    }\n  }\n\n  // 2.2 process <script setup> body\n  for (const node of scriptSetupAst.body) {\n    if (node.type === 'ExpressionStatement') {\n      const expr = unwrapTSNode(node.expression)\n      // process `defineProps` and `defineEmit(s)` calls\n      if (\n        processDefineProps(ctx, expr) ||\n        processDefineEmits(ctx, expr) ||\n        processDefineOptions(ctx, expr) ||\n        processDefineSlots(ctx, expr)\n      ) {\n        ctx.s.remove(node.start! + startOffset, node.end! + startOffset)\n      } else if (processDefineExpose(ctx, expr)) {\n        // defineExpose({}) -> expose({})\n        const callee = (expr as CallExpression).callee\n        ctx.s.overwrite(\n          callee.start! + startOffset,\n          callee.end! + startOffset,\n          '__expose',\n        )\n      } else {\n        processDefineModel(ctx, expr)\n      }\n    }\n\n    if (node.type === 'VariableDeclaration' && !node.declare) {\n      const total = node.declarations.length\n      let left = total\n      let lastNonRemoved: number | undefined\n\n      for (let i = 0; i < total; i++) {\n        const decl = node.declarations[i]\n        const init = decl.init && unwrapTSNode(decl.init)\n        if (init) {\n          if (processDefineOptions(ctx, init)) {\n            ctx.error(\n              `${DEFINE_OPTIONS}() has no returning value, it cannot be assigned.`,\n              node,\n            )\n          }\n\n          // defineProps\n          const isDefineProps = processDefineProps(ctx, init, decl.id as LVal)\n          if (ctx.propsDestructureRestId) {\n            setupBindings[ctx.propsDestructureRestId] =\n              BindingTypes.SETUP_REACTIVE_CONST\n          }\n\n          // defineEmits\n          const isDefineEmits =\n            !isDefineProps && processDefineEmits(ctx, init, decl.id as LVal)\n          !isDefineEmits &&\n            (processDefineSlots(ctx, init, decl.id as LVal) ||\n              processDefineModel(ctx, init, decl.id as LVal))\n\n          if (\n            isDefineProps &&\n            !ctx.propsDestructureRestId &&\n            ctx.propsDestructureDecl\n          ) {\n            if (left === 1) {\n              ctx.s.remove(node.start! + startOffset, node.end! + startOffset)\n            } else {\n              let start = decl.start! + startOffset\n              let end = decl.end! + startOffset\n              if (i === total - 1) {\n                // last one, locate the end of the last one that is not removed\n                // if we arrive at this branch, there must have been a\n                // non-removed decl before us, so lastNonRemoved is non-null.\n                start = node.declarations[lastNonRemoved!].end! + startOffset\n              } else {\n                // not the last one, locate the start of the next\n                end = node.declarations[i + 1].start! + startOffset\n              }\n              ctx.s.remove(start, end)\n              left--\n            }\n          } else if (isDefineEmits) {\n            ctx.s.overwrite(\n              startOffset + init.start!,\n              startOffset + init.end!,\n              '__emit',\n            )\n          } else {\n            lastNonRemoved = i\n          }\n        }\n      }\n    }\n\n    let isAllLiteral = false\n    // walk declarations to record declared bindings\n    if (\n      (node.type === 'VariableDeclaration' ||\n        node.type === 'FunctionDeclaration' ||\n        node.type === 'ClassDeclaration' ||\n        node.type === 'TSEnumDeclaration') &&\n      !node.declare\n    ) {\n      isAllLiteral = walkDeclaration(\n        'scriptSetup',\n        node,\n        setupBindings,\n        vueImportAliases,\n        hoistStatic,\n        !!ctx.propsDestructureDecl,\n      )\n    }\n\n    // hoist literal constants\n    if (hoistStatic && isAllLiteral) {\n      hoistNode(node)\n    }\n\n    // walk statements & named exports / variable declarations for top level\n    // await\n    if (\n      (node.type === 'VariableDeclaration' && !node.declare) ||\n      node.type.endsWith('Statement')\n    ) {\n      const scope: Statement[][] = [scriptSetupAst.body]\n      walk(node, {\n        enter(child: Node, parent: Node | null) {\n          if (isFunctionType(child)) {\n            this.skip()\n          }\n          if (child.type === 'BlockStatement') {\n            scope.push(child.body)\n          }\n          if (child.type === 'AwaitExpression') {\n            hasAwait = true\n            // if the await expression is an expression statement and\n            // - is in the root scope\n            // - or is not the first statement in a nested block scope\n            // then it needs a semicolon before the generated code.\n            const currentScope = scope[scope.length - 1]\n            const needsSemi = currentScope.some((n, i) => {\n              return (\n                (scope.length === 1 || i > 0) &&\n                n.type === 'ExpressionStatement' &&\n                n.start === child.start\n              )\n            })\n            processAwait(\n              ctx,\n              child,\n              needsSemi,\n              parent!.type === 'ExpressionStatement',\n            )\n          }\n        },\n        exit(node: Node) {\n          if (node.type === 'BlockStatement') scope.pop()\n        },\n      })\n    }\n\n    if (\n      (node.type === 'ExportNamedDeclaration' && node.exportKind !== 'type') ||\n      node.type === 'ExportAllDeclaration' ||\n      node.type === 'ExportDefaultDeclaration'\n    ) {\n      ctx.error(\n        `<script setup> cannot contain ES module exports. ` +\n          `If you are using a previous version of <script setup>, please ` +\n          `consult the updated RFC at https://github.com/vuejs/rfcs/pull/227.`,\n        node,\n      )\n    }\n\n    if (ctx.isTS) {\n      // move all Type declarations to outer scope\n      if (\n        node.type.startsWith('TS') ||\n        (node.type === 'ExportNamedDeclaration' &&\n          node.exportKind === 'type') ||\n        (node.type === 'VariableDeclaration' && node.declare)\n      ) {\n        if (node.type !== 'TSEnumDeclaration') {\n          hoistNode(node)\n        }\n      }\n    }\n  }\n\n  // 3 props destructure transform\n  if (ctx.propsDestructureDecl) {\n    transformDestructuredProps(ctx, vueImportAliases)\n  }\n\n  // 4. check macro args to make sure it doesn't reference setup scope\n  // variables\n  checkInvalidScopeReference(ctx.propsRuntimeDecl, DEFINE_PROPS)\n  checkInvalidScopeReference(ctx.propsRuntimeDefaults, DEFINE_PROPS)\n  checkInvalidScopeReference(ctx.propsDestructureDecl, DEFINE_PROPS)\n  checkInvalidScopeReference(ctx.emitsRuntimeDecl, DEFINE_EMITS)\n  checkInvalidScopeReference(ctx.optionsRuntimeDecl, DEFINE_OPTIONS)\n  for (const { runtimeOptionNodes } of Object.values(ctx.modelDecls)) {\n    for (const node of runtimeOptionNodes) {\n      checkInvalidScopeReference(node, DEFINE_MODEL)\n    }\n  }\n\n  // 5. remove non-script content\n  if (script) {\n    if (startOffset < scriptStartOffset!) {\n      // <script setup> before <script>\n      ctx.s.remove(0, startOffset)\n      ctx.s.remove(endOffset, scriptStartOffset!)\n      ctx.s.remove(scriptEndOffset!, source.length)\n    } else {\n      // <script> before <script setup>\n      ctx.s.remove(0, scriptStartOffset!)\n      ctx.s.remove(scriptEndOffset!, startOffset)\n      ctx.s.remove(endOffset, source.length)\n    }\n  } else {\n    // only <script setup>\n    ctx.s.remove(0, startOffset)\n    ctx.s.remove(endOffset, source.length)\n  }\n\n  // 6. analyze binding metadata\n  // `defineProps` & `defineModel` also register props bindings\n  if (scriptAst) {\n    Object.assign(ctx.bindingMetadata, analyzeScriptBindings(scriptAst.body))\n  }\n  for (const [key, { isType, imported, source }] of Object.entries(\n    ctx.userImports,\n  )) {\n    if (isType) continue\n    ctx.bindingMetadata[key] =\n      imported === '*' ||\n      (imported === 'default' && source.endsWith('.vue')) ||\n      source === 'vue'\n        ? BindingTypes.SETUP_CONST\n        : BindingTypes.SETUP_MAYBE_REF\n  }\n  for (const key in scriptBindings) {\n    ctx.bindingMetadata[key] = scriptBindings[key]\n  }\n  for (const key in setupBindings) {\n    ctx.bindingMetadata[key] = setupBindings[key]\n  }\n\n  // #11265, https://github.com/vitejs/rolldown-vite/issues/432\n  // 6.1 demote `const foo = reactive()` to `let` when used as v-model target.\n  // In non-inline template compilation, v-model assigns via `$setup.foo = $event`,\n  // which requires a SETUP_LET binding (getter + setter) to keep script state in sync.\n  // In inline mode, it generates `foo = $event`, which also requires `let`.\n  if (sfc.template && !sfc.template.src && sfc.template.ast) {\n    const vModelIds = resolveTemplateVModelIdentifiers(sfc)\n    if (vModelIds.size) {\n      const toDemote = new Set<string>()\n      for (const id of vModelIds) {\n        if (setupBindings[id] === BindingTypes.SETUP_REACTIVE_CONST) {\n          toDemote.add(id)\n        }\n      }\n\n      if (toDemote.size) {\n        for (const node of scriptSetupAst.body) {\n          if (\n            node.type === 'VariableDeclaration' &&\n            node.kind === 'const' &&\n            !node.declare\n          ) {\n            const demotedInDecl: string[] = []\n            for (const decl of node.declarations) {\n              if (decl.id.type === 'Identifier' && toDemote.has(decl.id.name)) {\n                demotedInDecl.push(decl.id.name)\n              }\n            }\n            if (demotedInDecl.length) {\n              ctx.s.overwrite(\n                node.start! + startOffset,\n                node.start! + startOffset + 'const'.length,\n                'let',\n              )\n              for (const id of demotedInDecl) {\n                setupBindings[id] = BindingTypes.SETUP_LET\n                ctx.bindingMetadata[id] = BindingTypes.SETUP_LET\n                warnOnce(\n                  `\\`v-model\\` cannot update a \\`const\\` reactive binding \\`${id}\\`. ` +\n                    `The compiler has transformed it to \\`let\\` to make the update work.`,\n                )\n              }\n            }\n          }\n        }\n      }\n    }\n  }\n\n  // 7. inject `useCssVars` calls\n  if (\n    sfc.cssVars.length &&\n    // no need to do this when targeting SSR\n    !options.templateOptions?.ssr\n  ) {\n    ctx.helperImports.add(CSS_VARS_HELPER)\n    ctx.helperImports.add('unref')\n    ctx.s.prependLeft(\n      startOffset,\n      `\\n${genCssVarsCode(\n        sfc.cssVars,\n        ctx.bindingMetadata,\n        scopeId,\n        !!options.isProd,\n      )}\\n`,\n    )\n  }\n\n  // 8. finalize setup() argument signature\n  let args = `__props`\n  if (ctx.propsTypeDecl) {\n    // mark as any and only cast on assignment\n    // since the user defined complex types may be incompatible with the\n    // inferred type from generated runtime declarations\n    args += `: any`\n  }\n  // inject user assignment of props\n  // we use a default __props so that template expressions referencing props\n  // can use it directly\n  if (ctx.propsDecl) {\n    if (ctx.propsDestructureRestId) {\n      ctx.s.overwrite(\n        startOffset + ctx.propsCall!.start!,\n        startOffset + ctx.propsCall!.end!,\n        `${ctx.helper(`createPropsRestProxy`)}(__props, ${JSON.stringify(\n          Object.keys(ctx.propsDestructuredBindings),\n        )})`,\n      )\n      ctx.s.overwrite(\n        startOffset + ctx.propsDestructureDecl!.start!,\n        startOffset + ctx.propsDestructureDecl!.end!,\n        ctx.propsDestructureRestId,\n      )\n    } else if (!ctx.propsDestructureDecl) {\n      ctx.s.overwrite(\n        startOffset + ctx.propsCall!.start!,\n        startOffset + ctx.propsCall!.end!,\n        '__props',\n      )\n    }\n  }\n\n  // inject temp variables for async context preservation\n  if (hasAwait) {\n    const any = ctx.isTS ? `: any` : ``\n    ctx.s.prependLeft(startOffset, `\\nlet __temp${any}, __restore${any}\\n`)\n  }\n\n  const destructureElements =\n    ctx.hasDefineExposeCall || !options.inlineTemplate\n      ? [`expose: __expose`]\n      : []\n  if (ctx.emitDecl) {\n    destructureElements.push(`emit: __emit`)\n  }\n  if (destructureElements.length) {\n    args += `, { ${destructureElements.join(', ')} }`\n  }\n\n  let templateMap\n  // 9. generate return statement\n  let returned\n  // ensure props bindings register before compile template in inline mode\n  const propsDecl = genRuntimeProps(ctx)\n  if (\n    !options.inlineTemplate ||\n    (!sfc.template && ctx.hasDefaultExportRender)\n  ) {\n    // non-inline mode, or has manual render in normal <script>\n    // return bindings from script and script setup\n    const allBindings: Record<string, any> = {\n      ...scriptBindings,\n      ...setupBindings,\n    }\n    for (const key in ctx.userImports) {\n      if (\n        !ctx.userImports[key].isType &&\n        ctx.userImports[key].isUsedInTemplate\n      ) {\n        allBindings[key] = true\n      }\n    }\n    returned = `{ `\n    for (const key in allBindings) {\n      if (\n        allBindings[key] === true &&\n        ctx.userImports[key].source !== 'vue' &&\n        !ctx.userImports[key].source.endsWith('.vue')\n      ) {\n        // generate getter for import bindings\n        // skip vue imports since we know they will never change\n        returned += `get ${key}() { return ${key} }, `\n      } else if (ctx.bindingMetadata[key] === BindingTypes.SETUP_LET) {\n        // local let binding, also add setter\n        const setArg = key === 'v' ? `_v` : `v`\n        returned +=\n          `get ${key}() { return ${key} }, ` +\n          `set ${key}(${setArg}) { ${key} = ${setArg} }, `\n      } else {\n        returned += `${key}, `\n      }\n    }\n    returned = returned.replace(/, $/, '') + ` }`\n  } else {\n    // inline mode\n    if (sfc.template && !sfc.template.src) {\n      if (options.templateOptions && options.templateOptions.ssr) {\n        hasInlinedSsrRenderFn = true\n      }\n      // inline render function mode - we are going to compile the template and\n      // inline it right here\n      const { code, ast, preamble, tips, errors, map } = compileTemplate({\n        filename,\n        ast: sfc.template.ast,\n        source: sfc.template.content,\n        inMap: sfc.template.map,\n        ...options.templateOptions,\n        id: scopeId,\n        scoped: sfc.styles.some(s => s.scoped),\n        isProd: options.isProd,\n        ssrCssVars: sfc.cssVars,\n        compilerOptions: {\n          ...(options.templateOptions &&\n            options.templateOptions.compilerOptions),\n          inline: true,\n          isTS: ctx.isTS,\n          bindingMetadata: ctx.bindingMetadata,\n        },\n      })\n      templateMap = map\n      if (tips.length) {\n        tips.forEach(warnOnce)\n      }\n      const err = errors[0]\n      if (typeof err === 'string') {\n        throw new Error(err)\n      } else if (err) {\n        if (err.loc) {\n          err.message +=\n            `\\n\\n` +\n            sfc.filename +\n            '\\n' +\n            generateCodeFrame(\n              source,\n              err.loc.start.offset,\n              err.loc.end.offset,\n            ) +\n            `\\n`\n        }\n        throw err\n      }\n      if (preamble) {\n        ctx.s.prepend(preamble)\n      }\n      // avoid duplicated unref import\n      // as this may get injected by the render function preamble OR the\n      // css vars codegen\n      if (ast && ast.helpers.has(UNREF)) {\n        ctx.helperImports.delete('unref')\n      }\n      returned = code\n    } else {\n      returned = `() => {}`\n    }\n  }\n\n  if (!options.inlineTemplate && !__TEST__) {\n    // in non-inline mode, the `__isScriptSetup: true` flag is used by\n    // componentPublicInstance proxy to allow properties that start with $ or _\n    ctx.s.appendRight(\n      endOffset,\n      `\\nconst __returned__ = ${returned}\\n` +\n        `Object.defineProperty(__returned__, '__isScriptSetup', { enumerable: false, value: true })\\n` +\n        `return __returned__` +\n        `\\n}\\n\\n`,\n    )\n  } else {\n    ctx.s.appendRight(endOffset, `\\nreturn ${returned}\\n}\\n\\n`)\n  }\n\n  // 10. finalize default export\n  const genDefaultAs = options.genDefaultAs\n    ? `const ${options.genDefaultAs} =`\n    : `export default`\n\n  let runtimeOptions = ``\n  if (!ctx.hasDefaultExportName && filename && filename !== DEFAULT_FILENAME) {\n    const match = filename.match(/([^/\\\\]+)\\.\\w+$/)\n    if (match) {\n      runtimeOptions += `\\n  __name: '${match[1]}',`\n    }\n  }\n  if (hasInlinedSsrRenderFn) {\n    runtimeOptions += `\\n  __ssrInlineRender: true,`\n  }\n\n  if (propsDecl) runtimeOptions += `\\n  props: ${propsDecl},`\n\n  const emitsDecl = genRuntimeEmits(ctx)\n  if (emitsDecl) runtimeOptions += `\\n  emits: ${emitsDecl},`\n\n  let definedOptions = ''\n  if (ctx.optionsRuntimeDecl) {\n    definedOptions = scriptSetup.content\n      .slice(ctx.optionsRuntimeDecl.start!, ctx.optionsRuntimeDecl.end!)\n      .trim()\n  }\n\n  // <script setup> components are closed by default. If the user did not\n  // explicitly call `defineExpose`, call expose() with no args.\n  const exposeCall =\n    ctx.hasDefineExposeCall || options.inlineTemplate ? `` : `  __expose();\\n`\n  // wrap setup code with function.\n  if (ctx.isTS) {\n    // for TS, make sure the exported type is still valid type with\n    // correct props information\n    // we have to use object spread for types to be merged properly\n    // user's TS setting should compile it down to proper targets\n    // export default defineComponent({ ...__default__, ... })\n    const def =\n      (defaultExport ? `\\n  ...${normalScriptDefaultVar},` : ``) +\n      (definedOptions ? `\\n  ...${definedOptions},` : '')\n    ctx.s.prependLeft(\n      startOffset,\n      `\\n${genDefaultAs} /*@__PURE__*/${ctx.helper(\n        `defineComponent`,\n      )}({${def}${runtimeOptions}\\n  ${\n        hasAwait ? `async ` : ``\n      }setup(${args}) {\\n${exposeCall}`,\n    )\n    ctx.s.appendRight(endOffset, `})`)\n  } else {\n    if (defaultExport || definedOptions) {\n      // without TS, can't rely on rest spread, so we use Object.assign\n      // export default Object.assign(__default__, { ... })\n      ctx.s.prependLeft(\n        startOffset,\n        `\\n${genDefaultAs} /*@__PURE__*/Object.assign(${\n          defaultExport ? `${normalScriptDefaultVar}, ` : ''\n        }${definedOptions ? `${definedOptions}, ` : ''}{${runtimeOptions}\\n  ` +\n          `${hasAwait ? `async ` : ``}setup(${args}) {\\n${exposeCall}`,\n      )\n      ctx.s.appendRight(endOffset, `})`)\n    } else {\n      ctx.s.prependLeft(\n        startOffset,\n        `\\n${genDefaultAs} {${runtimeOptions}\\n  ` +\n          `${hasAwait ? `async ` : ``}setup(${args}) {\\n${exposeCall}`,\n      )\n      ctx.s.appendRight(endOffset, `}`)\n    }\n  }\n\n  // 11. finalize Vue helper imports\n  if (ctx.helperImports.size > 0) {\n    const runtimeModuleName =\n      options.templateOptions?.compilerOptions?.runtimeModuleName\n    const importSrc = runtimeModuleName\n      ? JSON.stringify(runtimeModuleName)\n      : `'vue'`\n    ctx.s.prepend(\n      `import { ${[...ctx.helperImports]\n        .map(h => `${h} as _${h}`)\n        .join(', ')} } from ${importSrc}\\n`,\n    )\n  }\n\n  const content = ctx.s.toString()\n  let map =\n    options.sourceMap !== false\n      ? (ctx.s.generateMap({\n          source: filename,\n          hires: true,\n          includeContent: true,\n        }) as unknown as RawSourceMap)\n      : undefined\n  // merge source maps of the script setup and template in inline mode\n  if (templateMap && map) {\n    const offset = content.indexOf(returned)\n    const templateLineOffset =\n      content.slice(0, offset).split(/\\r?\\n/).length - 1\n    map = mergeSourceMaps(map, templateMap, templateLineOffset)\n  }\n  return {\n    ...scriptSetup,\n    bindings: ctx.bindingMetadata,\n    imports: ctx.userImports,\n    content,\n    map,\n    scriptAst: scriptAst?.body,\n    scriptSetupAst: scriptSetupAst?.body,\n    deps: ctx.deps ? [...ctx.deps] : undefined,\n  }\n}\n\nfunction registerBinding(\n  bindings: Record<string, BindingTypes>,\n  node: Identifier,\n  type: BindingTypes,\n) {\n  bindings[node.name] = type\n}\n\nfunction walkDeclaration(\n  from: 'script' | 'scriptSetup',\n  node: Declaration,\n  bindings: Record<string, BindingTypes>,\n  userImportAliases: Record<string, string>,\n  hoistStatic: boolean,\n  isPropsDestructureEnabled = false,\n): boolean {\n  let isAllLiteral = false\n\n  if (node.type === 'VariableDeclaration') {\n    const isConst = node.kind === 'const'\n    isAllLiteral =\n      isConst &&\n      node.declarations.every(\n        decl => decl.id.type === 'Identifier' && isStaticNode(decl.init!),\n      )\n\n    // export const foo = ...\n    for (const { id, init: _init } of node.declarations) {\n      const init = _init && unwrapTSNode(_init)\n      const isConstMacroCall =\n        isConst &&\n        isCallOf(\n          init,\n          c =>\n            c === DEFINE_PROPS ||\n            c === DEFINE_EMITS ||\n            c === WITH_DEFAULTS ||\n            c === DEFINE_SLOTS,\n        )\n      if (id.type === 'Identifier') {\n        let bindingType\n        const userReactiveBinding = userImportAliases['reactive']\n        if (\n          (hoistStatic || from === 'script') &&\n          (isAllLiteral || (isConst && isStaticNode(init!)))\n        ) {\n          bindingType = BindingTypes.LITERAL_CONST\n        } else if (isCallOf(init, userReactiveBinding)) {\n          // treat reactive() calls as let since it's meant to be mutable\n          bindingType = isConst\n            ? BindingTypes.SETUP_REACTIVE_CONST\n            : BindingTypes.SETUP_LET\n        } else if (\n          // if a declaration is a const literal, we can mark it so that\n          // the generated render fn code doesn't need to unref() it\n          isConstMacroCall ||\n          (isConst && canNeverBeRef(init!, userReactiveBinding))\n        ) {\n          bindingType = isCallOf(init, DEFINE_PROPS)\n            ? BindingTypes.SETUP_REACTIVE_CONST\n            : BindingTypes.SETUP_CONST\n        } else if (isConst) {\n          if (\n            isCallOf(\n              init,\n              m =>\n                m === userImportAliases['ref'] ||\n                m === userImportAliases['computed'] ||\n                m === userImportAliases['shallowRef'] ||\n                m === userImportAliases['customRef'] ||\n                m === userImportAliases['toRef'] ||\n                m === userImportAliases['useTemplateRef'] ||\n                m === DEFINE_MODEL,\n            )\n          ) {\n            bindingType = BindingTypes.SETUP_REF\n          } else {\n            bindingType = BindingTypes.SETUP_MAYBE_REF\n          }\n        } else {\n          bindingType = BindingTypes.SETUP_LET\n        }\n        registerBinding(bindings, id, bindingType)\n      } else {\n        if (isCallOf(init, DEFINE_PROPS) && isPropsDestructureEnabled) {\n          continue\n        }\n        if (id.type === 'ObjectPattern') {\n          walkObjectPattern(id, bindings, isConst, isConstMacroCall)\n        } else if (id.type === 'ArrayPattern') {\n          walkArrayPattern(id, bindings, isConst, isConstMacroCall)\n        }\n      }\n    }\n  } else if (node.type === 'TSEnumDeclaration') {\n    isAllLiteral = node.members.every(\n      member => !member.initializer || isStaticNode(member.initializer),\n    )\n    bindings[node.id!.name] = isAllLiteral\n      ? BindingTypes.LITERAL_CONST\n      : BindingTypes.SETUP_CONST\n  } else if (\n    node.type === 'FunctionDeclaration' ||\n    node.type === 'ClassDeclaration'\n  ) {\n    // export function foo() {} / export class Foo {}\n    // export declarations must be named.\n    bindings[node.id!.name] = BindingTypes.SETUP_CONST\n  }\n\n  return isAllLiteral\n}\n\nfunction walkObjectPattern(\n  node: ObjectPattern,\n  bindings: Record<string, BindingTypes>,\n  isConst: boolean,\n  isDefineCall = false,\n) {\n  for (const p of node.properties) {\n    if (p.type === 'ObjectProperty') {\n      if (p.key.type === 'Identifier' && p.key === p.value) {\n        // shorthand: const { x } = ...\n        const type = isDefineCall\n          ? BindingTypes.SETUP_CONST\n          : isConst\n            ? BindingTypes.SETUP_MAYBE_REF\n            : BindingTypes.SETUP_LET\n        registerBinding(bindings, p.key, type)\n      } else {\n        walkPattern(p.value, bindings, isConst, isDefineCall)\n      }\n    } else {\n      // ...rest\n      // argument can only be identifier when destructuring\n      const type = isConst ? BindingTypes.SETUP_CONST : BindingTypes.SETUP_LET\n      registerBinding(bindings, p.argument as Identifier, type)\n    }\n  }\n}\n\nfunction walkArrayPattern(\n  node: ArrayPattern,\n  bindings: Record<string, BindingTypes>,\n  isConst: boolean,\n  isDefineCall = false,\n) {\n  for (const e of node.elements) {\n    e && walkPattern(e, bindings, isConst, isDefineCall)\n  }\n}\n\nfunction walkPattern(\n  node: Node,\n  bindings: Record<string, BindingTypes>,\n  isConst: boolean,\n  isDefineCall = false,\n) {\n  if (node.type === 'Identifier') {\n    const type = isDefineCall\n      ? BindingTypes.SETUP_CONST\n      : isConst\n        ? BindingTypes.SETUP_MAYBE_REF\n        : BindingTypes.SETUP_LET\n    registerBinding(bindings, node, type)\n  } else if (node.type === 'RestElement') {\n    // argument can only be identifier when destructuring\n    const type = isConst ? BindingTypes.SETUP_CONST : BindingTypes.SETUP_LET\n    registerBinding(bindings, node.argument as Identifier, type)\n  } else if (node.type === 'ObjectPattern') {\n    walkObjectPattern(node, bindings, isConst)\n  } else if (node.type === 'ArrayPattern') {\n    walkArrayPattern(node, bindings, isConst)\n  } else if (node.type === 'AssignmentPattern') {\n    if (node.left.type === 'Identifier') {\n      const type = isDefineCall\n        ? BindingTypes.SETUP_CONST\n        : isConst\n          ? BindingTypes.SETUP_MAYBE_REF\n          : BindingTypes.SETUP_LET\n      registerBinding(bindings, node.left, type)\n    } else {\n      walkPattern(node.left, bindings, isConst)\n    }\n  }\n}\n\nfunction canNeverBeRef(node: Node, userReactiveImport?: string): boolean {\n  if (isCallOf(node, userReactiveImport)) {\n    return true\n  }\n  switch (node.type) {\n    case 'UnaryExpression':\n    case 'BinaryExpression':\n    case 'ArrayExpression':\n    case 'ObjectExpression':\n    case 'FunctionExpression':\n    case 'ArrowFunctionExpression':\n    case 'UpdateExpression':\n    case 'ClassExpression':\n    case 'TaggedTemplateExpression':\n      return true\n    case 'SequenceExpression':\n      return canNeverBeRef(\n        node.expressions[node.expressions.length - 1],\n        userReactiveImport,\n      )\n    default:\n      if (isLiteralNode(node)) {\n        return true\n      }\n      return false\n  }\n}\n\nfunction isStaticNode(node: Node): boolean {\n  node = unwrapTSNode(node)\n\n  switch (node.type) {\n    case 'UnaryExpression': // void 0, !true\n      return isStaticNode(node.argument)\n\n    case 'LogicalExpression': // 1 > 2\n    case 'BinaryExpression': // 1 + 2\n      return isStaticNode(node.left) && isStaticNode(node.right)\n\n    case 'ConditionalExpression': {\n      // 1 ? 2 : 3\n      return (\n        isStaticNode(node.test) &&\n        isStaticNode(node.consequent) &&\n        isStaticNode(node.alternate)\n      )\n    }\n\n    case 'SequenceExpression': // (1, 2)\n    case 'TemplateLiteral': // `foo${1}`\n      return node.expressions.every(expr => isStaticNode(expr))\n\n    case 'ParenthesizedExpression': // (1)\n      return isStaticNode(node.expression)\n\n    case 'StringLiteral':\n    case 'NumericLiteral':\n    case 'BooleanLiteral':\n    case 'NullLiteral':\n    case 'BigIntLiteral':\n      return true\n  }\n  return false\n}\n\nexport function mergeSourceMaps(\n  scriptMap: RawSourceMap,\n  templateMap: RawSourceMap,\n  templateLineOffset: number,\n): RawSourceMap {\n  const generator = new SourceMapGenerator()\n  const addMapping = (map: RawSourceMap, lineOffset = 0) => {\n    const consumer = new SourceMapConsumer(map)\n    ;(consumer as any).sources.forEach((sourceFile: string) => {\n      ;(generator as any)._sources.add(sourceFile)\n      const sourceContent = consumer.sourceContentFor(sourceFile)\n      if (sourceContent != null) {\n        generator.setSourceContent(sourceFile, sourceContent)\n      }\n    })\n    consumer.eachMapping(m => {\n      if (m.originalLine == null) return\n      generator.addMapping({\n        generated: {\n          line: m.generatedLine + lineOffset,\n          column: m.generatedColumn,\n        },\n        original: {\n          line: m.originalLine,\n          column: m.originalColumn!,\n        },\n        source: m.source,\n        name: m.name,\n      })\n    })\n  }\n\n  addMapping(scriptMap)\n  addMapping(templateMap, templateLineOffset)\n  ;(generator as any)._sourceRoot = scriptMap.sourceRoot\n  ;(generator as any)._file = scriptMap.file\n  return (generator as any).toJSON()\n}\n"
  },
  {
    "path": "packages/compiler-sfc/src/compileStyle.ts",
    "content": "import postcss, {\n  type LazyResult,\n  type Message,\n  type ProcessOptions,\n  type Result,\n  type SourceMap,\n} from 'postcss'\nimport trimPlugin from './style/pluginTrim'\nimport scopedPlugin from './style/pluginScoped'\nimport {\n  type PreprocessLang,\n  type StylePreprocessor,\n  type StylePreprocessorResults,\n  processors,\n} from './style/preprocessors'\nimport type { RawSourceMap } from '@vue/compiler-core'\nimport { cssVarsPlugin } from './style/cssVars'\nimport postcssModules from 'postcss-modules'\n\nexport interface SFCStyleCompileOptions {\n  source: string\n  filename: string\n  id: string\n  scoped?: boolean\n  trim?: boolean\n  isProd?: boolean\n  inMap?: RawSourceMap\n  preprocessLang?: PreprocessLang\n  preprocessOptions?: any\n  preprocessCustomRequire?: (id: string) => any\n  postcssOptions?: any\n  postcssPlugins?: any[]\n  /**\n   * @deprecated use `inMap` instead.\n   */\n  map?: RawSourceMap\n}\n\n/**\n * Aligns with postcss-modules\n * https://github.com/css-modules/postcss-modules\n */\nexport interface CSSModulesOptions {\n  scopeBehaviour?: 'global' | 'local'\n  generateScopedName?:\n    | string\n    | ((name: string, filename: string, css: string) => string)\n  hashPrefix?: string\n  localsConvention?: 'camelCase' | 'camelCaseOnly' | 'dashes' | 'dashesOnly'\n  exportGlobals?: boolean\n  globalModulePaths?: RegExp[]\n}\n\nexport interface SFCAsyncStyleCompileOptions extends SFCStyleCompileOptions {\n  isAsync?: boolean\n  // css modules support, note this requires async so that we can get the\n  // resulting json\n  modules?: boolean\n  modulesOptions?: CSSModulesOptions\n}\n\nexport interface SFCStyleCompileResults {\n  code: string\n  map: RawSourceMap | undefined\n  rawResult: Result | LazyResult | undefined\n  errors: Error[]\n  modules?: Record<string, string>\n  dependencies: Set<string>\n}\n\nexport function compileStyle(\n  options: SFCStyleCompileOptions,\n): SFCStyleCompileResults {\n  return doCompileStyle({\n    ...options,\n    isAsync: false,\n  }) as SFCStyleCompileResults\n}\n\nexport function compileStyleAsync(\n  options: SFCAsyncStyleCompileOptions,\n): Promise<SFCStyleCompileResults> {\n  return doCompileStyle({\n    ...options,\n    isAsync: true,\n  }) as Promise<SFCStyleCompileResults>\n}\n\nexport function doCompileStyle(\n  options: SFCAsyncStyleCompileOptions,\n): SFCStyleCompileResults | Promise<SFCStyleCompileResults> {\n  const {\n    filename,\n    id,\n    scoped = false,\n    trim = true,\n    isProd = false,\n    modules = false,\n    modulesOptions = {},\n    preprocessLang,\n    postcssOptions,\n    postcssPlugins,\n  } = options\n  const preprocessor = preprocessLang && processors[preprocessLang]\n  const preProcessedSource = preprocessor && preprocess(options, preprocessor)\n  const map = preProcessedSource\n    ? preProcessedSource.map\n    : options.inMap || options.map\n  const source = preProcessedSource ? preProcessedSource.code : options.source\n\n  const shortId = id.replace(/^data-v-/, '')\n  const longId = `data-v-${shortId}`\n\n  const plugins = (postcssPlugins || []).slice()\n  plugins.unshift(cssVarsPlugin({ id: shortId, isProd }))\n  if (trim) {\n    plugins.push(trimPlugin())\n  }\n  if (scoped) {\n    plugins.push(scopedPlugin(longId))\n  }\n  let cssModules: Record<string, string> | undefined\n  if (modules) {\n    if (__GLOBAL__ || __ESM_BROWSER__) {\n      throw new Error(\n        '[@vue/compiler-sfc] `modules` option is not supported in the browser build.',\n      )\n    }\n    if (!options.isAsync) {\n      throw new Error(\n        '[@vue/compiler-sfc] `modules` option can only be used with compileStyleAsync().',\n      )\n    }\n    plugins.push(\n      postcssModules({\n        ...modulesOptions,\n        getJSON: (_cssFileName: string, json: Record<string, string>) => {\n          cssModules = json\n        },\n      }),\n    )\n  }\n\n  const postCSSOptions: ProcessOptions = {\n    ...postcssOptions,\n    to: filename,\n    from: filename,\n  }\n  if (map) {\n    postCSSOptions.map = {\n      inline: false,\n      annotation: false,\n      prev: map,\n    }\n  }\n\n  let result: LazyResult | undefined\n  let code: string | undefined\n  let outMap: SourceMap | undefined\n  // stylus output include plain css. so need remove the repeat item\n  const dependencies = new Set(\n    preProcessedSource ? preProcessedSource.dependencies : [],\n  )\n  // sass has filename self when provided filename option\n  dependencies.delete(filename)\n\n  const errors: Error[] = []\n  if (preProcessedSource && preProcessedSource.errors.length) {\n    errors.push(...preProcessedSource.errors)\n  }\n\n  const recordPlainCssDependencies = (messages: Message[]) => {\n    messages.forEach(msg => {\n      if (msg.type === 'dependency') {\n        // postcss output path is absolute position path\n        dependencies.add(msg.file)\n      }\n    })\n    return dependencies\n  }\n\n  try {\n    result = postcss(plugins).process(source, postCSSOptions)\n\n    // In async mode, return a promise.\n    if (options.isAsync) {\n      return result\n        .then(result => ({\n          code: result.css || '',\n          map: result.map && result.map.toJSON(),\n          errors,\n          modules: cssModules,\n          rawResult: result,\n          dependencies: recordPlainCssDependencies(result.messages),\n        }))\n        .catch(error => ({\n          code: '',\n          map: undefined,\n          errors: [...errors, error],\n          rawResult: undefined,\n          dependencies,\n        }))\n    }\n\n    recordPlainCssDependencies(result.messages)\n    // force synchronous transform (we know we only have sync plugins)\n    code = result.css\n    outMap = result.map\n  } catch (e: any) {\n    errors.push(e)\n  }\n\n  return {\n    code: code || ``,\n    map: outMap && outMap.toJSON(),\n    errors,\n    rawResult: result,\n    dependencies,\n  }\n}\n\nfunction preprocess(\n  options: SFCStyleCompileOptions,\n  preprocessor: StylePreprocessor,\n): StylePreprocessorResults {\n  if ((__ESM_BROWSER__ || __GLOBAL__) && !options.preprocessCustomRequire) {\n    throw new Error(\n      `[@vue/compiler-sfc] Style preprocessing in the browser build must ` +\n        `provide the \\`preprocessCustomRequire\\` option to return the in-browser ` +\n        `version of the preprocessor.`,\n    )\n  }\n\n  return preprocessor(\n    options.source,\n    options.inMap || options.map,\n    {\n      filename: options.filename,\n      ...options.preprocessOptions,\n    },\n    options.preprocessCustomRequire,\n  )\n}\n"
  },
  {
    "path": "packages/compiler-sfc/src/compileTemplate.ts",
    "content": "import {\n  type CodegenResult,\n  type CompilerError,\n  type CompilerOptions,\n  type ElementNode,\n  type NodeTransform,\n  NodeTypes,\n  type ParserOptions,\n  type RawSourceMap,\n  type RootNode,\n  createRoot,\n} from '@vue/compiler-core'\nimport { SourceMapConsumer, SourceMapGenerator } from 'source-map-js'\nimport {\n  type AssetURLOptions,\n  type AssetURLTagConfig,\n  createAssetUrlTransformWithOptions,\n  normalizeOptions,\n  transformAssetUrl,\n} from './template/transformAssetUrl'\nimport {\n  createSrcsetTransformWithOptions,\n  transformSrcset,\n} from './template/transformSrcset'\nimport { generateCodeFrame, isObject } from '@vue/shared'\nimport * as CompilerDOM from '@vue/compiler-dom'\nimport * as CompilerSSR from '@vue/compiler-ssr'\nimport consolidate from '@vue/consolidate'\nimport { warnOnce } from './warn'\nimport { genCssVarsFromList } from './style/cssVars'\n\nexport interface TemplateCompiler {\n  compile(source: string | RootNode, options: CompilerOptions): CodegenResult\n  parse(template: string, options: ParserOptions): RootNode\n}\n\nexport interface SFCTemplateCompileResults {\n  code: string\n  ast?: RootNode\n  preamble?: string\n  source: string\n  tips: string[]\n  errors: (string | CompilerError)[]\n  map?: RawSourceMap\n}\n\nexport interface SFCTemplateCompileOptions {\n  source: string\n  ast?: RootNode\n  filename: string\n  id: string\n  scoped?: boolean\n  slotted?: boolean\n  isProd?: boolean\n  ssr?: boolean\n  ssrCssVars?: string[]\n  inMap?: RawSourceMap\n  compiler?: TemplateCompiler\n  compilerOptions?: CompilerOptions\n  preprocessLang?: string\n  preprocessOptions?: any\n  /**\n   * In some cases, compiler-sfc may not be inside the project root (e.g. when\n   * linked or globally installed). In such cases a custom `require` can be\n   * passed to correctly resolve the preprocessors.\n   */\n  preprocessCustomRequire?: (id: string) => any\n  /**\n   * Configure what tags/attributes to transform into asset url imports,\n   * or disable the transform altogether with `false`.\n   */\n  transformAssetUrls?: AssetURLOptions | AssetURLTagConfig | boolean\n}\n\ninterface PreProcessor {\n  render(\n    source: string,\n    options: any,\n    cb: (err: Error | null, res: string) => void,\n  ): void\n}\n\nfunction preprocess(\n  { source, filename, preprocessOptions }: SFCTemplateCompileOptions,\n  preprocessor: PreProcessor,\n): string {\n  // Consolidate exposes a callback based API, but the callback is in fact\n  // called synchronously for most templating engines. In our case, we have to\n  // expose a synchronous API so that it is usable in Jest transforms (which\n  // have to be sync because they are applied via Node.js require hooks)\n  let res: string = ''\n  let err: Error | null = null\n\n  preprocessor.render(\n    source,\n    { filename, ...preprocessOptions },\n    (_err, _res) => {\n      if (_err) err = _err\n      res = _res\n    },\n  )\n\n  if (err) throw err\n  return res\n}\n\nexport function compileTemplate(\n  options: SFCTemplateCompileOptions,\n): SFCTemplateCompileResults {\n  const { preprocessLang, preprocessCustomRequire } = options\n\n  if (\n    (__ESM_BROWSER__ || __GLOBAL__) &&\n    preprocessLang &&\n    !preprocessCustomRequire\n  ) {\n    throw new Error(\n      `[@vue/compiler-sfc] Template preprocessing in the browser build must ` +\n        `provide the \\`preprocessCustomRequire\\` option to return the in-browser ` +\n        `version of the preprocessor in the shape of { render(): string }.`,\n    )\n  }\n\n  const preprocessor = preprocessLang\n    ? preprocessCustomRequire\n      ? preprocessCustomRequire(preprocessLang)\n      : __ESM_BROWSER__\n        ? undefined\n        : consolidate[preprocessLang as keyof typeof consolidate]\n    : false\n  if (preprocessor) {\n    try {\n      return doCompileTemplate({\n        ...options,\n        source: preprocess(options, preprocessor),\n        ast: undefined, // invalidate AST if template goes through preprocessor\n      })\n    } catch (e: any) {\n      return {\n        code: `export default function render() {}`,\n        source: options.source,\n        tips: [],\n        errors: [e],\n      }\n    }\n  } else if (preprocessLang) {\n    return {\n      code: `export default function render() {}`,\n      source: options.source,\n      tips: [\n        `Component ${options.filename} uses lang ${preprocessLang} for template. Please install the language preprocessor.`,\n      ],\n      errors: [\n        `Component ${options.filename} uses lang ${preprocessLang} for template, however it is not installed.`,\n      ],\n    }\n  } else {\n    return doCompileTemplate(options)\n  }\n}\n\nfunction doCompileTemplate({\n  filename,\n  id,\n  scoped,\n  slotted,\n  inMap,\n  source,\n  ast: inAST,\n  ssr = false,\n  ssrCssVars,\n  isProd = false,\n  compiler,\n  compilerOptions = {},\n  transformAssetUrls,\n}: SFCTemplateCompileOptions): SFCTemplateCompileResults {\n  const errors: CompilerError[] = []\n  const warnings: CompilerError[] = []\n\n  let nodeTransforms: NodeTransform[] = []\n  if (isObject(transformAssetUrls)) {\n    const assetOptions = normalizeOptions(transformAssetUrls)\n    nodeTransforms = [\n      createAssetUrlTransformWithOptions(assetOptions),\n      createSrcsetTransformWithOptions(assetOptions),\n    ]\n  } else if (transformAssetUrls !== false) {\n    nodeTransforms = [transformAssetUrl, transformSrcset]\n  }\n\n  if (ssr && !ssrCssVars) {\n    warnOnce(\n      `compileTemplate is called with \\`ssr: true\\` but no ` +\n        `corresponding \\`cssVars\\` option.`,\n    )\n  }\n  if (!id) {\n    warnOnce(`compileTemplate now requires the \\`id\\` option.`)\n    id = ''\n  }\n\n  const shortId = id.replace(/^data-v-/, '')\n  const longId = `data-v-${shortId}`\n\n  const defaultCompiler = ssr ? (CompilerSSR as TemplateCompiler) : CompilerDOM\n  compiler = compiler || defaultCompiler\n\n  if (compiler !== defaultCompiler) {\n    // user using custom compiler, this means we cannot reuse the AST from\n    // the descriptor as they might be different.\n    inAST = undefined\n  }\n\n  if (inAST?.transformed) {\n    // If input AST has already been transformed, then it cannot be reused.\n    // We need to parse a fresh one. Can't just use `source` here since we need\n    // the AST location info to be relative to the entire SFC.\n    const newAST = (ssr ? CompilerDOM : compiler).parse(inAST.source, {\n      prefixIdentifiers: true,\n      ...compilerOptions,\n      parseMode: 'sfc',\n      onError: e => errors.push(e),\n    })\n    const template = newAST.children.find(\n      node => node.type === NodeTypes.ELEMENT && node.tag === 'template',\n    ) as ElementNode\n    inAST = createRoot(template.children, inAST.source)\n  }\n\n  let { code, ast, preamble, map } = compiler.compile(inAST || source, {\n    mode: 'module',\n    prefixIdentifiers: true,\n    hoistStatic: true,\n    cacheHandlers: true,\n    ssrCssVars:\n      ssr && ssrCssVars && ssrCssVars.length\n        ? genCssVarsFromList(ssrCssVars, shortId, isProd, true)\n        : '',\n    scopeId: scoped ? longId : undefined,\n    slotted,\n    sourceMap: true,\n    ...compilerOptions,\n    hmr: !isProd,\n    nodeTransforms: nodeTransforms.concat(compilerOptions.nodeTransforms || []),\n    filename,\n    onError: e => errors.push(e),\n    onWarn: w => warnings.push(w),\n  })\n\n  // inMap should be the map produced by ./parse.ts which is a simple line-only\n  // mapping. If it is present, we need to adjust the final map and errors to\n  // reflect the original line numbers.\n  if (inMap && !inAST) {\n    if (map) {\n      map = mapLines(inMap, map)\n    }\n    if (errors.length) {\n      patchErrors(errors, source, inMap)\n    }\n  }\n\n  const tips = warnings.map(w => {\n    let msg = w.message\n    if (w.loc) {\n      msg += `\\n${generateCodeFrame(\n        inAST?.source || source,\n        w.loc.start.offset,\n        w.loc.end.offset,\n      )}`\n    }\n    return msg\n  })\n\n  return { code, ast, preamble, source, errors, tips, map }\n}\n\nfunction mapLines(oldMap: RawSourceMap, newMap: RawSourceMap): RawSourceMap {\n  if (!oldMap) return newMap\n  if (!newMap) return oldMap\n\n  const oldMapConsumer = new SourceMapConsumer(oldMap)\n  const newMapConsumer = new SourceMapConsumer(newMap)\n  const mergedMapGenerator = new SourceMapGenerator()\n\n  newMapConsumer.eachMapping(m => {\n    if (m.originalLine == null) {\n      return\n    }\n\n    const origPosInOldMap = oldMapConsumer.originalPositionFor({\n      line: m.originalLine,\n      column: m.originalColumn!,\n    })\n\n    if (origPosInOldMap.source == null) {\n      return\n    }\n\n    mergedMapGenerator.addMapping({\n      generated: {\n        line: m.generatedLine,\n        column: m.generatedColumn,\n      },\n      original: {\n        line: origPosInOldMap.line, // map line\n        // use current column, since the oldMap produced by @vue/compiler-sfc\n        // does not\n        column: m.originalColumn!,\n      },\n      source: origPosInOldMap.source,\n      name: origPosInOldMap.name,\n    })\n  })\n\n  // source-map's type definition is incomplete\n  const generator = mergedMapGenerator as any\n  ;(oldMapConsumer as any).sources.forEach((sourceFile: string) => {\n    generator._sources.add(sourceFile)\n    const sourceContent = oldMapConsumer.sourceContentFor(sourceFile)\n    if (sourceContent != null) {\n      mergedMapGenerator.setSourceContent(sourceFile, sourceContent)\n    }\n  })\n\n  generator._sourceRoot = oldMap.sourceRoot\n  generator._file = oldMap.file\n  return generator.toJSON()\n}\n\nfunction patchErrors(\n  errors: CompilerError[],\n  source: string,\n  inMap: RawSourceMap,\n) {\n  const originalSource = inMap.sourcesContent![0]\n  const offset = originalSource.indexOf(source)\n  const lineOffset = originalSource.slice(0, offset).split(/\\r?\\n/).length - 1\n  errors.forEach(err => {\n    if (err.loc) {\n      err.loc.start.line += lineOffset\n      err.loc.start.offset += offset\n      if (err.loc.end !== err.loc.start) {\n        err.loc.end.line += lineOffset\n        err.loc.end.offset += offset\n      }\n    }\n  })\n}\n"
  },
  {
    "path": "packages/compiler-sfc/src/index.ts",
    "content": "export const version: string = __VERSION__\n\n// API\nexport { parse } from './parse'\nexport { compileTemplate } from './compileTemplate'\nexport { compileStyle, compileStyleAsync } from './compileStyle'\nexport { compileScript } from './compileScript'\nexport { rewriteDefault, rewriteDefaultAST } from './rewriteDefault'\nexport { resolveTypeElements, inferRuntimeType } from './script/resolveType'\n\nimport { type SFCParseResult, parseCache as _parseCache } from './parse'\n// #9521 export parseCache as a simple map to avoid exposing LRU types\nexport const parseCache = _parseCache as Map<string, SFCParseResult>\n\n// error messages\nimport {\n  DOMErrorMessages,\n  errorMessages as coreErrorMessages,\n} from '@vue/compiler-dom'\n\nexport const errorMessages: Record<number, string> = {\n  ...coreErrorMessages,\n  ...DOMErrorMessages,\n}\n\n// Utilities\nexport { parse as babelParse } from '@babel/parser'\nimport MagicString from 'magic-string'\nexport { MagicString }\n// technically internal but we want it in @vue/repl, cast it as any to avoid\n// relying on estree types\nimport { walk as _walk } from 'estree-walker'\nexport const walk = _walk as any\nexport {\n  generateCodeFrame,\n  walkIdentifiers,\n  extractIdentifiers,\n  isInDestructureAssignment,\n  isStaticProperty,\n} from '@vue/compiler-core'\n\n// Internals for type resolution\nexport { invalidateTypeCache, registerTS } from './script/resolveType'\nexport { extractRuntimeProps } from './script/defineProps'\nexport { extractRuntimeEmits } from './script/defineEmits'\n\n// Types\nexport type {\n  SFCParseOptions,\n  SFCParseResult,\n  SFCDescriptor,\n  SFCBlock,\n  SFCTemplateBlock,\n  SFCScriptBlock,\n  SFCStyleBlock,\n} from './parse'\nexport type {\n  TemplateCompiler,\n  SFCTemplateCompileOptions,\n  SFCTemplateCompileResults,\n} from './compileTemplate'\nexport type {\n  SFCStyleCompileOptions,\n  SFCAsyncStyleCompileOptions,\n  SFCStyleCompileResults,\n} from './compileStyle'\nexport type { SFCScriptCompileOptions } from './compileScript'\nexport type { ScriptCompileContext } from './script/context'\nexport type {\n  TypeResolveContext,\n  SimpleTypeResolveOptions,\n  SimpleTypeResolveContext,\n} from './script/resolveType'\nexport type {\n  AssetURLOptions,\n  AssetURLTagConfig,\n} from './template/transformAssetUrl'\nexport type {\n  CompilerOptions,\n  CompilerError,\n  BindingMetadata,\n} from '@vue/compiler-core'\n\n/**\n * @deprecated this is preserved to avoid breaking vite-plugin-vue < 5.0\n * with reactivityTransform: true. The desired behavior should be silently\n * ignoring the option instead of breaking.\n */\nexport const shouldTransformRef = () => false\n"
  },
  {
    "path": "packages/compiler-sfc/src/parse.ts",
    "content": "import {\n  type BindingMetadata,\n  type CodegenSourceMapGenerator,\n  type CompilerError,\n  type ElementNode,\n  NodeTypes,\n  type ParserOptions,\n  type RawSourceMap,\n  type RootNode,\n  type SourceLocation,\n  createRoot,\n} from '@vue/compiler-core'\nimport * as CompilerDOM from '@vue/compiler-dom'\nimport { SourceMapGenerator } from 'source-map-js'\nimport type { TemplateCompiler } from './compileTemplate'\nimport { parseCssVars } from './style/cssVars'\nimport { createCache } from './cache'\nimport type { ImportBinding } from './compileScript'\nimport { isImportUsed } from './script/importUsageCheck'\nimport type { LRUCache } from 'lru-cache'\nimport { genCacheKey } from '@vue/shared'\n\nexport const DEFAULT_FILENAME = 'anonymous.vue'\n\nexport interface SFCParseOptions {\n  filename?: string\n  sourceMap?: boolean\n  sourceRoot?: string\n  pad?: boolean | 'line' | 'space'\n  ignoreEmpty?: boolean\n  compiler?: TemplateCompiler\n  templateParseOptions?: ParserOptions\n}\n\nexport interface SFCBlock {\n  type: string\n  content: string\n  attrs: Record<string, string | true>\n  loc: SourceLocation\n  map?: RawSourceMap\n  lang?: string\n  src?: string\n}\n\nexport interface SFCTemplateBlock extends SFCBlock {\n  type: 'template'\n  ast?: RootNode\n}\n\nexport interface SFCScriptBlock extends SFCBlock {\n  type: 'script'\n  setup?: string | boolean\n  bindings?: BindingMetadata\n  imports?: Record<string, ImportBinding>\n  scriptAst?: import('@babel/types').Statement[]\n  scriptSetupAst?: import('@babel/types').Statement[]\n  warnings?: string[]\n  /**\n   * Fully resolved dependency file paths (unix slashes) with imported types\n   * used in macros, used for HMR cache busting in @vitejs/plugin-vue and\n   * vue-loader.\n   */\n  deps?: string[]\n}\n\nexport interface SFCStyleBlock extends SFCBlock {\n  type: 'style'\n  scoped?: boolean\n  module?: string | boolean\n}\n\nexport interface SFCDescriptor {\n  filename: string\n  source: string\n  template: SFCTemplateBlock | null\n  script: SFCScriptBlock | null\n  scriptSetup: SFCScriptBlock | null\n  styles: SFCStyleBlock[]\n  customBlocks: SFCBlock[]\n  cssVars: string[]\n  /**\n   * whether the SFC uses :slotted() modifier.\n   * this is used as a compiler optimization hint.\n   */\n  slotted: boolean\n\n  /**\n   * compare with an existing descriptor to determine whether HMR should perform\n   * a reload vs. re-render.\n   *\n   * Note: this comparison assumes the prev/next script are already identical,\n   * and only checks the special case where <script setup lang=\"ts\"> unused import\n   * pruning result changes due to template changes.\n   */\n  shouldForceReload: (prevImports: Record<string, ImportBinding>) => boolean\n}\n\nexport interface SFCParseResult {\n  descriptor: SFCDescriptor\n  errors: (CompilerError | SyntaxError)[]\n}\n\nexport const parseCache:\n  | Map<string, SFCParseResult>\n  | LRUCache<string, SFCParseResult> = createCache<SFCParseResult>()\n\nexport function parse(\n  source: string,\n  options: SFCParseOptions = {},\n): SFCParseResult {\n  const sourceKey = genCacheKey(source, {\n    ...options,\n    compiler: { parse: options.compiler?.parse },\n  })\n  const cache = parseCache.get(sourceKey)\n  if (cache) {\n    return cache\n  }\n\n  const {\n    sourceMap = true,\n    filename = DEFAULT_FILENAME,\n    sourceRoot = '',\n    pad = false,\n    ignoreEmpty = true,\n    compiler = CompilerDOM,\n    templateParseOptions = {},\n  } = options\n\n  const descriptor: SFCDescriptor = {\n    filename,\n    source,\n    template: null,\n    script: null,\n    scriptSetup: null,\n    styles: [],\n    customBlocks: [],\n    cssVars: [],\n    slotted: false,\n    shouldForceReload: prevImports => hmrShouldReload(prevImports, descriptor),\n  }\n\n  const errors: (CompilerError | SyntaxError)[] = []\n  const ast = compiler.parse(source, {\n    parseMode: 'sfc',\n    prefixIdentifiers: true,\n    ...templateParseOptions,\n    onError: e => {\n      errors.push(e)\n    },\n  })\n  ast.children.forEach(node => {\n    if (node.type !== NodeTypes.ELEMENT) {\n      return\n    }\n    // we only want to keep the nodes that are not empty\n    // (when the tag is not a template)\n    if (\n      ignoreEmpty &&\n      node.tag !== 'template' &&\n      isEmpty(node) &&\n      !hasSrc(node)\n    ) {\n      return\n    }\n    switch (node.tag) {\n      case 'template':\n        if (!descriptor.template) {\n          const templateBlock = (descriptor.template = createBlock(\n            node,\n            source,\n            false,\n          ) as SFCTemplateBlock)\n\n          if (!templateBlock.attrs.src) {\n            templateBlock.ast = createRoot(node.children, source)\n          }\n\n          // warn against 2.x <template functional>\n          if (templateBlock.attrs.functional) {\n            const err = new SyntaxError(\n              `<template functional> is no longer supported in Vue 3, since ` +\n                `functional components no longer have significant performance ` +\n                `difference from stateful ones. Just use a normal <template> ` +\n                `instead.`,\n            ) as CompilerError\n            err.loc = node.props.find(\n              p => p.type === NodeTypes.ATTRIBUTE && p.name === 'functional',\n            )!.loc\n            errors.push(err)\n          }\n        } else {\n          errors.push(createDuplicateBlockError(node))\n        }\n        break\n      case 'script':\n        const scriptBlock = createBlock(node, source, pad) as SFCScriptBlock\n        const isSetup = !!scriptBlock.attrs.setup\n        if (isSetup && !descriptor.scriptSetup) {\n          descriptor.scriptSetup = scriptBlock\n          break\n        }\n        if (!isSetup && !descriptor.script) {\n          descriptor.script = scriptBlock\n          break\n        }\n        errors.push(createDuplicateBlockError(node, isSetup))\n        break\n      case 'style':\n        const styleBlock = createBlock(node, source, pad) as SFCStyleBlock\n        if (styleBlock.attrs.vars) {\n          errors.push(\n            new SyntaxError(\n              `<style vars> has been replaced by a new proposal: ` +\n                `https://github.com/vuejs/rfcs/pull/231`,\n            ),\n          )\n        }\n        descriptor.styles.push(styleBlock)\n        break\n      default:\n        descriptor.customBlocks.push(createBlock(node, source, pad))\n        break\n    }\n  })\n  if (!descriptor.template && !descriptor.script && !descriptor.scriptSetup) {\n    errors.push(\n      new SyntaxError(\n        `At least one <template> or <script> is required in a single file component. ${descriptor.filename}`,\n      ),\n    )\n  }\n  if (descriptor.scriptSetup) {\n    if (descriptor.scriptSetup.src) {\n      errors.push(\n        new SyntaxError(\n          `<script setup> cannot use the \"src\" attribute because ` +\n            `its syntax will be ambiguous outside of the component.`,\n        ),\n      )\n      descriptor.scriptSetup = null\n    }\n    if (descriptor.script && descriptor.script.src) {\n      errors.push(\n        new SyntaxError(\n          `<script> cannot use the \"src\" attribute when <script setup> is ` +\n            `also present because they must be processed together.`,\n        ),\n      )\n      descriptor.script = null\n    }\n  }\n\n  // dedent pug/jade templates\n  let templateColumnOffset = 0\n  if (\n    descriptor.template &&\n    (descriptor.template.lang === 'pug' || descriptor.template.lang === 'jade')\n  ) {\n    ;[descriptor.template.content, templateColumnOffset] = dedent(\n      descriptor.template.content,\n    )\n  }\n\n  if (sourceMap) {\n    const genMap = (block: SFCBlock | null, columnOffset = 0) => {\n      if (block && !block.src) {\n        block.map = generateSourceMap(\n          filename,\n          source,\n          block.content,\n          sourceRoot,\n          !pad || block.type === 'template' ? block.loc.start.line - 1 : 0,\n          columnOffset,\n        )\n      }\n    }\n    genMap(descriptor.template, templateColumnOffset)\n    genMap(descriptor.script)\n    descriptor.styles.forEach(s => genMap(s))\n    descriptor.customBlocks.forEach(s => genMap(s))\n  }\n\n  // parse CSS vars\n  descriptor.cssVars = parseCssVars(descriptor)\n\n  // check if the SFC uses :slotted\n  const slottedRE = /(?:::v-|:)slotted\\(/\n  descriptor.slotted = descriptor.styles.some(\n    s => s.scoped && slottedRE.test(s.content),\n  )\n\n  const result = {\n    descriptor,\n    errors,\n  }\n  parseCache.set(sourceKey, result)\n  return result\n}\n\nfunction createDuplicateBlockError(\n  node: ElementNode,\n  isScriptSetup = false,\n): CompilerError {\n  const err = new SyntaxError(\n    `Single file component can contain only one <${node.tag}${\n      isScriptSetup ? ` setup` : ``\n    }> element`,\n  ) as CompilerError\n  err.loc = node.loc\n  return err\n}\n\nfunction createBlock(\n  node: ElementNode,\n  source: string,\n  pad: SFCParseOptions['pad'],\n): SFCBlock {\n  const type = node.tag\n  const loc = node.innerLoc!\n  const attrs: Record<string, string | true> = {}\n  const block: SFCBlock = {\n    type,\n    content: source.slice(loc.start.offset, loc.end.offset),\n    loc,\n    attrs,\n  }\n  if (pad) {\n    block.content = padContent(source, block, pad) + block.content\n  }\n  node.props.forEach(p => {\n    if (p.type === NodeTypes.ATTRIBUTE) {\n      const name = p.name\n      attrs[name] = p.value ? p.value.content || true : true\n      if (name === 'lang') {\n        block.lang = p.value && p.value.content\n      } else if (name === 'src') {\n        block.src = p.value && p.value.content\n      } else if (type === 'style') {\n        if (name === 'scoped') {\n          ;(block as SFCStyleBlock).scoped = true\n        } else if (name === 'module') {\n          ;(block as SFCStyleBlock).module = attrs[name]\n        }\n      } else if (type === 'script' && name === 'setup') {\n        ;(block as SFCScriptBlock).setup = attrs.setup\n      }\n    }\n  })\n  return block\n}\n\nconst splitRE = /\\r?\\n/g\nconst emptyRE = /^(?:\\/\\/)?\\s*$/\nconst replaceRE = /./g\n\nfunction generateSourceMap(\n  filename: string,\n  source: string,\n  generated: string,\n  sourceRoot: string,\n  lineOffset: number,\n  columnOffset: number,\n): RawSourceMap {\n  const map = new SourceMapGenerator({\n    file: filename.replace(/\\\\/g, '/'),\n    sourceRoot: sourceRoot.replace(/\\\\/g, '/'),\n  }) as unknown as CodegenSourceMapGenerator\n  map.setSourceContent(filename, source)\n  map._sources.add(filename)\n  generated.split(splitRE).forEach((line, index) => {\n    if (!emptyRE.test(line)) {\n      const originalLine = index + 1 + lineOffset\n      const generatedLine = index + 1\n      for (let i = 0; i < line.length; i++) {\n        if (!/\\s/.test(line[i])) {\n          map._mappings.add({\n            originalLine,\n            originalColumn: i + columnOffset,\n            generatedLine,\n            generatedColumn: i,\n            source: filename,\n            name: null,\n          })\n        }\n      }\n    }\n  })\n  return map.toJSON()\n}\n\nfunction padContent(\n  content: string,\n  block: SFCBlock,\n  pad: SFCParseOptions['pad'],\n): string {\n  content = content.slice(0, block.loc.start.offset)\n  if (pad === 'space') {\n    return content.replace(replaceRE, ' ')\n  } else {\n    const offset = content.split(splitRE).length\n    const padChar = block.type === 'script' && !block.lang ? '//\\n' : '\\n'\n    return Array(offset).join(padChar)\n  }\n}\n\nfunction hasSrc(node: ElementNode) {\n  return node.props.some(p => {\n    if (p.type !== NodeTypes.ATTRIBUTE) {\n      return false\n    }\n    return p.name === 'src'\n  })\n}\n\n/**\n * Returns true if the node has no children\n * once the empty text nodes (trimmed content) have been filtered out.\n */\nfunction isEmpty(node: ElementNode) {\n  for (let i = 0; i < node.children.length; i++) {\n    const child = node.children[i]\n    if (child.type !== NodeTypes.TEXT || child.content.trim() !== '') {\n      return false\n    }\n  }\n  return true\n}\n\n/**\n * Note: this comparison assumes the prev/next script are already identical,\n * and only checks the special case where <script setup lang=\"ts\"> unused import\n * pruning result changes due to template changes.\n */\nexport function hmrShouldReload(\n  prevImports: Record<string, ImportBinding>,\n  next: SFCDescriptor,\n): boolean {\n  if (\n    !next.scriptSetup ||\n    (next.scriptSetup.lang !== 'ts' && next.scriptSetup.lang !== 'tsx')\n  ) {\n    return false\n  }\n\n  // for each previous import, check if its used status remain the same based on\n  // the next descriptor's template\n  for (const key in prevImports) {\n    // if an import was previous unused, but now is used, we need to force\n    // reload so that the script now includes that import.\n    if (!prevImports[key].isUsedInTemplate && isImportUsed(key, next)) {\n      return true\n    }\n  }\n\n  return false\n}\n\n/**\n * Dedent a string.\n *\n * This removes any whitespace that is common to all lines in the string from\n * each line in the string.\n */\nfunction dedent(s: string): [string, number] {\n  const lines = s.split('\\n')\n  const minIndent = lines.reduce(function (minIndent, line) {\n    if (line.trim() === '') {\n      return minIndent\n    }\n    const indent = line.match(/^\\s*/)?.[0]?.length || 0\n    return Math.min(indent, minIndent)\n  }, Infinity)\n  if (minIndent === 0) {\n    return [s, minIndent]\n  }\n  return [\n    lines\n      .map(function (line) {\n        return line.slice(minIndent)\n      })\n      .join('\\n'),\n    minIndent,\n  ]\n}\n"
  },
  {
    "path": "packages/compiler-sfc/src/rewriteDefault.ts",
    "content": "import { parse } from '@babel/parser'\nimport MagicString from 'magic-string'\nimport type { ParserPlugin } from '@babel/parser'\nimport type { Identifier, Statement } from '@babel/types'\nimport { resolveParserPlugins } from './script/context'\n\nexport function rewriteDefault(\n  input: string,\n  as: string,\n  parserPlugins?: ParserPlugin[],\n): string {\n  const ast = parse(input, {\n    sourceType: 'module',\n    plugins: resolveParserPlugins('js', parserPlugins),\n  }).program.body\n  const s = new MagicString(input)\n\n  rewriteDefaultAST(ast, s, as)\n\n  return s.toString()\n}\n\n/**\n * Utility for rewriting `export default` in a script block into a variable\n * declaration so that we can inject things into it\n */\nexport function rewriteDefaultAST(\n  ast: Statement[],\n  s: MagicString,\n  as: string,\n): void {\n  if (!hasDefaultExport(ast)) {\n    s.append(`\\nconst ${as} = {}`)\n    return\n  }\n\n  // if the script somehow still contains `default export`, it probably has\n  // multi-line comments or template strings. fallback to a full parse.\n  ast.forEach(node => {\n    if (node.type === 'ExportDefaultDeclaration') {\n      if (node.declaration.type === 'ClassDeclaration' && node.declaration.id) {\n        const start: number =\n          node.declaration.decorators && node.declaration.decorators.length > 0\n            ? node.declaration.decorators[\n                node.declaration.decorators.length - 1\n              ].end!\n            : node.start!\n        s.overwrite(start, node.declaration.id.start!, ` class `)\n        s.append(`\\nconst ${as} = ${node.declaration.id.name}`)\n      } else {\n        s.overwrite(node.start!, node.declaration.start!, `const ${as} = `)\n      }\n    } else if (node.type === 'ExportNamedDeclaration') {\n      for (const specifier of node.specifiers) {\n        if (\n          specifier.type === 'ExportSpecifier' &&\n          specifier.exported.type === 'Identifier' &&\n          specifier.exported.name === 'default'\n        ) {\n          if (node.source) {\n            if (specifier.local.name === 'default') {\n              s.prepend(\n                `import { default as __VUE_DEFAULT__ } from '${node.source.value}'\\n`,\n              )\n              const end = specifierEnd(s, specifier.local.end!, node.end!)\n              s.remove(specifier.start!, end)\n              s.append(`\\nconst ${as} = __VUE_DEFAULT__`)\n              continue\n            } else {\n              s.prepend(\n                `import { ${s.slice(\n                  specifier.local.start!,\n                  specifier.local.end!,\n                )} as __VUE_DEFAULT__ } from '${node.source.value}'\\n`,\n              )\n              const end = specifierEnd(s, specifier.exported.end!, node.end!)\n              s.remove(specifier.start!, end)\n              s.append(`\\nconst ${as} = __VUE_DEFAULT__`)\n              continue\n            }\n          }\n\n          const end = specifierEnd(s, specifier.end!, node.end!)\n          s.remove(specifier.start!, end)\n          s.append(`\\nconst ${as} = ${specifier.local.name}`)\n        }\n      }\n    }\n  })\n}\n\nexport function hasDefaultExport(ast: Statement[]): boolean {\n  for (const stmt of ast) {\n    if (stmt.type === 'ExportDefaultDeclaration') {\n      return true\n    } else if (\n      stmt.type === 'ExportNamedDeclaration' &&\n      stmt.specifiers.some(\n        spec => (spec.exported as Identifier).name === 'default',\n      )\n    ) {\n      return true\n    }\n  }\n  return false\n}\n\nfunction specifierEnd(s: MagicString, end: number, nodeEnd: number | null) {\n  // export { default   , foo } ...\n  let hasCommas = false\n  let oldEnd = end\n  while (end < nodeEnd!) {\n    if (/\\s/.test(s.slice(end, end + 1))) {\n      end++\n    } else if (s.slice(end, end + 1) === ',') {\n      end++\n      hasCommas = true\n      break\n    } else if (s.slice(end, end + 1) === '}') {\n      break\n    }\n  }\n  return hasCommas ? end : oldEnd\n}\n"
  },
  {
    "path": "packages/compiler-sfc/src/script/analyzeScriptBindings.ts",
    "content": "import type {\n  ArrayExpression,\n  Node,\n  ObjectExpression,\n  Statement,\n} from '@babel/types'\nimport { type BindingMetadata, BindingTypes } from '@vue/compiler-dom'\nimport { resolveObjectKey } from './utils'\n\n/**\n * Analyze bindings in normal `<script>`\n * Note that `compileScriptSetup` already analyzes bindings as part of its\n * compilation process so this should only be used on single `<script>` SFCs.\n */\nexport function analyzeScriptBindings(ast: Statement[]): BindingMetadata {\n  for (const node of ast) {\n    if (\n      node.type === 'ExportDefaultDeclaration' &&\n      node.declaration.type === 'ObjectExpression'\n    ) {\n      return analyzeBindingsFromOptions(node.declaration)\n    }\n  }\n  return {}\n}\n\nfunction analyzeBindingsFromOptions(node: ObjectExpression): BindingMetadata {\n  const bindings: BindingMetadata = {}\n  // #3270, #3275\n  // mark non-script-setup so we don't resolve components/directives from these\n  Object.defineProperty(bindings, '__isScriptSetup', {\n    enumerable: false,\n    value: false,\n  })\n  for (const property of node.properties) {\n    if (\n      property.type === 'ObjectProperty' &&\n      !property.computed &&\n      property.key.type === 'Identifier'\n    ) {\n      // props\n      if (property.key.name === 'props') {\n        // props: ['foo']\n        // props: { foo: ... }\n        for (const key of getObjectOrArrayExpressionKeys(property.value)) {\n          bindings[key] = BindingTypes.PROPS\n        }\n      }\n\n      // inject\n      else if (property.key.name === 'inject') {\n        // inject: ['foo']\n        // inject: { foo: {} }\n        for (const key of getObjectOrArrayExpressionKeys(property.value)) {\n          bindings[key] = BindingTypes.OPTIONS\n        }\n      }\n\n      // computed & methods\n      else if (\n        property.value.type === 'ObjectExpression' &&\n        (property.key.name === 'computed' || property.key.name === 'methods')\n      ) {\n        // methods: { foo() {} }\n        // computed: { foo() {} }\n        for (const key of getObjectExpressionKeys(property.value)) {\n          bindings[key] = BindingTypes.OPTIONS\n        }\n      }\n    }\n\n    // setup & data\n    else if (\n      property.type === 'ObjectMethod' &&\n      property.key.type === 'Identifier' &&\n      (property.key.name === 'setup' || property.key.name === 'data')\n    ) {\n      for (const bodyItem of property.body.body) {\n        // setup() {\n        //   return {\n        //     foo: null\n        //   }\n        // }\n        if (\n          bodyItem.type === 'ReturnStatement' &&\n          bodyItem.argument &&\n          bodyItem.argument.type === 'ObjectExpression'\n        ) {\n          for (const key of getObjectExpressionKeys(bodyItem.argument)) {\n            bindings[key] =\n              property.key.name === 'setup'\n                ? BindingTypes.SETUP_MAYBE_REF\n                : BindingTypes.DATA\n          }\n        }\n      }\n    }\n  }\n\n  return bindings\n}\n\nfunction getObjectExpressionKeys(node: ObjectExpression): string[] {\n  const keys = []\n  for (const prop of node.properties) {\n    if (prop.type === 'SpreadElement') continue\n    const key = resolveObjectKey(prop.key, prop.computed)\n    if (key) keys.push(String(key))\n  }\n  return keys\n}\n\nfunction getArrayExpressionKeys(node: ArrayExpression): string[] {\n  const keys = []\n  for (const element of node.elements) {\n    if (element && element.type === 'StringLiteral') {\n      keys.push(element.value)\n    }\n  }\n  return keys\n}\n\nexport function getObjectOrArrayExpressionKeys(value: Node): string[] {\n  if (value.type === 'ArrayExpression') {\n    return getArrayExpressionKeys(value)\n  }\n  if (value.type === 'ObjectExpression') {\n    return getObjectExpressionKeys(value)\n  }\n  return []\n}\n"
  },
  {
    "path": "packages/compiler-sfc/src/script/context.ts",
    "content": "import type { CallExpression, Node, ObjectPattern, Program } from '@babel/types'\nimport type { SFCDescriptor } from '../parse'\nimport { generateCodeFrame, isArray } from '@vue/shared'\nimport { type ParserPlugin, parse as babelParse } from '@babel/parser'\nimport type { ImportBinding, SFCScriptCompileOptions } from '../compileScript'\nimport type { PropsDestructureBindings } from './defineProps'\nimport type { ModelDecl } from './defineModel'\nimport type { BindingMetadata } from '../../../compiler-core/src'\nimport MagicString from 'magic-string'\nimport type { TypeScope } from './resolveType'\nimport { warn } from '../warn'\nimport { isJS, isTS } from './utils'\n\nexport class ScriptCompileContext {\n  isJS: boolean\n  isTS: boolean\n  isCE = false\n\n  scriptAst: Program | null\n  scriptSetupAst: Program | null\n\n  source: string = this.descriptor.source\n  filename: string = this.descriptor.filename\n  s: MagicString = new MagicString(this.source)\n  startOffset: number | undefined =\n    this.descriptor.scriptSetup?.loc.start.offset\n  endOffset: number | undefined = this.descriptor.scriptSetup?.loc.end.offset\n\n  // import / type analysis\n  scope?: TypeScope\n  globalScopes?: TypeScope[]\n  userImports: Record<string, ImportBinding> = Object.create(null)\n\n  // macros presence check\n  hasDefinePropsCall = false\n  hasDefineEmitCall = false\n  hasDefineExposeCall = false\n  hasDefaultExportName = false\n  hasDefaultExportRender = false\n  hasDefineOptionsCall = false\n  hasDefineSlotsCall = false\n  hasDefineModelCall = false\n\n  // defineProps\n  propsCall: CallExpression | undefined\n  propsDecl: Node | undefined\n  propsRuntimeDecl: Node | undefined\n  propsTypeDecl: Node | undefined\n  propsDestructureDecl: ObjectPattern | undefined\n  propsDestructuredBindings: PropsDestructureBindings = Object.create(null)\n  propsDestructureRestId: string | undefined\n  propsRuntimeDefaults: Node | undefined\n\n  // defineEmits\n  emitsRuntimeDecl: Node | undefined\n  emitsTypeDecl: Node | undefined\n  emitDecl: Node | undefined\n\n  // defineModel\n  modelDecls: Record<string, ModelDecl> = Object.create(null)\n\n  // defineOptions\n  optionsRuntimeDecl: Node | undefined\n\n  // codegen\n  bindingMetadata: BindingMetadata = {}\n  helperImports: Set<string> = new Set()\n  helper(key: string): string {\n    this.helperImports.add(key)\n    return `_${key}`\n  }\n\n  /**\n   * to be exposed on compiled script block for HMR cache busting\n   */\n  deps?: Set<string>\n\n  /**\n   * cache for resolved fs\n   */\n  fs?: NonNullable<SFCScriptCompileOptions['fs']>\n\n  constructor(\n    public descriptor: SFCDescriptor,\n    public options: Partial<SFCScriptCompileOptions>,\n  ) {\n    const { script, scriptSetup } = descriptor\n    const scriptLang = script && script.lang\n    const scriptSetupLang = scriptSetup && scriptSetup.lang\n\n    this.isJS = isJS(scriptLang, scriptSetupLang)\n    this.isTS = isTS(scriptLang, scriptSetupLang)\n\n    const customElement = options.customElement\n    const filename = this.descriptor.filename\n    if (customElement) {\n      this.isCE =\n        typeof customElement === 'boolean'\n          ? customElement\n          : customElement(filename)\n    }\n    // resolve parser plugins\n    const plugins: ParserPlugin[] = resolveParserPlugins(\n      (scriptLang || scriptSetupLang)!,\n      options.babelParserPlugins,\n    )\n\n    function parse(input: string, offset: number): Program {\n      try {\n        return babelParse(input, {\n          plugins,\n          sourceType: 'module',\n        }).program\n      } catch (e: any) {\n        e.message = `[vue/compiler-sfc] ${e.message}\\n\\n${\n          descriptor.filename\n        }\\n${generateCodeFrame(\n          descriptor.source,\n          e.pos + offset,\n          e.pos + offset + 1,\n        )}`\n        throw e\n      }\n    }\n\n    this.scriptAst =\n      descriptor.script &&\n      parse(descriptor.script.content, descriptor.script.loc.start.offset)\n\n    this.scriptSetupAst =\n      descriptor.scriptSetup &&\n      parse(descriptor.scriptSetup!.content, this.startOffset!)\n  }\n\n  getString(node: Node, scriptSetup = true): string {\n    const block = scriptSetup\n      ? this.descriptor.scriptSetup!\n      : this.descriptor.script!\n    return block.content.slice(node.start!, node.end!)\n  }\n\n  warn(msg: string, node: Node, scope?: TypeScope): void {\n    warn(generateError(msg, node, this, scope))\n  }\n\n  error(msg: string, node: Node, scope?: TypeScope): never {\n    throw new Error(\n      `[@vue/compiler-sfc] ${generateError(msg, node, this, scope)}`,\n    )\n  }\n}\n\nfunction generateError(\n  msg: string,\n  node: Node,\n  ctx: ScriptCompileContext,\n  scope?: TypeScope,\n) {\n  const offset = scope ? scope.offset : ctx.startOffset!\n  return `${msg}\\n\\n${(scope || ctx.descriptor).filename}\\n${generateCodeFrame(\n    (scope || ctx.descriptor).source,\n    node.start! + offset,\n    node.end! + offset,\n  )}`\n}\n\nexport function resolveParserPlugins(\n  lang: string,\n  userPlugins?: ParserPlugin[],\n  dts = false,\n): ParserPlugin[] {\n  const plugins: ParserPlugin[] = []\n  if (\n    !userPlugins ||\n    !userPlugins.some(\n      p =>\n        p === 'importAssertions' ||\n        p === 'importAttributes' ||\n        (isArray(p) && p[0] === 'importAttributes'),\n    )\n  ) {\n    plugins.push('importAttributes')\n  }\n  if (lang === 'jsx' || lang === 'tsx' || lang === 'mtsx') {\n    plugins.push('jsx')\n  } else if (userPlugins) {\n    // If don't match the case of adding jsx\n    // should remove the jsx from user options\n    userPlugins = userPlugins.filter(p => p !== 'jsx')\n  }\n  if (\n    lang === 'ts' ||\n    lang === 'mts' ||\n    lang === 'tsx' ||\n    lang === 'cts' ||\n    lang === 'mtsx'\n  ) {\n    plugins.push(['typescript', { dts }], 'explicitResourceManagement')\n    if (!userPlugins || !userPlugins.includes('decorators')) {\n      plugins.push('decorators-legacy')\n    }\n  }\n  if (userPlugins) {\n    plugins.push(...userPlugins)\n  }\n  return plugins\n}\n"
  },
  {
    "path": "packages/compiler-sfc/src/script/defineEmits.ts",
    "content": "import type {\n  ArrayPattern,\n  Identifier,\n  LVal,\n  Node,\n  ObjectPattern,\n  RestElement,\n} from '@babel/types'\nimport { isCallOf } from './utils'\nimport type { ScriptCompileContext } from './context'\nimport {\n  type TypeResolveContext,\n  resolveTypeElements,\n  resolveUnionType,\n} from './resolveType'\n\nexport const DEFINE_EMITS = 'defineEmits'\n\nexport function processDefineEmits(\n  ctx: ScriptCompileContext,\n  node: Node,\n  declId?: LVal,\n): boolean {\n  if (!isCallOf(node, DEFINE_EMITS)) {\n    return false\n  }\n  if (ctx.hasDefineEmitCall) {\n    ctx.error(`duplicate ${DEFINE_EMITS}() call`, node)\n  }\n  ctx.hasDefineEmitCall = true\n  ctx.emitsRuntimeDecl = node.arguments[0]\n  if (node.typeParameters) {\n    if (ctx.emitsRuntimeDecl) {\n      ctx.error(\n        `${DEFINE_EMITS}() cannot accept both type and non-type arguments ` +\n          `at the same time. Use one or the other.`,\n        node,\n      )\n    }\n    ctx.emitsTypeDecl = node.typeParameters.params[0]\n  }\n\n  ctx.emitDecl = declId\n\n  return true\n}\n\nexport function genRuntimeEmits(ctx: ScriptCompileContext): string | undefined {\n  let emitsDecl = ''\n  if (ctx.emitsRuntimeDecl) {\n    emitsDecl = ctx.getString(ctx.emitsRuntimeDecl).trim()\n  } else if (ctx.emitsTypeDecl) {\n    const typeDeclaredEmits = extractRuntimeEmits(ctx)\n    emitsDecl = typeDeclaredEmits.size\n      ? `[${Array.from(typeDeclaredEmits)\n          .map(k => JSON.stringify(k))\n          .join(', ')}]`\n      : ``\n  }\n  if (ctx.hasDefineModelCall) {\n    let modelEmitsDecl = `[${Object.keys(ctx.modelDecls)\n      .map(n => JSON.stringify(`update:${n}`))\n      .join(', ')}]`\n    emitsDecl = emitsDecl\n      ? `/*@__PURE__*/${ctx.helper(\n          'mergeModels',\n        )}(${emitsDecl}, ${modelEmitsDecl})`\n      : modelEmitsDecl\n  }\n  return emitsDecl\n}\n\nexport function extractRuntimeEmits(ctx: TypeResolveContext): Set<string> {\n  const emits = new Set<string>()\n  const node = ctx.emitsTypeDecl!\n\n  if (node.type === 'TSFunctionType') {\n    extractEventNames(ctx, node.parameters[0], emits)\n    return emits\n  }\n\n  const { props, calls } = resolveTypeElements(ctx, node)\n\n  let hasProperty = false\n  for (const key in props) {\n    emits.add(key)\n    hasProperty = true\n  }\n\n  if (calls) {\n    if (hasProperty) {\n      ctx.error(\n        `defineEmits() type cannot mixed call signature and property syntax.`,\n        node,\n      )\n    }\n    for (const call of calls) {\n      extractEventNames(ctx, call.parameters[0], emits)\n    }\n  }\n\n  return emits\n}\n\nfunction extractEventNames(\n  ctx: TypeResolveContext,\n  eventName: ArrayPattern | Identifier | ObjectPattern | RestElement,\n  emits: Set<string>,\n) {\n  if (\n    eventName.type === 'Identifier' &&\n    eventName.typeAnnotation &&\n    eventName.typeAnnotation.type === 'TSTypeAnnotation'\n  ) {\n    const types = resolveUnionType(ctx, eventName.typeAnnotation.typeAnnotation)\n\n    for (const type of types) {\n      if (type.type === 'TSLiteralType') {\n        if (\n          type.literal.type !== 'UnaryExpression' &&\n          type.literal.type !== 'TemplateLiteral'\n        ) {\n          emits.add(String(type.literal.value))\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "packages/compiler-sfc/src/script/defineExpose.ts",
    "content": "import type { Node } from '@babel/types'\nimport { isCallOf } from './utils'\nimport type { ScriptCompileContext } from './context'\n\nexport const DEFINE_EXPOSE = 'defineExpose'\n\nexport function processDefineExpose(\n  ctx: ScriptCompileContext,\n  node: Node,\n): boolean {\n  if (isCallOf(node, DEFINE_EXPOSE)) {\n    if (ctx.hasDefineExposeCall) {\n      ctx.error(`duplicate ${DEFINE_EXPOSE}() call`, node)\n    }\n    ctx.hasDefineExposeCall = true\n    return true\n  }\n  return false\n}\n"
  },
  {
    "path": "packages/compiler-sfc/src/script/defineModel.ts",
    "content": "import type { LVal, Node, TSType } from '@babel/types'\nimport type { ScriptCompileContext } from './context'\nimport { inferRuntimeType } from './resolveType'\nimport { UNKNOWN_TYPE, isCallOf, toRuntimeTypeString } from './utils'\nimport { BindingTypes, unwrapTSNode } from '@vue/compiler-dom'\n\nexport const DEFINE_MODEL = 'defineModel'\n\nexport interface ModelDecl {\n  type: TSType | undefined\n  options: string | undefined\n  identifier: string | undefined\n  runtimeOptionNodes: Node[]\n}\n\nexport function processDefineModel(\n  ctx: ScriptCompileContext,\n  node: Node,\n  declId?: LVal,\n): boolean {\n  if (!isCallOf(node, DEFINE_MODEL)) {\n    return false\n  }\n\n  ctx.hasDefineModelCall = true\n\n  const type =\n    (node.typeParameters && node.typeParameters.params[0]) || undefined\n  let modelName: string\n  let options: Node | undefined\n  const arg0 = node.arguments[0] && unwrapTSNode(node.arguments[0])\n  const hasName = arg0 && arg0.type === 'StringLiteral'\n  if (hasName) {\n    modelName = arg0.value\n    options = node.arguments[1]\n  } else {\n    modelName = 'modelValue'\n    options = arg0\n  }\n\n  if (ctx.modelDecls[modelName]) {\n    ctx.error(`duplicate model name ${JSON.stringify(modelName)}`, node)\n  }\n\n  let optionsString = options && ctx.getString(options)\n  let optionsRemoved = !options\n  const runtimeOptionNodes: Node[] = []\n\n  if (\n    options &&\n    options.type === 'ObjectExpression' &&\n    !options.properties.some(p => p.type === 'SpreadElement' || p.computed)\n  ) {\n    let removed = 0\n    for (let i = options.properties.length - 1; i >= 0; i--) {\n      const p = options.properties[i]\n      const next = options.properties[i + 1]\n      const start = p.start!\n      const end = next ? next.start! : options.end! - 1\n      if (\n        (p.type === 'ObjectProperty' || p.type === 'ObjectMethod') &&\n        ((p.key.type === 'Identifier' &&\n          (p.key.name === 'get' || p.key.name === 'set')) ||\n          (p.key.type === 'StringLiteral' &&\n            (p.key.value === 'get' || p.key.value === 'set')))\n      ) {\n        // remove runtime-only options from prop options to avoid duplicates\n        optionsString =\n          optionsString.slice(0, start - options.start!) +\n          optionsString.slice(end - options.start!)\n      } else {\n        // remove prop options from runtime options\n        removed++\n        ctx.s.remove(ctx.startOffset! + start, ctx.startOffset! + end)\n        // record prop options for invalid scope var reference check\n        runtimeOptionNodes.push(p)\n      }\n    }\n    if (removed === options.properties.length) {\n      optionsRemoved = true\n      ctx.s.remove(\n        ctx.startOffset! + (hasName ? arg0.end! : options.start!),\n        ctx.startOffset! + options.end!,\n      )\n    }\n  }\n\n  ctx.modelDecls[modelName] = {\n    type,\n    options: optionsString,\n    runtimeOptionNodes,\n    identifier:\n      declId && declId.type === 'Identifier' ? declId.name : undefined,\n  }\n  // register binding type\n  ctx.bindingMetadata[modelName] = BindingTypes.PROPS\n\n  // defineModel -> useModel\n  ctx.s.overwrite(\n    ctx.startOffset! + node.callee.start!,\n    ctx.startOffset! + node.callee.end!,\n    ctx.helper('useModel'),\n  )\n  // inject arguments\n  ctx.s.appendLeft(\n    ctx.startOffset! +\n      (node.arguments.length ? node.arguments[0].start! : node.end! - 1),\n    `__props, ` +\n      (hasName\n        ? ``\n        : `${JSON.stringify(modelName)}${optionsRemoved ? `` : `, `}`),\n  )\n\n  return true\n}\n\nexport function genModelProps(ctx: ScriptCompileContext): string | undefined {\n  if (!ctx.hasDefineModelCall) return\n\n  const isProd = !!ctx.options.isProd\n  let modelPropsDecl = ''\n  for (const [name, { type, options: runtimeOptions }] of Object.entries(\n    ctx.modelDecls,\n  )) {\n    let skipCheck = false\n    let codegenOptions = ``\n    let runtimeTypes = type && inferRuntimeType(ctx, type)\n    if (runtimeTypes) {\n      const hasBoolean = runtimeTypes.includes('Boolean')\n      const hasFunction = runtimeTypes.includes('Function')\n      const hasUnknownType = runtimeTypes.includes(UNKNOWN_TYPE)\n\n      if (hasUnknownType) {\n        if (hasBoolean || hasFunction) {\n          runtimeTypes = runtimeTypes.filter(t => t !== UNKNOWN_TYPE)\n          skipCheck = true\n        } else {\n          runtimeTypes = ['null']\n        }\n      }\n\n      if (!isProd) {\n        codegenOptions =\n          `type: ${toRuntimeTypeString(runtimeTypes)}` +\n          (skipCheck ? ', skipCheck: true' : '')\n      } else if (hasBoolean || (runtimeOptions && hasFunction)) {\n        // preserve types if contains boolean, or\n        // function w/ runtime options that may contain default\n        codegenOptions = `type: ${toRuntimeTypeString(runtimeTypes)}`\n      } else {\n        // able to drop types in production\n      }\n    }\n\n    let decl: string\n    if (codegenOptions && runtimeOptions) {\n      decl = ctx.isTS\n        ? `{ ${codegenOptions}, ...${runtimeOptions} }`\n        : `Object.assign({ ${codegenOptions} }, ${runtimeOptions})`\n    } else if (codegenOptions) {\n      decl = `{ ${codegenOptions} }`\n    } else if (runtimeOptions) {\n      decl = runtimeOptions\n    } else {\n      decl = `{}`\n    }\n    modelPropsDecl += `\\n    ${JSON.stringify(name)}: ${decl},`\n\n    // also generate modifiers prop\n    const modifierPropName = JSON.stringify(\n      name === 'modelValue' ? `modelModifiers` : `${name}Modifiers`,\n    )\n    modelPropsDecl += `\\n    ${modifierPropName}: {},`\n  }\n  return `{${modelPropsDecl}\\n  }`\n}\n"
  },
  {
    "path": "packages/compiler-sfc/src/script/defineOptions.ts",
    "content": "import type { Node } from '@babel/types'\nimport { unwrapTSNode } from '@vue/compiler-dom'\nimport type { ScriptCompileContext } from './context'\nimport { isCallOf } from './utils'\nimport { DEFINE_PROPS } from './defineProps'\nimport { DEFINE_EMITS } from './defineEmits'\nimport { DEFINE_EXPOSE } from './defineExpose'\nimport { DEFINE_SLOTS } from './defineSlots'\n\nexport const DEFINE_OPTIONS = 'defineOptions'\n\nexport function processDefineOptions(\n  ctx: ScriptCompileContext,\n  node: Node,\n): boolean {\n  if (!isCallOf(node, DEFINE_OPTIONS)) {\n    return false\n  }\n  if (ctx.hasDefineOptionsCall) {\n    ctx.error(`duplicate ${DEFINE_OPTIONS}() call`, node)\n  }\n  if (node.typeParameters) {\n    ctx.error(`${DEFINE_OPTIONS}() cannot accept type arguments`, node)\n  }\n  if (!node.arguments[0]) return true\n\n  ctx.hasDefineOptionsCall = true\n  ctx.optionsRuntimeDecl = unwrapTSNode(node.arguments[0])\n\n  let propsOption = undefined\n  let emitsOption = undefined\n  let exposeOption = undefined\n  let slotsOption = undefined\n  if (ctx.optionsRuntimeDecl.type === 'ObjectExpression') {\n    for (const prop of ctx.optionsRuntimeDecl.properties) {\n      if (\n        (prop.type === 'ObjectProperty' || prop.type === 'ObjectMethod') &&\n        prop.key.type === 'Identifier'\n      ) {\n        switch (prop.key.name) {\n          case 'props':\n            propsOption = prop\n            break\n\n          case 'emits':\n            emitsOption = prop\n            break\n\n          case 'expose':\n            exposeOption = prop\n            break\n\n          case 'slots':\n            slotsOption = prop\n            break\n        }\n      }\n    }\n  }\n\n  if (propsOption) {\n    ctx.error(\n      `${DEFINE_OPTIONS}() cannot be used to declare props. Use ${DEFINE_PROPS}() instead.`,\n      propsOption,\n    )\n  }\n  if (emitsOption) {\n    ctx.error(\n      `${DEFINE_OPTIONS}() cannot be used to declare emits. Use ${DEFINE_EMITS}() instead.`,\n      emitsOption,\n    )\n  }\n  if (exposeOption) {\n    ctx.error(\n      `${DEFINE_OPTIONS}() cannot be used to declare expose. Use ${DEFINE_EXPOSE}() instead.`,\n      exposeOption,\n    )\n  }\n  if (slotsOption) {\n    ctx.error(\n      `${DEFINE_OPTIONS}() cannot be used to declare slots. Use ${DEFINE_SLOTS}() instead.`,\n      slotsOption,\n    )\n  }\n\n  return true\n}\n"
  },
  {
    "path": "packages/compiler-sfc/src/script/defineProps.ts",
    "content": "import type {\n  Expression,\n  LVal,\n  Node,\n  ObjectExpression,\n  ObjectMethod,\n  ObjectProperty,\n} from '@babel/types'\nimport { BindingTypes, isFunctionType, unwrapTSNode } from '@vue/compiler-dom'\nimport type { ScriptCompileContext } from './context'\nimport {\n  type TypeResolveContext,\n  inferRuntimeType,\n  resolveTypeElements,\n} from './resolveType'\nimport {\n  UNKNOWN_TYPE,\n  concatStrings,\n  getEscapedPropName,\n  isCallOf,\n  isLiteralNode,\n  resolveObjectKey,\n  toRuntimeTypeString,\n} from './utils'\nimport { genModelProps } from './defineModel'\nimport { getObjectOrArrayExpressionKeys } from './analyzeScriptBindings'\nimport { processPropsDestructure } from './definePropsDestructure'\n\nexport const DEFINE_PROPS = 'defineProps'\nexport const WITH_DEFAULTS = 'withDefaults'\n\nexport interface PropTypeData {\n  key: string\n  type: string[]\n  required: boolean\n  skipCheck: boolean\n}\n\nexport type PropsDestructureBindings = Record<\n  string, // public prop key\n  {\n    local: string // local identifier, may be different\n    default?: Expression\n  }\n>\n\nexport function processDefineProps(\n  ctx: ScriptCompileContext,\n  node: Node,\n  declId?: LVal,\n  isWithDefaults = false,\n): boolean {\n  if (!isCallOf(node, DEFINE_PROPS)) {\n    return processWithDefaults(ctx, node, declId)\n  }\n\n  if (ctx.hasDefinePropsCall) {\n    ctx.error(`duplicate ${DEFINE_PROPS}() call`, node)\n  }\n  ctx.hasDefinePropsCall = true\n  ctx.propsRuntimeDecl = node.arguments[0]\n\n  // register bindings\n  if (ctx.propsRuntimeDecl) {\n    for (const key of getObjectOrArrayExpressionKeys(ctx.propsRuntimeDecl)) {\n      if (!(key in ctx.bindingMetadata)) {\n        ctx.bindingMetadata[key] = BindingTypes.PROPS\n      }\n    }\n  }\n\n  // call has type parameters - infer runtime types from it\n  if (node.typeParameters) {\n    if (ctx.propsRuntimeDecl) {\n      ctx.error(\n        `${DEFINE_PROPS}() cannot accept both type and non-type arguments ` +\n          `at the same time. Use one or the other.`,\n        node,\n      )\n    }\n    ctx.propsTypeDecl = node.typeParameters.params[0]\n  }\n\n  // handle props destructure\n  if (!isWithDefaults && declId && declId.type === 'ObjectPattern') {\n    processPropsDestructure(ctx, declId)\n  }\n\n  ctx.propsCall = node\n  ctx.propsDecl = declId\n\n  return true\n}\n\nfunction processWithDefaults(\n  ctx: ScriptCompileContext,\n  node: Node,\n  declId?: LVal,\n): boolean {\n  if (!isCallOf(node, WITH_DEFAULTS)) {\n    return false\n  }\n  if (\n    !processDefineProps(\n      ctx,\n      node.arguments[0],\n      declId,\n      true /* isWithDefaults */,\n    )\n  ) {\n    ctx.error(\n      `${WITH_DEFAULTS}' first argument must be a ${DEFINE_PROPS} call.`,\n      node.arguments[0] || node,\n    )\n  }\n\n  if (ctx.propsRuntimeDecl) {\n    ctx.error(\n      `${WITH_DEFAULTS} can only be used with type-based ` +\n        `${DEFINE_PROPS} declaration.`,\n      node,\n    )\n  }\n  if (declId && declId.type === 'ObjectPattern') {\n    ctx.warn(\n      `${WITH_DEFAULTS}() is unnecessary when using destructure with ${DEFINE_PROPS}().\\n` +\n        `Reactive destructure will be disabled when using withDefaults().\\n` +\n        `Prefer using destructure default values, e.g. const { foo = 1 } = defineProps(...). `,\n      node.callee,\n    )\n  }\n  ctx.propsRuntimeDefaults = node.arguments[1]\n  if (!ctx.propsRuntimeDefaults) {\n    ctx.error(`The 2nd argument of ${WITH_DEFAULTS} is required.`, node)\n  }\n  ctx.propsCall = node\n\n  return true\n}\n\nexport function genRuntimeProps(ctx: ScriptCompileContext): string | undefined {\n  let propsDecls: undefined | string\n\n  if (ctx.propsRuntimeDecl) {\n    propsDecls = ctx.getString(ctx.propsRuntimeDecl).trim()\n    if (ctx.propsDestructureDecl) {\n      const defaults: string[] = []\n      for (const key in ctx.propsDestructuredBindings) {\n        const d = genDestructuredDefaultValue(ctx, key)\n        const finalKey = getEscapedPropName(key)\n        if (d)\n          defaults.push(\n            `${finalKey}: ${d.valueString}${\n              d.needSkipFactory ? `, __skip_${finalKey}: true` : ``\n            }`,\n          )\n      }\n      if (defaults.length) {\n        propsDecls = `/*@__PURE__*/${ctx.helper(\n          `mergeDefaults`,\n        )}(${propsDecls}, {\\n  ${defaults.join(',\\n  ')}\\n})`\n      }\n    }\n  } else if (ctx.propsTypeDecl) {\n    propsDecls = extractRuntimeProps(ctx)\n  }\n\n  const modelsDecls = genModelProps(ctx)\n\n  if (propsDecls && modelsDecls) {\n    return `/*@__PURE__*/${ctx.helper(\n      'mergeModels',\n    )}(${propsDecls}, ${modelsDecls})`\n  } else {\n    return modelsDecls || propsDecls\n  }\n}\n\nexport function extractRuntimeProps(\n  ctx: TypeResolveContext,\n): string | undefined {\n  // this is only called if propsTypeDecl exists\n  const props = resolveRuntimePropsFromType(ctx, ctx.propsTypeDecl!)\n  if (!props.length) {\n    return\n  }\n\n  const propStrings: string[] = []\n  const hasStaticDefaults = hasStaticWithDefaults(ctx)\n\n  for (const prop of props) {\n    propStrings.push(genRuntimePropFromType(ctx, prop, hasStaticDefaults))\n    // register bindings\n    if ('bindingMetadata' in ctx && !(prop.key in ctx.bindingMetadata)) {\n      ctx.bindingMetadata[prop.key] = BindingTypes.PROPS\n    }\n  }\n\n  let propsDecls = `{\n    ${propStrings.join(',\\n    ')}\\n  }`\n\n  if (ctx.propsRuntimeDefaults && !hasStaticDefaults) {\n    propsDecls = `/*@__PURE__*/${ctx.helper(\n      'mergeDefaults',\n    )}(${propsDecls}, ${ctx.getString(ctx.propsRuntimeDefaults)})`\n  }\n\n  return propsDecls\n}\n\nfunction resolveRuntimePropsFromType(\n  ctx: TypeResolveContext,\n  node: Node,\n): PropTypeData[] {\n  const props: PropTypeData[] = []\n  const elements = resolveTypeElements(ctx, node)\n  for (const key in elements.props) {\n    const e = elements.props[key]\n    let type = inferRuntimeType(ctx, e)\n    let skipCheck = false\n    // skip check for result containing unknown types\n    if (type.includes(UNKNOWN_TYPE)) {\n      if (type.includes('Boolean') || type.includes('Function')) {\n        type = type.filter(t => t !== UNKNOWN_TYPE)\n        skipCheck = true\n      } else {\n        type = ['null']\n      }\n    }\n    props.push({\n      key,\n      required: !e.optional,\n      type: type || [`null`],\n      skipCheck,\n    })\n  }\n  return props\n}\n\nfunction genRuntimePropFromType(\n  ctx: TypeResolveContext,\n  { key, required, type, skipCheck }: PropTypeData,\n  hasStaticDefaults: boolean,\n): string {\n  let defaultString: string | undefined\n  const destructured = genDestructuredDefaultValue(ctx, key, type)\n  if (destructured) {\n    defaultString = `default: ${destructured.valueString}${\n      destructured.needSkipFactory ? `, skipFactory: true` : ``\n    }`\n  } else if (hasStaticDefaults) {\n    const prop = (ctx.propsRuntimeDefaults as ObjectExpression).properties.find(\n      node => {\n        if (node.type === 'SpreadElement') return false\n        return resolveObjectKey(node.key, node.computed) === key\n      },\n    ) as ObjectProperty | ObjectMethod\n    if (prop) {\n      if (prop.type === 'ObjectProperty') {\n        // prop has corresponding static default value\n        defaultString = `default: ${ctx.getString(prop.value)}`\n      } else {\n        let paramsString = ''\n        if (prop.params.length) {\n          const start = prop.params[0].start\n          const end = prop.params[prop.params.length - 1].end\n          paramsString = ctx.getString({ start, end } as Node)\n        }\n        defaultString = `${prop.async ? 'async ' : ''}${\n          prop.kind !== 'method' ? `${prop.kind} ` : ''\n        }default(${paramsString}) ${ctx.getString(prop.body)}`\n      }\n    }\n  }\n\n  const finalKey = getEscapedPropName(key)\n  if (!ctx.options.isProd) {\n    return `${finalKey}: { ${concatStrings([\n      `type: ${toRuntimeTypeString(type)}`,\n      `required: ${required}`,\n      skipCheck && 'skipCheck: true',\n      defaultString,\n    ])} }`\n  } else if (\n    type.some(\n      el =>\n        el === 'Boolean' ||\n        ((!hasStaticDefaults || defaultString) && el === 'Function'),\n    )\n  ) {\n    // #4783 for boolean, should keep the type\n    // #7111 for function, if default value exists or it's not static, should keep it\n    // in production\n    return `${finalKey}: { ${concatStrings([\n      `type: ${toRuntimeTypeString(type)}`,\n      defaultString,\n    ])} }`\n  } else {\n    // #8989 for custom element, should keep the type\n    if (ctx.isCE) {\n      if (defaultString) {\n        return `${finalKey}: ${`{ ${defaultString}, type: ${toRuntimeTypeString(\n          type,\n        )} }`}`\n      } else {\n        return `${finalKey}: {type: ${toRuntimeTypeString(type)}}`\n      }\n    }\n\n    // production: checks are useless\n    return `${finalKey}: ${defaultString ? `{ ${defaultString} }` : `{}`}`\n  }\n}\n\n/**\n * check defaults. If the default object is an object literal with only\n * static properties, we can directly generate more optimized default\n * declarations. Otherwise we will have to fallback to runtime merging.\n */\nfunction hasStaticWithDefaults(ctx: TypeResolveContext) {\n  return !!(\n    ctx.propsRuntimeDefaults &&\n    ctx.propsRuntimeDefaults.type === 'ObjectExpression' &&\n    ctx.propsRuntimeDefaults.properties.every(\n      node =>\n        node.type !== 'SpreadElement' &&\n        (!node.computed || node.key.type.endsWith('Literal')),\n    )\n  )\n}\n\nfunction genDestructuredDefaultValue(\n  ctx: TypeResolveContext,\n  key: string,\n  inferredType?: string[],\n):\n  | {\n      valueString: string\n      needSkipFactory: boolean\n    }\n  | undefined {\n  const destructured = ctx.propsDestructuredBindings[key]\n  const defaultVal = destructured && destructured.default\n  if (defaultVal) {\n    const value = ctx.getString(defaultVal)\n    const unwrapped = unwrapTSNode(defaultVal)\n\n    if (inferredType && inferredType.length && !inferredType.includes('null')) {\n      const valueType = inferValueType(unwrapped)\n      if (valueType && !inferredType.includes(valueType)) {\n        ctx.error(\n          `Default value of prop \"${key}\" does not match declared type.`,\n          unwrapped,\n        )\n      }\n    }\n\n    // If the default value is a function or is an identifier referencing\n    // external value, skip factory wrap. This is needed when using\n    // destructure w/ runtime declaration since we cannot safely infer\n    // whether the expected runtime prop type is `Function`.\n    const needSkipFactory =\n      !inferredType &&\n      (isFunctionType(unwrapped) || unwrapped.type === 'Identifier')\n\n    const needFactoryWrap =\n      !needSkipFactory &&\n      !isLiteralNode(unwrapped) &&\n      !inferredType?.includes('Function')\n\n    return {\n      valueString: needFactoryWrap ? `() => (${value})` : value,\n      needSkipFactory,\n    }\n  }\n}\n\n// non-comprehensive, best-effort type inference for a runtime value\n// this is used to catch default value / type declaration mismatches\n// when using props destructure.\nfunction inferValueType(node: Node): string | undefined {\n  switch (node.type) {\n    case 'StringLiteral':\n      return 'String'\n    case 'NumericLiteral':\n      return 'Number'\n    case 'BooleanLiteral':\n      return 'Boolean'\n    case 'ObjectExpression':\n      return 'Object'\n    case 'ArrayExpression':\n      return 'Array'\n    case 'FunctionExpression':\n    case 'ArrowFunctionExpression':\n      return 'Function'\n  }\n}\n"
  },
  {
    "path": "packages/compiler-sfc/src/script/definePropsDestructure.ts",
    "content": "import type {\n  BlockStatement,\n  Expression,\n  Identifier,\n  Node,\n  ObjectPattern,\n  Program,\n  VariableDeclaration,\n} from '@babel/types'\nimport { walk } from 'estree-walker'\nimport {\n  BindingTypes,\n  TS_NODE_TYPES,\n  extractIdentifiers,\n  isFunctionType,\n  isInDestructureAssignment,\n  isReferencedIdentifier,\n  isStaticProperty,\n  unwrapTSNode,\n  walkFunctionParams,\n} from '@vue/compiler-dom'\nimport { genPropsAccessExp } from '@vue/shared'\nimport { isCallOf, resolveObjectKey } from './utils'\nimport type { ScriptCompileContext } from './context'\nimport { DEFINE_PROPS } from './defineProps'\n\nexport function processPropsDestructure(\n  ctx: ScriptCompileContext,\n  declId: ObjectPattern,\n): void {\n  if (ctx.options.propsDestructure === 'error') {\n    ctx.error(`Props destructure is explicitly prohibited via config.`, declId)\n  } else if (ctx.options.propsDestructure === false) {\n    return\n  }\n\n  ctx.propsDestructureDecl = declId\n\n  const registerBinding = (\n    key: string,\n    local: string,\n    defaultValue?: Expression,\n  ) => {\n    ctx.propsDestructuredBindings[key] = { local, default: defaultValue }\n    if (local !== key) {\n      ctx.bindingMetadata[local] = BindingTypes.PROPS_ALIASED\n      ;(ctx.bindingMetadata.__propsAliases ||\n        (ctx.bindingMetadata.__propsAliases = {}))[local] = key\n    }\n  }\n\n  for (const prop of declId.properties) {\n    if (prop.type === 'ObjectProperty') {\n      const propKey = resolveObjectKey(prop.key, prop.computed)\n\n      if (!propKey) {\n        ctx.error(\n          `${DEFINE_PROPS}() destructure cannot use computed key.`,\n          prop.key,\n        )\n      }\n\n      if (prop.value.type === 'AssignmentPattern') {\n        // default value { foo = 123 }\n        const { left, right } = prop.value\n        if (left.type !== 'Identifier') {\n          ctx.error(\n            `${DEFINE_PROPS}() destructure does not support nested patterns.`,\n            left,\n          )\n        }\n        registerBinding(propKey, left.name, right)\n      } else if (prop.value.type === 'Identifier') {\n        // simple destructure\n        registerBinding(propKey, prop.value.name)\n      } else {\n        ctx.error(\n          `${DEFINE_PROPS}() destructure does not support nested patterns.`,\n          prop.value,\n        )\n      }\n    } else {\n      // rest spread\n      ctx.propsDestructureRestId = (prop.argument as Identifier).name\n      // register binding\n      ctx.bindingMetadata[ctx.propsDestructureRestId] =\n        BindingTypes.SETUP_REACTIVE_CONST\n    }\n  }\n}\n\n/**\n * true -> prop binding\n * false -> local binding\n */\ntype Scope = Record<string, boolean>\n\nexport function transformDestructuredProps(\n  ctx: ScriptCompileContext,\n  vueImportAliases: Record<string, string>,\n): void {\n  if (ctx.options.propsDestructure === false) {\n    return\n  }\n\n  const rootScope: Scope = Object.create(null)\n  const scopeStack: Scope[] = [rootScope]\n  let currentScope: Scope = rootScope\n  const excludedIds = new WeakSet<Identifier>()\n  const parentStack: Node[] = []\n  const propsLocalToPublicMap: Record<string, string> = Object.create(null)\n\n  for (const key in ctx.propsDestructuredBindings) {\n    const { local } = ctx.propsDestructuredBindings[key]\n    rootScope[local] = true\n    propsLocalToPublicMap[local] = key\n  }\n\n  function pushScope() {\n    scopeStack.push((currentScope = Object.create(currentScope)))\n  }\n\n  function popScope() {\n    scopeStack.pop()\n    currentScope = scopeStack[scopeStack.length - 1] || null\n  }\n\n  function registerLocalBinding(id: Identifier) {\n    excludedIds.add(id)\n    if (currentScope) {\n      currentScope[id.name] = false\n    } else {\n      ctx.error(\n        'registerBinding called without active scope, something is wrong.',\n        id,\n      )\n    }\n  }\n\n  function walkScope(node: Program | BlockStatement, isRoot = false) {\n    for (const stmt of node.body) {\n      if (stmt.type === 'VariableDeclaration') {\n        walkVariableDeclaration(stmt, isRoot)\n      } else if (\n        stmt.type === 'FunctionDeclaration' ||\n        stmt.type === 'ClassDeclaration'\n      ) {\n        if (stmt.declare || !stmt.id) continue\n        registerLocalBinding(stmt.id)\n      } else if (\n        stmt.type === 'ExportNamedDeclaration' &&\n        stmt.declaration &&\n        stmt.declaration.type === 'VariableDeclaration'\n      ) {\n        walkVariableDeclaration(stmt.declaration, isRoot)\n      } else if (\n        stmt.type === 'LabeledStatement' &&\n        stmt.body.type === 'VariableDeclaration'\n      ) {\n        walkVariableDeclaration(stmt.body, isRoot)\n      }\n    }\n  }\n\n  function walkVariableDeclaration(stmt: VariableDeclaration, isRoot = false) {\n    if (stmt.declare) {\n      return\n    }\n    for (const decl of stmt.declarations) {\n      const isDefineProps =\n        isRoot && decl.init && isCallOf(unwrapTSNode(decl.init), 'defineProps')\n      for (const id of extractIdentifiers(decl.id)) {\n        if (isDefineProps) {\n          // for defineProps destructure, only exclude them since they\n          // are already passed in as knownProps\n          excludedIds.add(id)\n        } else {\n          registerLocalBinding(id)\n        }\n      }\n    }\n  }\n\n  function rewriteId(id: Identifier, parent: Node, parentStack: Node[]) {\n    if (\n      (parent.type === 'AssignmentExpression' && id === parent.left) ||\n      parent.type === 'UpdateExpression'\n    ) {\n      ctx.error(`Cannot assign to destructured props as they are readonly.`, id)\n    }\n\n    if (isStaticProperty(parent) && parent.shorthand) {\n      // let binding used in a property shorthand\n      // skip for destructure patterns\n      if (\n        !(parent as any).inPattern ||\n        isInDestructureAssignment(parent, parentStack)\n      ) {\n        // { prop } -> { prop: __props.prop }\n        ctx.s.appendLeft(\n          id.end! + ctx.startOffset!,\n          `: ${genPropsAccessExp(propsLocalToPublicMap[id.name])}`,\n        )\n      }\n    } else {\n      // x --> __props.x\n      ctx.s.overwrite(\n        id.start! + ctx.startOffset!,\n        id.end! + ctx.startOffset!,\n        genPropsAccessExp(propsLocalToPublicMap[id.name]),\n      )\n    }\n  }\n\n  function checkUsage(node: Node, method: string, alias = method) {\n    if (isCallOf(node, alias)) {\n      const arg = unwrapTSNode(node.arguments[0])\n      if (arg.type === 'Identifier' && currentScope[arg.name]) {\n        ctx.error(\n          `\"${arg.name}\" is a destructured prop and should not be passed directly to ${method}(). ` +\n            `Pass a getter () => ${arg.name} instead.`,\n          arg,\n        )\n      }\n    }\n  }\n\n  // check root scope first\n  const ast = ctx.scriptSetupAst!\n  walkScope(ast, true)\n  walk(ast, {\n    enter(node: Node, parent: Node | null) {\n      parent && parentStack.push(parent)\n\n      // skip type nodes\n      if (\n        parent &&\n        parent.type.startsWith('TS') &&\n        !TS_NODE_TYPES.includes(parent.type)\n      ) {\n        return this.skip()\n      }\n\n      checkUsage(node, 'watch', vueImportAliases.watch)\n      checkUsage(node, 'toRef', vueImportAliases.toRef)\n\n      // function scopes\n      if (isFunctionType(node)) {\n        pushScope()\n        walkFunctionParams(node, registerLocalBinding)\n        if (node.body.type === 'BlockStatement') {\n          walkScope(node.body)\n        }\n        return\n      }\n\n      // catch param\n      if (node.type === 'CatchClause') {\n        pushScope()\n        if (node.param && node.param.type === 'Identifier') {\n          registerLocalBinding(node.param)\n        }\n        walkScope(node.body)\n        return\n      }\n\n      // for loops: loop variable should be scoped to the loop\n      if (\n        node.type === 'ForOfStatement' ||\n        node.type === 'ForInStatement' ||\n        node.type === 'ForStatement'\n      ) {\n        pushScope()\n        const varDecl = node.type === 'ForStatement' ? node.init : node.left\n        if (varDecl && varDecl.type === 'VariableDeclaration') {\n          walkVariableDeclaration(varDecl)\n        }\n        if (node.body.type === 'BlockStatement') {\n          walkScope(node.body)\n        }\n        return\n      }\n\n      // non-function block scopes\n      if (node.type === 'BlockStatement' && !isFunctionType(parent!)) {\n        pushScope()\n        walkScope(node)\n        return\n      }\n\n      if (node.type === 'Identifier') {\n        if (\n          isReferencedIdentifier(node, parent!, parentStack) &&\n          !excludedIds.has(node)\n        ) {\n          if (currentScope[node.name]) {\n            rewriteId(node, parent!, parentStack)\n          }\n        }\n      }\n    },\n    leave(node: Node, parent: Node | null) {\n      parent && parentStack.pop()\n      if (\n        (node.type === 'BlockStatement' && !isFunctionType(parent!)) ||\n        isFunctionType(node) ||\n        node.type === 'CatchClause' ||\n        node.type === 'ForOfStatement' ||\n        node.type === 'ForInStatement' ||\n        node.type === 'ForStatement'\n      ) {\n        popScope()\n      }\n    },\n  })\n}\n"
  },
  {
    "path": "packages/compiler-sfc/src/script/defineSlots.ts",
    "content": "import type { LVal, Node } from '@babel/types'\nimport { isCallOf } from './utils'\nimport type { ScriptCompileContext } from './context'\n\nexport const DEFINE_SLOTS = 'defineSlots'\n\nexport function processDefineSlots(\n  ctx: ScriptCompileContext,\n  node: Node,\n  declId?: LVal,\n): boolean {\n  if (!isCallOf(node, DEFINE_SLOTS)) {\n    return false\n  }\n  if (ctx.hasDefineSlotsCall) {\n    ctx.error(`duplicate ${DEFINE_SLOTS}() call`, node)\n  }\n  ctx.hasDefineSlotsCall = true\n\n  if (node.arguments.length > 0) {\n    ctx.error(`${DEFINE_SLOTS}() cannot accept arguments`, node)\n  }\n\n  if (declId) {\n    ctx.s.overwrite(\n      ctx.startOffset! + node.start!,\n      ctx.startOffset! + node.end!,\n      `${ctx.helper('useSlots')}()`,\n    )\n  }\n\n  return true\n}\n"
  },
  {
    "path": "packages/compiler-sfc/src/script/importUsageCheck.ts",
    "content": "import type { SFCDescriptor } from '../parse'\nimport {\n  type ExpressionNode,\n  NodeTypes,\n  type SimpleExpressionNode,\n  type TemplateChildNode,\n  isSimpleIdentifier,\n  parserOptions,\n  walkIdentifiers,\n} from '@vue/compiler-dom'\nimport { createCache } from '../cache'\nimport { camelize, capitalize, isBuiltInDirective } from '@vue/shared'\n\n/**\n * Check if an import is used in the SFC's template. This is used to determine\n * the properties that should be included in the object returned from setup()\n * when not using inline mode.\n */\nexport function isImportUsed(local: string, sfc: SFCDescriptor): boolean {\n  return resolveTemplateUsedIdentifiers(sfc).has(local)\n}\n\nconst templateAnalysisCache = createCache<{\n  usedIds?: Set<string>\n  vModelIds: Set<string>\n}>()\n\nexport function resolveTemplateVModelIdentifiers(\n  sfc: SFCDescriptor,\n): Set<string> {\n  return resolveTemplateAnalysisResult(sfc, false).vModelIds\n}\n\nfunction resolveTemplateUsedIdentifiers(sfc: SFCDescriptor): Set<string> {\n  return resolveTemplateAnalysisResult(sfc).usedIds!\n}\n\nfunction resolveTemplateAnalysisResult(\n  sfc: SFCDescriptor,\n  collectUsedIds = true,\n): {\n  usedIds?: Set<string>\n  vModelIds: Set<string>\n} {\n  const { content, ast } = sfc.template!\n  const cached = templateAnalysisCache.get(content)\n  if (cached && (!collectUsedIds || cached.usedIds)) {\n    return cached\n  }\n\n  // When `collectUsedIds` is false we skip the expensive identifier extraction\n  // and only collect `vModelIds`.\n  const ids = collectUsedIds ? new Set<string>() : undefined\n  const vModelIds = new Set<string>()\n\n  ast!.children.forEach(walk)\n\n  function walk(node: TemplateChildNode) {\n    switch (node.type) {\n      case NodeTypes.ELEMENT:\n        let tag = node.tag\n        if (tag.includes('.')) tag = tag.split('.')[0].trim()\n        if (\n          !parserOptions.isNativeTag!(tag) &&\n          !parserOptions.isBuiltInComponent!(tag)\n        ) {\n          if (ids) {\n            ids.add(camelize(tag))\n            ids.add(capitalize(camelize(tag)))\n          }\n        }\n        for (let i = 0; i < node.props.length; i++) {\n          const prop = node.props[i]\n          if (prop.type === NodeTypes.DIRECTIVE) {\n            if (ids) {\n              if (!isBuiltInDirective(prop.name)) {\n                ids.add(`v${capitalize(camelize(prop.name))}`)\n              }\n            }\n\n            // collect v-model target identifiers (simple identifiers only)\n            if (prop.name === 'model') {\n              const exp = prop.exp\n              if (exp && exp.type === NodeTypes.SIMPLE_EXPRESSION) {\n                const expString = exp.content.trim()\n                if (\n                  isSimpleIdentifier(expString) &&\n                  expString !== 'undefined'\n                ) {\n                  vModelIds.add(expString)\n                }\n              }\n            }\n\n            // process dynamic directive arguments\n            if (\n              ids &&\n              prop.arg &&\n              !(prop.arg as SimpleExpressionNode).isStatic\n            ) {\n              extractIdentifiers(ids, prop.arg)\n            }\n\n            if (ids) {\n              if (prop.name === 'for') {\n                extractIdentifiers(ids, prop.forParseResult!.source)\n              } else if (prop.exp) {\n                extractIdentifiers(ids, prop.exp)\n              } else if (prop.name === 'bind' && !prop.exp) {\n                // v-bind shorthand name as identifier\n                ids.add(camelize((prop.arg as SimpleExpressionNode).content))\n              }\n            }\n          }\n          if (\n            ids &&\n            prop.type === NodeTypes.ATTRIBUTE &&\n            prop.name === 'ref' &&\n            prop.value?.content\n          ) {\n            ids.add(prop.value.content)\n          }\n        }\n        node.children.forEach(walk)\n        break\n      case NodeTypes.INTERPOLATION:\n        if (ids) extractIdentifiers(ids, node.content)\n        break\n    }\n  }\n\n  const result = { usedIds: ids, vModelIds }\n  templateAnalysisCache.set(content, result)\n  return result\n}\n\nfunction extractIdentifiers(ids: Set<string>, node: ExpressionNode) {\n  if (node.ast) {\n    walkIdentifiers(node.ast, n => ids.add(n.name))\n  } else if (node.ast === null) {\n    ids.add((node as SimpleExpressionNode).content)\n  }\n}\n"
  },
  {
    "path": "packages/compiler-sfc/src/script/normalScript.ts",
    "content": "import { analyzeScriptBindings } from './analyzeScriptBindings'\nimport type { ScriptCompileContext } from './context'\nimport MagicString from 'magic-string'\nimport { rewriteDefaultAST } from '../rewriteDefault'\nimport { genNormalScriptCssVarsCode } from '../style/cssVars'\nimport type { SFCScriptBlock } from '../parse'\n\nexport const normalScriptDefaultVar = `__default__`\n\nexport function processNormalScript(\n  ctx: ScriptCompileContext,\n  scopeId: string,\n): SFCScriptBlock {\n  const script = ctx.descriptor.script!\n  try {\n    let content = script.content\n    let map = script.map\n    const scriptAst = ctx.scriptAst!\n    const bindings = analyzeScriptBindings(scriptAst.body)\n    const { cssVars } = ctx.descriptor\n    const { genDefaultAs, isProd } = ctx.options\n\n    if (cssVars.length || genDefaultAs) {\n      const defaultVar = genDefaultAs || normalScriptDefaultVar\n      const s = new MagicString(content)\n      rewriteDefaultAST(scriptAst.body, s, defaultVar)\n      content = s.toString()\n      if (cssVars.length && !ctx.options.templateOptions?.ssr) {\n        content += genNormalScriptCssVarsCode(\n          cssVars,\n          bindings,\n          scopeId,\n          !!isProd,\n          defaultVar,\n        )\n      }\n      if (!genDefaultAs) {\n        content += `\\nexport default ${defaultVar}`\n      }\n    }\n    return {\n      ...script,\n      content,\n      map,\n      bindings,\n      scriptAst: scriptAst.body,\n    }\n  } catch (e: any) {\n    // silently fallback if parse fails since user may be using custom\n    // babel syntax\n    return script\n  }\n}\n"
  },
  {
    "path": "packages/compiler-sfc/src/script/resolveType.ts",
    "content": "import type {\n  Expression,\n  Identifier,\n  Node,\n  Statement,\n  TSCallSignatureDeclaration,\n  TSEnumDeclaration,\n  TSExpressionWithTypeArguments,\n  TSFunctionType,\n  TSImportType,\n  TSIndexedAccessType,\n  TSInterfaceDeclaration,\n  TSMappedType,\n  TSMethodSignature,\n  TSModuleBlock,\n  TSModuleDeclaration,\n  TSPropertySignature,\n  TSQualifiedName,\n  TSType,\n  TSTypeAnnotation,\n  TSTypeElement,\n  TSTypeLiteral,\n  TSTypeQuery,\n  TSTypeReference,\n  TemplateLiteral,\n} from '@babel/types'\nimport {\n  UNKNOWN_TYPE,\n  createGetCanonicalFileName,\n  getId,\n  getImportedName,\n  getStringLiteralKey,\n  joinPaths,\n  normalizePath,\n} from './utils'\nimport { type ScriptCompileContext, resolveParserPlugins } from './context'\nimport type { ImportBinding, SFCScriptCompileOptions } from '../compileScript'\nimport { capitalize, hasOwn } from '@vue/shared'\nimport { parse as babelParse } from '@babel/parser'\nimport { parse } from '../parse'\nimport { createCache } from '../cache'\nimport type TS from 'typescript'\nimport { dirname, extname, join } from 'path'\nimport { minimatch as isMatch } from 'minimatch'\nimport * as process from 'process'\n\nexport type SimpleTypeResolveOptions = Partial<\n  Pick<\n    SFCScriptCompileOptions,\n    'globalTypeFiles' | 'fs' | 'babelParserPlugins' | 'isProd'\n  >\n>\n\n/**\n * TypeResolveContext is compatible with ScriptCompileContext\n * but also allows a simpler version of it with minimal required properties\n * when resolveType needs to be used in a non-SFC context, e.g. in a babel\n * plugin. The simplest context can be just:\n * ```ts\n * const ctx: SimpleTypeResolveContext = {\n *   filename: '...',\n *   source: '...',\n *   options: {},\n *   error() {},\n *   ast: []\n * }\n * ```\n */\nexport type SimpleTypeResolveContext = Pick<\n  ScriptCompileContext,\n  // file\n  | 'source'\n  | 'filename'\n\n  // utils\n  | 'error'\n  | 'warn'\n  | 'helper'\n  | 'getString'\n\n  // props\n  | 'propsTypeDecl'\n  | 'propsRuntimeDefaults'\n  | 'propsDestructuredBindings'\n\n  // emits\n  | 'emitsTypeDecl'\n\n  // customElement\n  | 'isCE'\n> &\n  Partial<\n    Pick<ScriptCompileContext, 'scope' | 'globalScopes' | 'deps' | 'fs'>\n  > & {\n    ast: Statement[]\n    options: SimpleTypeResolveOptions\n  }\n\nexport type TypeResolveContext = (\n  | ScriptCompileContext\n  | SimpleTypeResolveContext\n) & {\n  silentOnExtendsFailure?: boolean\n}\n\ntype Import = Pick<ImportBinding, 'source' | 'imported'>\n\ninterface WithScope {\n  _ownerScope: TypeScope\n}\n\n// scope types always has ownerScope attached\ntype ScopeTypeNode = Node &\n  WithScope & { _ns?: TSModuleDeclaration & WithScope }\n\nexport class TypeScope {\n  constructor(\n    public filename: string,\n    public source: string,\n    public offset: number = 0,\n    public imports: Record<string, Import> = Object.create(null),\n    public types: Record<string, ScopeTypeNode> = Object.create(null),\n    public declares: Record<string, ScopeTypeNode> = Object.create(null),\n  ) {}\n  isGenericScope = false\n  resolvedImportSources: Record<string, string> = Object.create(null)\n  exportedTypes: Record<string, ScopeTypeNode> = Object.create(null)\n  exportedDeclares: Record<string, ScopeTypeNode> = Object.create(null)\n}\n\nexport interface MaybeWithScope {\n  _ownerScope?: TypeScope\n}\n\ninterface ResolvedElements {\n  props: Record<\n    string,\n    (TSPropertySignature | TSMethodSignature) & {\n      // resolved props always has ownerScope attached\n      _ownerScope: TypeScope\n    }\n  >\n  calls?: (TSCallSignatureDeclaration | TSFunctionType)[]\n}\n\n/**\n * Resolve arbitrary type node to a list of type elements that can be then\n * mapped to runtime props or emits.\n */\nexport function resolveTypeElements(\n  ctx: TypeResolveContext,\n  node: Node & MaybeWithScope & { _resolvedElements?: ResolvedElements },\n  scope?: TypeScope,\n  typeParameters?: Record<string, Node>,\n): ResolvedElements {\n  const canCache = !typeParameters\n  if (canCache && node._resolvedElements) {\n    return node._resolvedElements\n  }\n  const resolved = innerResolveTypeElements(\n    ctx,\n    node,\n    node._ownerScope || scope || ctxToScope(ctx),\n    typeParameters,\n  )\n  return canCache ? (node._resolvedElements = resolved) : resolved\n}\n\nfunction innerResolveTypeElements(\n  ctx: TypeResolveContext,\n  node: Node,\n  scope: TypeScope,\n  typeParameters?: Record<string, Node>,\n): ResolvedElements {\n  if (\n    node.leadingComments &&\n    node.leadingComments.some(c => c.value.includes('@vue-ignore'))\n  ) {\n    return { props: {} }\n  }\n  switch (node.type) {\n    case 'TSTypeLiteral':\n      return typeElementsToMap(ctx, node.members, scope, typeParameters)\n    case 'TSInterfaceDeclaration':\n      return resolveInterfaceMembers(ctx, node, scope, typeParameters)\n    case 'TSTypeAliasDeclaration':\n    case 'TSTypeAnnotation':\n    case 'TSParenthesizedType':\n      return resolveTypeElements(\n        ctx,\n        node.typeAnnotation,\n        scope,\n        typeParameters,\n      )\n    case 'TSFunctionType': {\n      return { props: {}, calls: [node] }\n    }\n    case 'TSUnionType':\n    case 'TSIntersectionType':\n      return mergeElements(\n        node.types.map(t => resolveTypeElements(ctx, t, scope, typeParameters)),\n        node.type,\n      )\n    case 'TSMappedType':\n      return resolveMappedType(ctx, node, scope, typeParameters)\n    case 'TSIndexedAccessType': {\n      const types = resolveIndexType(ctx, node, scope)\n      return mergeElements(\n        types.map(t => resolveTypeElements(ctx, t, t._ownerScope)),\n        'TSUnionType',\n      )\n    }\n    case 'TSExpressionWithTypeArguments': // referenced by interface extends\n    case 'TSTypeReference': {\n      const typeName = getReferenceName(node)\n      if (\n        (typeName === 'ExtractPropTypes' ||\n          typeName === 'ExtractPublicPropTypes') &&\n        node.typeParameters &&\n        scope.imports[typeName]?.source === 'vue'\n      ) {\n        return resolveExtractPropTypes(\n          resolveTypeElements(\n            ctx,\n            node.typeParameters.params[0],\n            scope,\n            typeParameters,\n          ),\n          scope,\n        )\n      }\n      const resolved = resolveTypeReference(ctx, node, scope)\n      if (resolved) {\n        let typeParams: Record<string, Node> | undefined\n        if (\n          (resolved.type === 'TSTypeAliasDeclaration' ||\n            resolved.type === 'TSInterfaceDeclaration') &&\n          resolved.typeParameters &&\n          node.typeParameters\n        ) {\n          typeParams = Object.create(null)\n          resolved.typeParameters.params.forEach((p, i) => {\n            let param = typeParameters && typeParameters[p.name]\n            if (!param) param = node.typeParameters!.params[i]\n            typeParams![p.name] = param\n          })\n        }\n        return resolveTypeElements(\n          ctx,\n          resolved,\n          resolved._ownerScope,\n          typeParams,\n        )\n      } else {\n        if (typeof typeName === 'string') {\n          if (typeParameters && typeParameters[typeName]) {\n            return resolveTypeElements(\n              ctx,\n              typeParameters[typeName],\n              scope,\n              typeParameters,\n            )\n          }\n          if (\n            // @ts-expect-error\n            SupportedBuiltinsSet.has(typeName)\n          ) {\n            return resolveBuiltin(\n              ctx,\n              node,\n              typeName as any,\n              scope,\n              typeParameters,\n            )\n          } else if (typeName === 'ReturnType' && node.typeParameters) {\n            // limited support, only reference types\n            const ret = resolveReturnType(\n              ctx,\n              node.typeParameters.params[0],\n              scope,\n            )\n            if (ret) {\n              return resolveTypeElements(ctx, ret, scope)\n            }\n          }\n        }\n        return ctx.error(\n          `Unresolvable type reference or unsupported built-in utility type`,\n          node,\n          scope,\n        )\n      }\n    }\n    case 'TSImportType': {\n      if (\n        getId(node.argument) === 'vue' &&\n        node.qualifier?.type === 'Identifier' &&\n        node.qualifier.name === 'ExtractPropTypes' &&\n        node.typeParameters\n      ) {\n        return resolveExtractPropTypes(\n          resolveTypeElements(ctx, node.typeParameters.params[0], scope),\n          scope,\n        )\n      }\n      const sourceScope = importSourceToScope(\n        ctx,\n        node.argument,\n        scope,\n        node.argument.value,\n      )\n      const resolved = resolveTypeReference(ctx, node, sourceScope)\n      if (resolved) {\n        return resolveTypeElements(ctx, resolved, resolved._ownerScope)\n      }\n      break\n    }\n    case 'TSTypeQuery':\n      {\n        const resolved = resolveTypeReference(ctx, node, scope)\n        if (resolved) {\n          return resolveTypeElements(ctx, resolved, resolved._ownerScope)\n        }\n      }\n      break\n  }\n  return ctx.error(`Unresolvable type: ${node.type}`, node, scope)\n}\n\nfunction typeElementsToMap(\n  ctx: TypeResolveContext,\n  elements: TSTypeElement[],\n  scope = ctxToScope(ctx),\n  typeParameters?: Record<string, Node>,\n): ResolvedElements {\n  const res: ResolvedElements = { props: {} }\n  for (const e of elements) {\n    if (e.type === 'TSPropertySignature' || e.type === 'TSMethodSignature') {\n      // capture generic parameters on node's scope\n      if (typeParameters) {\n        scope = createChildScope(scope)\n        scope.isGenericScope = true\n        Object.assign(scope.types, typeParameters)\n      }\n      ;(e as MaybeWithScope)._ownerScope = scope\n      const name = getStringLiteralKey(e)\n      if (name !== null) {\n        res.props[name] = e as ResolvedElements['props'][string]\n      } else {\n        ctx.error(\n          `Unsupported computed key in type referenced by a macro`,\n          e.key,\n          scope,\n        )\n      }\n    } else if (e.type === 'TSCallSignatureDeclaration') {\n      ;(res.calls || (res.calls = [])).push(e)\n    }\n  }\n  return res\n}\n\nfunction mergeElements(\n  maps: ResolvedElements[],\n  type: 'TSUnionType' | 'TSIntersectionType',\n): ResolvedElements {\n  if (maps.length === 1) return maps[0]\n  const res: ResolvedElements = { props: {} }\n  const { props: baseProps } = res\n  for (const { props, calls } of maps) {\n    for (const key in props) {\n      if (!hasOwn(baseProps, key)) {\n        baseProps[key] = props[key]\n      } else {\n        baseProps[key] = createProperty(\n          baseProps[key].key,\n          {\n            type,\n            // @ts-expect-error\n            types: [baseProps[key], props[key]],\n          },\n          baseProps[key]._ownerScope,\n          baseProps[key].optional || props[key].optional,\n        )\n      }\n    }\n    if (calls) {\n      ;(res.calls || (res.calls = [])).push(...calls)\n    }\n  }\n  return res\n}\n\nfunction createProperty(\n  key: Expression,\n  typeAnnotation: TSType,\n  scope: TypeScope,\n  optional: boolean,\n): TSPropertySignature & WithScope {\n  return {\n    type: 'TSPropertySignature',\n    key,\n    kind: 'get',\n    optional,\n    typeAnnotation: {\n      type: 'TSTypeAnnotation',\n      typeAnnotation,\n    },\n    _ownerScope: scope,\n  }\n}\n\nfunction resolveInterfaceMembers(\n  ctx: TypeResolveContext,\n  node: TSInterfaceDeclaration & MaybeWithScope,\n  scope: TypeScope,\n  typeParameters?: Record<string, Node>,\n): ResolvedElements {\n  const base = typeElementsToMap(\n    ctx,\n    node.body.body,\n    node._ownerScope,\n    typeParameters,\n  )\n  if (node.extends) {\n    for (const ext of node.extends) {\n      try {\n        const { props, calls } = resolveTypeElements(ctx, ext, scope)\n        for (const key in props) {\n          if (!hasOwn(base.props, key)) {\n            base.props[key] = props[key]\n          }\n        }\n        if (calls) {\n          ;(base.calls || (base.calls = [])).push(...calls)\n        }\n      } catch (e) {\n        // when called from inferRuntimeType context, silently ignore extends\n        // resolution failure so that properties defined in the interface can\n        // still be correctly resolved\n        if (!ctx.silentOnExtendsFailure) {\n          ctx.error(\n            `Failed to resolve extends base type.\\nIf this previously worked in 3.2, ` +\n              `you can instruct the compiler to ignore this extend by adding ` +\n              `/* @vue-ignore */ before it, for example:\\n\\n` +\n              `interface Props extends /* @vue-ignore */ Base {}\\n\\n` +\n              `Note: both in 3.2 or with the ignore, the properties in the base ` +\n              `type are treated as fallthrough attrs at runtime.`,\n            ext,\n            scope,\n          )\n        }\n      }\n    }\n  }\n  return base\n}\n\nfunction resolveMappedType(\n  ctx: TypeResolveContext,\n  node: TSMappedType,\n  scope: TypeScope,\n  typeParameters?: Record<string, Node>,\n): ResolvedElements {\n  const res: ResolvedElements = { props: {} }\n  let keys: string[]\n  if (node.nameType) {\n    const { name, constraint } = node.typeParameter\n    scope = createChildScope(scope)\n    Object.assign(scope.types, { ...typeParameters, [name]: constraint })\n    keys = resolveStringType(ctx, node.nameType, scope)\n  } else {\n    keys = resolveStringType(ctx, node.typeParameter.constraint!, scope)\n  }\n  for (const key of keys) {\n    res.props[key] = createProperty(\n      {\n        type: 'Identifier',\n        name: key,\n      },\n      node.typeAnnotation!,\n      scope,\n      !!node.optional,\n    )\n  }\n  return res\n}\n\nfunction resolveIndexType(\n  ctx: TypeResolveContext,\n  node: TSIndexedAccessType,\n  scope: TypeScope,\n): (TSType & MaybeWithScope)[] {\n  if (node.indexType.type === 'TSNumberKeyword') {\n    return resolveArrayElementType(ctx, node.objectType, scope)\n  }\n\n  const { indexType, objectType } = node\n  const types: TSType[] = []\n  let keys: string[]\n  let resolved: ResolvedElements\n  if (indexType.type === 'TSStringKeyword') {\n    resolved = resolveTypeElements(ctx, objectType, scope)\n    keys = Object.keys(resolved.props)\n  } else {\n    keys = resolveStringType(ctx, indexType, scope)\n    resolved = resolveTypeElements(ctx, objectType, scope)\n  }\n  for (const key of keys) {\n    const targetType = resolved.props[key]?.typeAnnotation?.typeAnnotation\n    if (targetType) {\n      ;(targetType as TSType & MaybeWithScope)._ownerScope =\n        resolved.props[key]._ownerScope\n      types.push(targetType)\n    }\n  }\n  return types\n}\n\nfunction resolveArrayElementType(\n  ctx: TypeResolveContext,\n  node: Node,\n  scope: TypeScope,\n): TSType[] {\n  // type[]\n  if (node.type === 'TSArrayType') {\n    return [node.elementType]\n  }\n  // tuple\n  if (node.type === 'TSTupleType') {\n    return node.elementTypes.map(t =>\n      t.type === 'TSNamedTupleMember' ? t.elementType : t,\n    )\n  }\n  if (node.type === 'TSTypeReference') {\n    // Array<type>\n    if (getReferenceName(node) === 'Array' && node.typeParameters) {\n      return node.typeParameters.params\n    } else {\n      const resolved = resolveTypeReference(ctx, node, scope)\n      if (resolved) {\n        return resolveArrayElementType(ctx, resolved, scope)\n      }\n    }\n  }\n  return ctx.error(\n    'Failed to resolve element type from target type',\n    node,\n    scope,\n  )\n}\n\nfunction resolveStringType(\n  ctx: TypeResolveContext,\n  node: Node,\n  scope: TypeScope,\n  typeParameters?: Record<string, Node>,\n): string[] {\n  switch (node.type) {\n    case 'StringLiteral':\n      return [node.value]\n    case 'TSLiteralType':\n      return resolveStringType(ctx, node.literal, scope, typeParameters)\n    case 'TSUnionType':\n      return node.types\n        .map(t => resolveStringType(ctx, t, scope, typeParameters))\n        .flat()\n    case 'TemplateLiteral': {\n      return resolveTemplateKeys(ctx, node, scope)\n    }\n    case 'TSTypeReference': {\n      const resolved = resolveTypeReference(ctx, node, scope)\n      if (resolved) {\n        return resolveStringType(ctx, resolved, scope, typeParameters)\n      }\n      if (node.typeName.type === 'Identifier') {\n        const name = node.typeName.name\n        if (typeParameters && typeParameters[name]) {\n          return resolveStringType(\n            ctx,\n            typeParameters[name],\n            scope,\n            typeParameters,\n          )\n        }\n        const getParam = (index = 0) =>\n          resolveStringType(\n            ctx,\n            node.typeParameters!.params[index],\n            scope,\n            typeParameters,\n          )\n        switch (name) {\n          case 'Extract':\n            return getParam(1)\n          case 'Exclude': {\n            const excluded = getParam(1)\n            return getParam().filter(s => !excluded.includes(s))\n          }\n          case 'Uppercase':\n            return getParam().map(s => s.toUpperCase())\n          case 'Lowercase':\n            return getParam().map(s => s.toLowerCase())\n          case 'Capitalize':\n            return getParam().map(capitalize)\n          case 'Uncapitalize':\n            return getParam().map(s => s[0].toLowerCase() + s.slice(1))\n          default:\n            ctx.error(\n              'Unsupported type when resolving index type',\n              node.typeName,\n              scope,\n            )\n        }\n      }\n    }\n  }\n  return ctx.error('Failed to resolve index type into finite keys', node, scope)\n}\n\nfunction resolveTemplateKeys(\n  ctx: TypeResolveContext,\n  node: TemplateLiteral,\n  scope: TypeScope,\n): string[] {\n  if (!node.expressions.length) {\n    return [node.quasis[0].value.raw]\n  }\n\n  const res: string[] = []\n  const e = node.expressions[0]\n  const q = node.quasis[0]\n  const leading = q ? q.value.raw : ``\n  const resolved = resolveStringType(ctx, e, scope)\n  const restResolved = resolveTemplateKeys(\n    ctx,\n    {\n      ...node,\n      expressions: node.expressions.slice(1),\n      quasis: q ? node.quasis.slice(1) : node.quasis,\n    },\n    scope,\n  )\n\n  for (const r of resolved) {\n    for (const rr of restResolved) {\n      res.push(leading + r + rr)\n    }\n  }\n\n  return res\n}\n\nconst SupportedBuiltinsSet = new Set([\n  'Partial',\n  'Required',\n  'Readonly',\n  'Pick',\n  'Omit',\n] as const)\n\ntype GetSetType<T> = T extends Set<infer V> ? V : never\n\nfunction resolveBuiltin(\n  ctx: TypeResolveContext,\n  node: TSTypeReference | TSExpressionWithTypeArguments,\n  name: GetSetType<typeof SupportedBuiltinsSet>,\n  scope: TypeScope,\n  typeParameters?: Record<string, Node>,\n): ResolvedElements {\n  const t = resolveTypeElements(\n    ctx,\n    node.typeParameters!.params[0],\n    scope,\n    typeParameters,\n  )\n  switch (name) {\n    case 'Partial': {\n      const res: ResolvedElements = { props: {}, calls: t.calls }\n      Object.keys(t.props).forEach(key => {\n        res.props[key] = { ...t.props[key], optional: true }\n      })\n      return res\n    }\n    case 'Required': {\n      const res: ResolvedElements = { props: {}, calls: t.calls }\n      Object.keys(t.props).forEach(key => {\n        res.props[key] = { ...t.props[key], optional: false }\n      })\n      return res\n    }\n    case 'Readonly':\n      return t\n    case 'Pick': {\n      const picked = resolveStringType(\n        ctx,\n        node.typeParameters!.params[1],\n        scope,\n        typeParameters,\n      )\n      const res: ResolvedElements = { props: {}, calls: t.calls }\n      for (const key of picked) {\n        res.props[key] = t.props[key]\n      }\n      return res\n    }\n    case 'Omit':\n      const omitted = resolveStringType(\n        ctx,\n        node.typeParameters!.params[1],\n        scope,\n        typeParameters,\n      )\n      const res: ResolvedElements = { props: {}, calls: t.calls }\n      for (const key in t.props) {\n        if (!omitted.includes(key)) {\n          res.props[key] = t.props[key]\n        }\n      }\n      return res\n  }\n}\n\ntype ReferenceTypes =\n  | TSTypeReference\n  | TSExpressionWithTypeArguments\n  | TSImportType\n  | TSTypeQuery\n\nfunction resolveTypeReference(\n  ctx: TypeResolveContext,\n  node: ReferenceTypes & {\n    _resolvedReference?: ScopeTypeNode\n  },\n  scope?: TypeScope,\n  name?: string,\n  onlyExported = false,\n): ScopeTypeNode | undefined {\n  const canCache = !scope?.isGenericScope\n  if (canCache && node._resolvedReference) {\n    return node._resolvedReference\n  }\n  const resolved = innerResolveTypeReference(\n    ctx,\n    scope || ctxToScope(ctx),\n    name || getReferenceName(node),\n    node,\n    onlyExported,\n  )\n  return canCache ? (node._resolvedReference = resolved) : resolved\n}\n\nfunction innerResolveTypeReference(\n  ctx: TypeResolveContext,\n  scope: TypeScope,\n  name: string | string[],\n  node: ReferenceTypes,\n  onlyExported: boolean,\n): ScopeTypeNode | undefined {\n  if (typeof name === 'string') {\n    if (scope.imports[name]) {\n      return resolveTypeFromImport(ctx, node, name, scope)\n    } else {\n      const lookupSource =\n        node.type === 'TSTypeQuery'\n          ? onlyExported\n            ? scope.exportedDeclares\n            : scope.declares\n          : onlyExported\n            ? scope.exportedTypes\n            : scope.types\n      if (lookupSource[name]) {\n        return lookupSource[name]\n      } else {\n        // fallback to global\n        const globalScopes = resolveGlobalScope(ctx)\n        if (globalScopes) {\n          for (const s of globalScopes) {\n            const src = node.type === 'TSTypeQuery' ? s.declares : s.types\n            if (src[name]) {\n              ;(ctx.deps || (ctx.deps = new Set())).add(s.filename)\n              return src[name]\n            }\n          }\n        }\n      }\n    }\n  } else {\n    let ns = innerResolveTypeReference(ctx, scope, name[0], node, onlyExported)\n    if (ns) {\n      if (ns.type !== 'TSModuleDeclaration') {\n        // namespace merged with other types, attached as _ns\n        ns = ns._ns\n      }\n      if (ns) {\n        const childScope = moduleDeclToScope(ctx, ns, ns._ownerScope || scope)\n        return innerResolveTypeReference(\n          ctx,\n          childScope,\n          name.length > 2 ? name.slice(1) : name[name.length - 1],\n          node,\n          !ns.declare,\n        )\n      }\n    }\n  }\n}\n\nfunction getReferenceName(node: ReferenceTypes): string | string[] {\n  const ref =\n    node.type === 'TSTypeReference'\n      ? node.typeName\n      : node.type === 'TSExpressionWithTypeArguments'\n        ? node.expression\n        : node.type === 'TSImportType'\n          ? node.qualifier\n          : node.exprName\n  if (ref?.type === 'Identifier') {\n    return ref.name\n  } else if (ref?.type === 'TSQualifiedName') {\n    return qualifiedNameToPath(ref)\n  } else {\n    return 'default'\n  }\n}\n\nfunction qualifiedNameToPath(node: Identifier | TSQualifiedName): string[] {\n  if (node.type === 'Identifier') {\n    return [node.name]\n  } else {\n    return [...qualifiedNameToPath(node.left), node.right.name]\n  }\n}\n\nfunction resolveGlobalScope(ctx: TypeResolveContext): TypeScope[] | undefined {\n  if (ctx.options.globalTypeFiles) {\n    const fs = resolveFS(ctx)\n    if (!fs) {\n      throw new Error('[vue/compiler-sfc] globalTypeFiles requires fs access.')\n    }\n    return ctx.options.globalTypeFiles.map(file =>\n      fileToScope(ctx, normalizePath(file), true),\n    )\n  }\n}\n\nlet ts: typeof TS | undefined\nlet loadTS: (() => typeof TS) | undefined\n\n/**\n * @private\n */\nexport function registerTS(_loadTS: () => typeof TS): void {\n  loadTS = () => {\n    try {\n      return _loadTS()\n    } catch (err: any) {\n      if (\n        typeof err.message === 'string' &&\n        err.message.includes('Cannot find module')\n      ) {\n        throw new Error(\n          'Failed to load TypeScript, which is required for resolving imported types. ' +\n            'Please make sure \"TypeScript\" is installed as a project dependency.',\n        )\n      } else {\n        throw new Error(\n          'Failed to load TypeScript for resolving imported types.',\n        )\n      }\n    }\n  }\n}\n\ntype FS = NonNullable<SFCScriptCompileOptions['fs']>\n\nfunction resolveFS(ctx: TypeResolveContext): FS | undefined {\n  if (ctx.fs) {\n    return ctx.fs\n  }\n  if (!ts && loadTS) {\n    ts = loadTS()\n  }\n  const fs = ctx.options.fs || ts?.sys\n  if (!fs) {\n    return\n  }\n  return (ctx.fs = {\n    fileExists(file) {\n      if (file.endsWith('.vue.ts') && !file.endsWith('.d.vue.ts')) {\n        file = file.replace(/\\.ts$/, '')\n      }\n      return fs.fileExists(file)\n    },\n    readFile(file) {\n      if (file.endsWith('.vue.ts') && !file.endsWith('.d.vue.ts')) {\n        file = file.replace(/\\.ts$/, '')\n      }\n      return fs.readFile(file)\n    },\n    realpath: fs.realpath,\n  })\n}\n\nfunction resolveTypeFromImport(\n  ctx: TypeResolveContext,\n  node: ReferenceTypes,\n  name: string,\n  scope: TypeScope,\n): ScopeTypeNode | undefined {\n  const { source, imported } = scope.imports[name]\n  const sourceScope = importSourceToScope(ctx, node, scope, source)\n  return resolveTypeReference(ctx, node, sourceScope, imported, true)\n}\n\nfunction importSourceToScope(\n  ctx: TypeResolveContext,\n  node: Node,\n  scope: TypeScope,\n  source: string,\n): TypeScope {\n  let fs: FS | undefined\n  try {\n    fs = resolveFS(ctx)\n  } catch (err: any) {\n    return ctx.error(err.message, node, scope)\n  }\n  if (!fs) {\n    return ctx.error(\n      `No fs option provided to \\`compileScript\\` in non-Node environment. ` +\n        `File system access is required for resolving imported types.`,\n      node,\n      scope,\n    )\n  }\n\n  let resolved: string | undefined = scope.resolvedImportSources[source]\n  if (!resolved) {\n    if (source.startsWith('..')) {\n      const osSpecificJoinFn = process.platform === 'win32' ? join : joinPaths\n\n      const filename = osSpecificJoinFn(dirname(scope.filename), source)\n      resolved = resolveExt(filename, fs)\n    } else if (source[0] === '.') {\n      // relative import - fast path\n      const filename = joinPaths(dirname(scope.filename), source)\n      resolved = resolveExt(filename, fs)\n    } else {\n      // module or aliased import - use full TS resolution, only supported in Node\n      if (!__CJS__) {\n        return ctx.error(\n          `Type import from non-relative sources is not supported in the browser build.`,\n          node,\n          scope,\n        )\n      }\n      if (!ts) {\n        if (loadTS) ts = loadTS()\n        if (!ts) {\n          return ctx.error(\n            `Failed to resolve import source ${JSON.stringify(source)}. ` +\n              `TypeScript is required as a peer dep for vue in order ` +\n              `to support resolving types from module imports.`,\n            node,\n            scope,\n          )\n        }\n      }\n      resolved = resolveWithTS(scope.filename, source, ts, fs)\n    }\n    if (resolved) {\n      resolved = scope.resolvedImportSources[source] = normalizePath(resolved)\n    }\n  }\n  if (resolved) {\n    // (hmr) register dependency file on ctx\n    ;(ctx.deps || (ctx.deps = new Set())).add(resolved)\n    return fileToScope(ctx, resolved)\n  } else {\n    return ctx.error(\n      `Failed to resolve import source ${JSON.stringify(source)}.`,\n      node,\n      scope,\n    )\n  }\n}\n\nfunction resolveExt(filename: string, fs: FS) {\n  // Keep the import's module kind so we can mirror TS NodeNext fallback order.\n  let moduleType: /*cjs*/ 'c' | /*mjs*/ 'm' | /*unknown*/ 'u' = 'u'\n  if (filename.endsWith('.mjs')) {\n    moduleType = 'm'\n  } else if (filename.endsWith('.cjs')) {\n    moduleType = 'c'\n  }\n  // #8339 ts may import .js but we should resolve to corresponding ts or d.ts\n  filename = filename.replace(/\\.[cm]?jsx?$/, '')\n  const tryResolve = (filename: string) => {\n    if (fs.fileExists(filename)) return filename\n  }\n  const resolveTs = () =>\n    tryResolve(filename + `.ts`) ||\n    tryResolve(filename + `.tsx`) ||\n    tryResolve(filename + `.d.ts`)\n  const resolveMts = () =>\n    tryResolve(filename + `.mts`) || tryResolve(filename + `.d.mts`)\n  const resolveCts = () =>\n    tryResolve(filename + `.cts`) || tryResolve(filename + `.d.cts`)\n\n  return (\n    tryResolve(filename) ||\n    // For explicit .mjs/.cjs imports, prefer .mts/.cts declarations first.\n    (moduleType === 'm'\n      ? resolveMts() || resolveTs()\n      : moduleType === 'c'\n        ? resolveCts() || resolveTs()\n        : resolveTs() || resolveMts() || resolveCts()) ||\n    tryResolve(joinPaths(filename, `index.ts`)) ||\n    tryResolve(joinPaths(filename, `index.tsx`)) ||\n    tryResolve(joinPaths(filename, `index.d.ts`))\n  )\n}\n\ninterface CachedConfig {\n  config: TS.ParsedCommandLine\n  cache?: TS.ModuleResolutionCache\n}\n\nconst tsConfigCache = createCache<CachedConfig[]>()\nconst tsConfigRefMap = new Map<string, string>()\n\nfunction resolveWithTS(\n  containingFile: string,\n  source: string,\n  ts: typeof TS,\n  fs: FS,\n): string | undefined {\n  if (!__CJS__) return\n\n  // 1. resolve tsconfig.json\n  const configPath = ts.findConfigFile(containingFile, fs.fileExists)\n  // 2. load tsconfig.json\n  let tsCompilerOptions: TS.CompilerOptions\n  let tsResolveCache: TS.ModuleResolutionCache | undefined\n  if (configPath) {\n    let configs: CachedConfig[]\n    const normalizedConfigPath = normalizePath(configPath)\n    const cached = tsConfigCache.get(normalizedConfigPath)\n    if (!cached) {\n      configs = loadTSConfig(configPath, ts, fs).map(config => ({ config }))\n      tsConfigCache.set(normalizedConfigPath, configs)\n    } else {\n      configs = cached\n    }\n    let matchedConfig: CachedConfig | undefined\n    if (configs.length === 1) {\n      matchedConfig = configs[0]\n    } else {\n      const [major, minor] = ts.versionMajorMinor.split('.').map(Number)\n      const getPattern = (base: string, p: string) => {\n        // ts 5.5+ supports ${configDir} in paths\n        const supportsConfigDir = major > 5 || (major === 5 && minor >= 5)\n        return p.startsWith('${configDir}') && supportsConfigDir\n          ? normalizePath(p.replace('${configDir}', dirname(configPath!)))\n          : joinPaths(base, p)\n      }\n      // resolve which config matches the current file\n      for (const c of configs) {\n        const base = normalizePath(\n          (c.config.options.pathsBasePath as string) ||\n            dirname(c.config.options.configFilePath as string),\n        )\n        const included: string[] | undefined = c.config.raw?.include\n        const excluded: string[] | undefined = c.config.raw?.exclude\n        if (\n          (!included && (!base || containingFile.startsWith(base))) ||\n          included?.some(p => isMatch(containingFile, getPattern(base, p)))\n        ) {\n          if (\n            excluded &&\n            excluded.some(p => isMatch(containingFile, getPattern(base, p)))\n          ) {\n            continue\n          }\n          matchedConfig = c\n          break\n        }\n      }\n      if (!matchedConfig) {\n        matchedConfig = configs[configs.length - 1]\n      }\n    }\n    tsCompilerOptions = matchedConfig.config.options\n    tsResolveCache =\n      matchedConfig.cache ||\n      (matchedConfig.cache = ts.createModuleResolutionCache(\n        process.cwd(),\n        createGetCanonicalFileName(ts.sys.useCaseSensitiveFileNames),\n        tsCompilerOptions,\n      ))\n  } else {\n    tsCompilerOptions = {}\n  }\n\n  // 3. resolve\n  const res = ts.resolveModuleName(\n    source,\n    containingFile,\n    tsCompilerOptions,\n    fs,\n    tsResolveCache,\n  )\n\n  if (res.resolvedModule) {\n    let filename = res.resolvedModule.resolvedFileName\n    if (filename.endsWith('.vue.ts') && !filename.endsWith('.d.vue.ts')) {\n      filename = filename.replace(/\\.ts$/, '')\n    }\n    return fs.realpath ? fs.realpath(filename) : filename\n  }\n}\n\nfunction loadTSConfig(\n  configPath: string,\n  ts: typeof TS,\n  fs: FS,\n  visited = new Set<string>(),\n): TS.ParsedCommandLine[] {\n  // The only case where `fs` is NOT `ts.sys` is during tests.\n  // parse config host requires an extra `readDirectory` method\n  // during tests, which is stubbed.\n  const parseConfigHost = __TEST__\n    ? {\n        ...fs,\n        useCaseSensitiveFileNames: true,\n        readDirectory: () => [],\n      }\n    : ts.sys\n  const config = ts.parseJsonConfigFileContent(\n    ts.readConfigFile(configPath, fs.readFile).config,\n    parseConfigHost,\n    dirname(configPath),\n    undefined,\n    configPath,\n  )\n  const res = [config]\n  visited.add(configPath)\n  if (config.projectReferences) {\n    for (const ref of config.projectReferences) {\n      const refPath = ts.resolveProjectReferencePath(ref)\n      if (visited.has(refPath) || !fs.fileExists(refPath)) {\n        continue\n      }\n      tsConfigRefMap.set(refPath, configPath)\n      res.unshift(...loadTSConfig(refPath, ts, fs, visited))\n    }\n  }\n  return res\n}\n\nconst fileToScopeCache = createCache<TypeScope>()\n\n/**\n * @private\n */\nexport function invalidateTypeCache(filename: string): void {\n  filename = normalizePath(filename)\n  fileToScopeCache.delete(filename)\n  tsConfigCache.delete(filename)\n  const affectedConfig = tsConfigRefMap.get(filename)\n  if (affectedConfig) tsConfigCache.delete(affectedConfig)\n}\n\nexport function fileToScope(\n  ctx: TypeResolveContext,\n  filename: string,\n  asGlobal = false,\n): TypeScope {\n  const cached = fileToScopeCache.get(filename)\n  if (cached) {\n    return cached\n  }\n  // fs should be guaranteed to exist here\n  const fs = resolveFS(ctx)!\n  const source = fs.readFile(filename) || ''\n  const body = parseFile(filename, source, fs, ctx.options.babelParserPlugins)\n  const scope = new TypeScope(filename, source, 0, recordImports(body))\n  recordTypes(ctx, body, scope, asGlobal)\n  fileToScopeCache.set(filename, scope)\n  return scope\n}\n\nfunction parseFile(\n  filename: string,\n  content: string,\n  fs: FS,\n  parserPlugins?: SFCScriptCompileOptions['babelParserPlugins'],\n): Statement[] {\n  const ext = extname(filename)\n  if (\n    ext === '.ts' ||\n    ext === '.mts' ||\n    ext === '.tsx' ||\n    ext === '.cts' ||\n    ext === '.mtsx'\n  ) {\n    return babelParse(content, {\n      plugins: resolveParserPlugins(\n        ext.slice(1),\n        parserPlugins,\n        /\\.d\\.[cm]?ts$/.test(filename),\n      ),\n      sourceType: 'module',\n    }).program.body\n  }\n\n  // simulate `allowArbitraryExtensions` on TypeScript >= 5.0\n  const isUnknownTypeSource = !/\\.[cm]?[tj]sx?$/.test(filename)\n  const arbitraryTypeSource = `${filename.slice(0, -ext.length)}.d${ext}.ts`\n  const hasArbitraryTypeDeclaration =\n    isUnknownTypeSource && fs.fileExists(arbitraryTypeSource)\n  if (hasArbitraryTypeDeclaration) {\n    return babelParse(fs.readFile(arbitraryTypeSource)!, {\n      plugins: resolveParserPlugins('ts', parserPlugins, true),\n      sourceType: 'module',\n    }).program.body\n  }\n\n  if (ext === '.vue') {\n    const {\n      descriptor: { script, scriptSetup },\n    } = parse(content)\n    if (!script && !scriptSetup) {\n      return []\n    }\n\n    // ensure the correct offset with original source\n    const scriptOffset = script ? script.loc.start.offset : Infinity\n    const scriptSetupOffset = scriptSetup\n      ? scriptSetup.loc.start.offset\n      : Infinity\n    const firstBlock = scriptOffset < scriptSetupOffset ? script : scriptSetup\n    const secondBlock = scriptOffset < scriptSetupOffset ? scriptSetup : script\n\n    let scriptContent =\n      ' '.repeat(Math.min(scriptOffset, scriptSetupOffset)) +\n      firstBlock!.content\n    if (secondBlock) {\n      scriptContent +=\n        ' '.repeat(secondBlock.loc.start.offset - script!.loc.end.offset) +\n        secondBlock.content\n    }\n    const lang = script?.lang || scriptSetup?.lang\n    return babelParse(scriptContent, {\n      plugins: resolveParserPlugins(lang!, parserPlugins),\n      sourceType: 'module',\n    }).program.body\n  }\n  return []\n}\n\nfunction ctxToScope(ctx: TypeResolveContext): TypeScope {\n  if (ctx.scope) {\n    return ctx.scope\n  }\n\n  const body =\n    'ast' in ctx\n      ? ctx.ast\n      : ctx.scriptAst\n        ? [...ctx.scriptAst.body, ...ctx.scriptSetupAst!.body]\n        : ctx.scriptSetupAst!.body\n\n  const scope = new TypeScope(\n    ctx.filename,\n    ctx.source,\n    'startOffset' in ctx ? ctx.startOffset! : 0,\n    'userImports' in ctx ? Object.create(ctx.userImports) : recordImports(body),\n  )\n\n  recordTypes(ctx, body, scope)\n\n  return (ctx.scope = scope)\n}\n\nfunction moduleDeclToScope(\n  ctx: TypeResolveContext,\n  node: TSModuleDeclaration & { _resolvedChildScope?: TypeScope },\n  parentScope: TypeScope,\n): TypeScope {\n  if (node._resolvedChildScope) {\n    return node._resolvedChildScope\n  }\n\n  const scope = createChildScope(parentScope)\n\n  if (node.body.type === 'TSModuleDeclaration') {\n    const decl = node.body as TSModuleDeclaration & WithScope\n    decl._ownerScope = scope\n    const id = getId(decl.id)\n    scope.types[id] = scope.exportedTypes[id] = decl\n  } else {\n    recordTypes(ctx, node.body.body, scope)\n  }\n\n  return (node._resolvedChildScope = scope)\n}\n\nfunction createChildScope(parentScope: TypeScope) {\n  return new TypeScope(\n    parentScope.filename,\n    parentScope.source,\n    parentScope.offset,\n    Object.create(parentScope.imports),\n    Object.create(parentScope.types),\n    Object.create(parentScope.declares),\n  )\n}\n\nconst importExportRE = /^Import|^Export/\n\nfunction recordTypes(\n  ctx: TypeResolveContext,\n  body: Statement[],\n  scope: TypeScope,\n  asGlobal = false,\n) {\n  const { types, declares, exportedTypes, exportedDeclares, imports } = scope\n  const isAmbient = asGlobal\n    ? !body.some(s => importExportRE.test(s.type))\n    : false\n  for (const stmt of body) {\n    if (asGlobal) {\n      if (isAmbient) {\n        if ((stmt as any).declare) {\n          recordType(stmt, types, declares)\n        }\n      } else if (stmt.type === 'TSModuleDeclaration' && stmt.global) {\n        for (const s of (stmt.body as TSModuleBlock).body) {\n          if (s.type === 'ExportNamedDeclaration' && s.declaration) {\n            // Handle export declarations inside declare global\n            recordType(s.declaration, types, declares)\n          } else {\n            recordType(s, types, declares)\n          }\n        }\n      }\n    } else {\n      recordType(stmt, types, declares)\n    }\n  }\n  if (!asGlobal) {\n    for (const stmt of body) {\n      if (stmt.type === 'ExportNamedDeclaration') {\n        if (stmt.declaration) {\n          recordType(stmt.declaration, types, declares)\n          recordType(stmt.declaration, exportedTypes, exportedDeclares)\n        } else {\n          for (const spec of stmt.specifiers) {\n            if (spec.type === 'ExportSpecifier') {\n              const local = spec.local.name\n              const exported = getId(spec.exported)\n              if (stmt.source) {\n                // re-export, register an import + export as a type reference\n                imports[exported] = {\n                  source: stmt.source.value,\n                  imported: local,\n                }\n                exportedTypes[exported] = {\n                  type: 'TSTypeReference',\n                  typeName: {\n                    type: 'Identifier',\n                    name: local,\n                  },\n                  _ownerScope: scope,\n                }\n              } else if (types[local]) {\n                // exporting local defined type\n                exportedTypes[exported] = types[local]\n              }\n            }\n          }\n        }\n      } else if (stmt.type === 'ExportAllDeclaration') {\n        const sourceScope = importSourceToScope(\n          ctx,\n          stmt.source,\n          scope,\n          stmt.source.value,\n        )\n        Object.assign(scope.exportedTypes, sourceScope.exportedTypes)\n      } else if (stmt.type === 'ExportDefaultDeclaration' && stmt.declaration) {\n        if (stmt.declaration.type !== 'Identifier') {\n          recordType(stmt.declaration, types, declares, 'default')\n          recordType(\n            stmt.declaration,\n            exportedTypes,\n            exportedDeclares,\n            'default',\n          )\n        } else if (types[stmt.declaration.name]) {\n          exportedTypes['default'] = types[stmt.declaration.name]\n        }\n      }\n    }\n  }\n  for (const key of Object.keys(types)) {\n    const node = types[key]\n    node._ownerScope = scope\n    if (node._ns) node._ns._ownerScope = scope\n  }\n  for (const key of Object.keys(declares)) {\n    declares[key]._ownerScope = scope\n  }\n}\n\nfunction recordType(\n  node: Node,\n  types: Record<string, Node>,\n  declares: Record<string, Node>,\n  overwriteId?: string,\n) {\n  switch (node.type) {\n    case 'TSInterfaceDeclaration':\n    case 'TSEnumDeclaration':\n    case 'TSModuleDeclaration': {\n      // Handle `declare global { ... }` blocks by recursively processing their contents\n      if (node.type === 'TSModuleDeclaration' && node.global) {\n        const body = node.body as TSModuleBlock\n        for (const s of body.body) {\n          if (s.type === 'ExportNamedDeclaration' && s.declaration) {\n            recordType(s.declaration, types, declares)\n          } else {\n            recordType(s, types, declares)\n          }\n        }\n        break\n      }\n      const id = overwriteId || getId(node.id)\n      let existing = types[id]\n      if (existing) {\n        if (node.type === 'TSModuleDeclaration') {\n          if (existing.type === 'TSModuleDeclaration') {\n            mergeNamespaces(existing as typeof node, node)\n          } else {\n            attachNamespace(existing, node)\n          }\n          break\n        }\n        if (existing.type === 'TSModuleDeclaration') {\n          // replace and attach namespace\n          types[id] = node\n          attachNamespace(node, existing)\n          break\n        }\n\n        if (existing.type !== node.type) {\n          // type-level error\n          break\n        }\n        if (node.type === 'TSInterfaceDeclaration') {\n          ;(existing as typeof node).body.body.push(...node.body.body)\n        } else {\n          ;(existing as typeof node).members.push(...node.members)\n        }\n      } else {\n        types[id] = node\n      }\n      break\n    }\n    case 'ClassDeclaration':\n      if (overwriteId || node.id) types[overwriteId || getId(node.id!)] = node\n      break\n    case 'TSTypeAliasDeclaration':\n      types[node.id.name] = node.typeParameters ? node : node.typeAnnotation\n      break\n    case 'TSDeclareFunction':\n      if (node.id) declares[node.id.name] = node\n      break\n    case 'VariableDeclaration': {\n      if (node.declare) {\n        for (const decl of node.declarations) {\n          if (decl.id.type === 'Identifier' && decl.id.typeAnnotation) {\n            declares[decl.id.name] = (\n              decl.id.typeAnnotation as TSTypeAnnotation\n            ).typeAnnotation\n          }\n        }\n      }\n      break\n    }\n  }\n}\n\nfunction mergeNamespaces(to: TSModuleDeclaration, from: TSModuleDeclaration) {\n  const toBody = to.body\n  const fromBody = from.body\n  if (toBody.type === 'TSModuleDeclaration') {\n    if (fromBody.type === 'TSModuleDeclaration') {\n      // both decl\n      mergeNamespaces(toBody, fromBody)\n    } else {\n      // to: decl -> from: block\n      fromBody.body.push({\n        type: 'ExportNamedDeclaration',\n        declaration: toBody,\n        exportKind: 'type',\n        specifiers: [],\n      })\n    }\n  } else if (fromBody.type === 'TSModuleDeclaration') {\n    // to: block <- from: decl\n    toBody.body.push({\n      type: 'ExportNamedDeclaration',\n      declaration: fromBody,\n      exportKind: 'type',\n      specifiers: [],\n    })\n  } else {\n    // both block\n    toBody.body.push(...fromBody.body)\n  }\n}\n\nfunction attachNamespace(\n  to: Node & { _ns?: TSModuleDeclaration },\n  ns: TSModuleDeclaration,\n) {\n  if (!to._ns) {\n    to._ns = ns\n  } else {\n    mergeNamespaces(to._ns, ns)\n  }\n}\n\nexport function recordImports(body: Statement[]): Record<string, Import> {\n  const imports: TypeScope['imports'] = Object.create(null)\n  for (const s of body) {\n    recordImport(s, imports)\n  }\n  return imports\n}\n\nfunction recordImport(node: Node, imports: TypeScope['imports']) {\n  if (node.type !== 'ImportDeclaration') {\n    return\n  }\n  for (const s of node.specifiers) {\n    imports[s.local.name] = {\n      imported: getImportedName(s),\n      source: node.source.value,\n    }\n  }\n}\n\nexport function inferRuntimeType(\n  ctx: TypeResolveContext,\n  node: Node & MaybeWithScope,\n  scope: TypeScope = node._ownerScope || ctxToScope(ctx),\n  isKeyOf = false,\n  typeParameters?: Record<string, Node>,\n): string[] {\n  if (\n    node.leadingComments &&\n    node.leadingComments.some(c => c.value.includes('@vue-ignore'))\n  ) {\n    return [UNKNOWN_TYPE]\n  }\n\n  // set flag to silence extends resolution errors in this context\n  const prevSilent = ctx.silentOnExtendsFailure\n  ctx.silentOnExtendsFailure = true\n\n  try {\n    switch (node.type) {\n      case 'TSStringKeyword':\n        return ['String']\n      case 'TSNumberKeyword':\n        return ['Number']\n      case 'TSBooleanKeyword':\n        return ['Boolean']\n      case 'TSObjectKeyword':\n        return ['Object']\n      case 'TSNullKeyword':\n        return ['null']\n      case 'TSTypeLiteral':\n      case 'TSInterfaceDeclaration': {\n        // TODO (nice to have) generate runtime property validation\n        const types = new Set<string>()\n        const members =\n          node.type === 'TSTypeLiteral' ? node.members : node.body.body\n\n        for (const m of members) {\n          if (isKeyOf) {\n            if (\n              m.type === 'TSPropertySignature' &&\n              m.key.type === 'NumericLiteral'\n            ) {\n              types.add('Number')\n            } else if (m.type === 'TSIndexSignature') {\n              const annotation = m.parameters[0].typeAnnotation\n              if (annotation && annotation.type !== 'Noop') {\n                const type = inferRuntimeType(\n                  ctx,\n                  annotation.typeAnnotation,\n                  scope,\n                )[0]\n                if (type === UNKNOWN_TYPE) return [UNKNOWN_TYPE]\n                types.add(type)\n              }\n            } else {\n              types.add('String')\n            }\n          } else if (\n            m.type === 'TSCallSignatureDeclaration' ||\n            m.type === 'TSConstructSignatureDeclaration'\n          ) {\n            types.add('Function')\n          } else {\n            types.add('Object')\n          }\n        }\n\n        return types.size\n          ? Array.from(types)\n          : [isKeyOf ? UNKNOWN_TYPE : 'Object']\n      }\n      case 'TSPropertySignature':\n        if (node.typeAnnotation) {\n          return inferRuntimeType(\n            ctx,\n            node.typeAnnotation.typeAnnotation,\n            scope,\n          )\n        }\n        break\n      case 'TSMethodSignature':\n      case 'TSFunctionType':\n        return ['Function']\n      case 'TSArrayType':\n      case 'TSTupleType':\n        // TODO (nice to have) generate runtime element type/length checks\n        return ['Array']\n\n      case 'TSLiteralType':\n        switch (node.literal.type) {\n          case 'StringLiteral':\n            return ['String']\n          case 'BooleanLiteral':\n            return ['Boolean']\n          case 'NumericLiteral':\n          case 'BigIntLiteral':\n            return ['Number']\n          default:\n            return [UNKNOWN_TYPE]\n        }\n\n      case 'TSTypeReference': {\n        const resolved = resolveTypeReference(ctx, node, scope)\n        if (resolved) {\n          if (resolved.type === 'TSTypeAliasDeclaration') {\n            // #13240\n            // Special case for function type aliases to ensure correct runtime behavior\n            // other type aliases still fallback to unknown as before\n            if (resolved.typeAnnotation.type === 'TSFunctionType') {\n              return ['Function']\n            }\n\n            if (node.typeParameters) {\n              const typeParams: Record<string, Node> = Object.create(null)\n              if (resolved.typeParameters) {\n                resolved.typeParameters.params.forEach((p, i) => {\n                  typeParams![p.name] = node.typeParameters!.params[i]\n                })\n              }\n              return inferRuntimeType(\n                ctx,\n                resolved.typeAnnotation,\n                resolved._ownerScope,\n                isKeyOf,\n                typeParams,\n              )\n            }\n          }\n\n          return inferRuntimeType(ctx, resolved, resolved._ownerScope, isKeyOf)\n        }\n        if (node.typeName.type === 'Identifier') {\n          if (typeParameters && typeParameters[node.typeName.name]) {\n            return inferRuntimeType(\n              ctx,\n              typeParameters[node.typeName.name],\n              scope,\n              isKeyOf,\n              typeParameters,\n            )\n          }\n          if (isKeyOf) {\n            switch (node.typeName.name) {\n              case 'String':\n              case 'Array':\n              case 'ArrayLike':\n              case 'Parameters':\n              case 'ConstructorParameters':\n              case 'ReadonlyArray':\n                return ['String', 'Number']\n\n              // TS built-in utility types\n              case 'Record':\n              case 'Partial':\n              case 'Required':\n              case 'Readonly':\n                if (node.typeParameters && node.typeParameters.params[0]) {\n                  return inferRuntimeType(\n                    ctx,\n                    node.typeParameters.params[0],\n                    scope,\n                    true,\n                  )\n                }\n                break\n              case 'Pick':\n              case 'Extract':\n                if (node.typeParameters && node.typeParameters.params[1]) {\n                  return inferRuntimeType(\n                    ctx,\n                    node.typeParameters.params[1],\n                    scope,\n                  )\n                }\n                break\n\n              case 'Function':\n              case 'Object':\n              case 'Set':\n              case 'Map':\n              case 'WeakSet':\n              case 'WeakMap':\n              case 'Date':\n              case 'Promise':\n              case 'Error':\n              case 'Uppercase':\n              case 'Lowercase':\n              case 'Capitalize':\n              case 'Uncapitalize':\n              case 'ReadonlyMap':\n              case 'ReadonlySet':\n                return ['String']\n            }\n          } else {\n            switch (node.typeName.name) {\n              case 'Array':\n              case 'Function':\n              case 'Object':\n              case 'Set':\n              case 'Map':\n              case 'WeakSet':\n              case 'WeakMap':\n              case 'Date':\n              case 'Promise':\n              case 'Error':\n                return [node.typeName.name]\n\n              // TS built-in utility types\n              // https://www.typescriptlang.org/docs/handbook/utility-types.html\n              case 'Partial':\n              case 'Required':\n              case 'Readonly':\n              case 'Record':\n              case 'Pick':\n              case 'Omit':\n              case 'InstanceType':\n                return ['Object']\n\n              case 'Uppercase':\n              case 'Lowercase':\n              case 'Capitalize':\n              case 'Uncapitalize':\n                return ['String']\n\n              case 'Parameters':\n              case 'ConstructorParameters':\n              case 'ReadonlyArray':\n                return ['Array']\n\n              case 'ReadonlyMap':\n                return ['Map']\n              case 'ReadonlySet':\n                return ['Set']\n\n              case 'NonNullable':\n                if (node.typeParameters && node.typeParameters.params[0]) {\n                  return inferRuntimeType(\n                    ctx,\n                    node.typeParameters.params[0],\n                    scope,\n                  ).filter(t => t !== 'null')\n                }\n                break\n              case 'Extract':\n                if (node.typeParameters && node.typeParameters.params[1]) {\n                  return inferRuntimeType(\n                    ctx,\n                    node.typeParameters.params[1],\n                    scope,\n                  )\n                }\n                break\n              case 'Exclude':\n              case 'OmitThisParameter':\n                if (node.typeParameters && node.typeParameters.params[0]) {\n                  return inferRuntimeType(\n                    ctx,\n                    node.typeParameters.params[0],\n                    scope,\n                  )\n                }\n                break\n            }\n          }\n        }\n        // cannot infer, fallback to UNKNOWN: ThisParameterType\n        break\n      }\n\n      case 'TSParenthesizedType':\n        return inferRuntimeType(ctx, node.typeAnnotation, scope)\n\n      case 'TSUnionType':\n        return flattenTypes(ctx, node.types, scope, isKeyOf, typeParameters)\n      case 'TSIntersectionType': {\n        return flattenTypes(\n          ctx,\n          node.types,\n          scope,\n          isKeyOf,\n          typeParameters,\n        ).filter(t => t !== UNKNOWN_TYPE)\n      }\n      case 'TSMappedType': {\n        // only support { [K in keyof T]: T[K] }\n        const { typeAnnotation, typeParameter } = node\n        if (\n          typeAnnotation &&\n          typeAnnotation.type === 'TSIndexedAccessType' &&\n          typeParameter &&\n          typeParameter.constraint &&\n          typeParameters\n        ) {\n          const constraint = typeParameter.constraint\n          if (\n            constraint.type === 'TSTypeOperator' &&\n            constraint.operator === 'keyof' &&\n            constraint.typeAnnotation &&\n            constraint.typeAnnotation.type === 'TSTypeReference' &&\n            constraint.typeAnnotation.typeName.type === 'Identifier'\n          ) {\n            const typeName = constraint.typeAnnotation.typeName.name\n            const index = typeAnnotation.indexType\n            const obj = typeAnnotation.objectType\n            if (\n              obj &&\n              obj.type === 'TSTypeReference' &&\n              obj.typeName.type === 'Identifier' &&\n              obj.typeName.name === typeName &&\n              index &&\n              index.type === 'TSTypeReference' &&\n              index.typeName.type === 'Identifier' &&\n              index.typeName.name === typeParameter.name\n            ) {\n              const targetType = typeParameters[typeName]\n              if (targetType) {\n                return inferRuntimeType(ctx, targetType, scope)\n              }\n            }\n          }\n        }\n\n        return [UNKNOWN_TYPE]\n      }\n\n      case 'TSEnumDeclaration':\n        return inferEnumType(node)\n\n      case 'TSSymbolKeyword':\n        return ['Symbol']\n\n      case 'TSIndexedAccessType': {\n        const types = resolveIndexType(ctx, node, scope)\n        return flattenTypes(ctx, types, scope, isKeyOf)\n      }\n\n      case 'ClassDeclaration':\n        return ['Object']\n\n      case 'TSImportType': {\n        const sourceScope = importSourceToScope(\n          ctx,\n          node.argument,\n          scope,\n          node.argument.value,\n        )\n        const resolved = resolveTypeReference(ctx, node, sourceScope)\n        if (resolved) {\n          return inferRuntimeType(ctx, resolved, resolved._ownerScope)\n        }\n        break\n      }\n\n      case 'TSTypeQuery': {\n        const id = node.exprName\n        if (id.type === 'Identifier') {\n          // typeof only support identifier in local scope\n          const matched = scope.declares[id.name]\n          if (matched) {\n            return inferRuntimeType(ctx, matched, matched._ownerScope, isKeyOf)\n          }\n        }\n        break\n      }\n\n      // e.g. readonly\n      case 'TSTypeOperator': {\n        return inferRuntimeType(\n          ctx,\n          node.typeAnnotation,\n          scope,\n          node.operator === 'keyof',\n        )\n      }\n\n      case 'TSAnyKeyword': {\n        if (isKeyOf) {\n          return ['String', 'Number', 'Symbol']\n        }\n        break\n      }\n    }\n  } catch (e) {\n    // always soft fail on failed runtime type inference\n  } finally {\n    ctx.silentOnExtendsFailure = prevSilent\n  }\n  return [UNKNOWN_TYPE] // no runtime check\n}\n\nfunction flattenTypes(\n  ctx: TypeResolveContext,\n  types: TSType[],\n  scope: TypeScope,\n  isKeyOf: boolean = false,\n  typeParameters: Record<string, Node> | undefined = undefined,\n): string[] {\n  if (types.length === 1) {\n    return inferRuntimeType(\n      ctx,\n      types[0],\n      (types[0] as MaybeWithScope)._ownerScope || scope,\n      isKeyOf,\n      typeParameters,\n    )\n  }\n  return [\n    ...new Set(\n      ([] as string[]).concat(\n        ...types.map(t =>\n          inferRuntimeType(\n            ctx,\n            t,\n            (t as MaybeWithScope)._ownerScope || scope,\n            isKeyOf,\n            typeParameters,\n          ),\n        ),\n      ),\n    ),\n  ]\n}\n\nfunction inferEnumType(node: TSEnumDeclaration): string[] {\n  const types = new Set<string>()\n  for (const m of node.members) {\n    if (m.initializer) {\n      switch (m.initializer.type) {\n        case 'StringLiteral':\n          types.add('String')\n          break\n        case 'NumericLiteral':\n          types.add('Number')\n          break\n      }\n    }\n  }\n  return types.size ? [...types] : ['Number']\n}\n\n/**\n * support for the `ExtractPropTypes` helper - it's non-exhaustive, mostly\n * tailored towards popular component libs like element-plus and antd-vue.\n */\nfunction resolveExtractPropTypes(\n  { props }: ResolvedElements,\n  scope: TypeScope,\n): ResolvedElements {\n  const res: ResolvedElements = { props: {} }\n  for (const key in props) {\n    const raw = props[key]\n    res.props[key] = reverseInferType(\n      raw.key,\n      raw.typeAnnotation!.typeAnnotation,\n      scope,\n    )\n  }\n  return res\n}\n\nfunction reverseInferType(\n  key: Expression,\n  node: TSType,\n  scope: TypeScope,\n  optional = true,\n  checkObjectSyntax = true,\n): TSPropertySignature & WithScope {\n  if (checkObjectSyntax && node.type === 'TSTypeLiteral') {\n    // check { type: xxx }\n    const typeType = findStaticPropertyType(node, 'type')\n    if (typeType) {\n      const requiredType = findStaticPropertyType(node, 'required')\n      const optional =\n        requiredType &&\n        requiredType.type === 'TSLiteralType' &&\n        requiredType.literal.type === 'BooleanLiteral'\n          ? !requiredType.literal.value\n          : true\n      return reverseInferType(key, typeType, scope, optional, false)\n    }\n  } else if (\n    node.type === 'TSTypeReference' &&\n    node.typeName.type === 'Identifier'\n  ) {\n    if (node.typeName.name.endsWith('Constructor')) {\n      return createProperty(\n        key,\n        ctorToType(node.typeName.name),\n        scope,\n        optional,\n      )\n    } else if (node.typeName.name === 'PropType' && node.typeParameters) {\n      // PropType<{}>\n      return createProperty(key, node.typeParameters.params[0], scope, optional)\n    }\n  }\n  if (\n    (node.type === 'TSTypeReference' || node.type === 'TSImportType') &&\n    node.typeParameters\n  ) {\n    // try if we can catch Foo.Bar<XXXConstructor>\n    for (const t of node.typeParameters.params) {\n      const inferred = reverseInferType(key, t, scope, optional)\n      if (inferred) return inferred\n    }\n  }\n  return createProperty(key, { type: `TSNullKeyword` }, scope, optional)\n}\n\nfunction ctorToType(ctorType: string): TSType {\n  const ctor = ctorType.slice(0, -11)\n  switch (ctor) {\n    case 'String':\n    case 'Number':\n    case 'Boolean':\n      return { type: `TS${ctor}Keyword` }\n    case 'Array':\n    case 'Function':\n    case 'Object':\n    case 'Set':\n    case 'Map':\n    case 'WeakSet':\n    case 'WeakMap':\n    case 'Date':\n    case 'Promise':\n      return {\n        type: 'TSTypeReference',\n        typeName: { type: 'Identifier', name: ctor },\n      }\n  }\n  // fallback to null\n  return { type: `TSNullKeyword` }\n}\n\nfunction findStaticPropertyType(node: TSTypeLiteral, key: string) {\n  const prop = node.members.find(\n    m =>\n      m.type === 'TSPropertySignature' &&\n      getStringLiteralKey(m) === key &&\n      m.typeAnnotation,\n  )\n  return prop && prop.typeAnnotation!.typeAnnotation\n}\n\nfunction resolveReturnType(\n  ctx: TypeResolveContext,\n  arg: Node,\n  scope: TypeScope,\n) {\n  let resolved: Node | undefined = arg\n  if (\n    arg.type === 'TSTypeReference' ||\n    arg.type === 'TSTypeQuery' ||\n    arg.type === 'TSImportType'\n  ) {\n    resolved = resolveTypeReference(ctx, arg, scope)\n  }\n  if (!resolved) return\n  if (resolved.type === 'TSFunctionType') {\n    return resolved.typeAnnotation?.typeAnnotation\n  }\n  if (resolved.type === 'TSDeclareFunction') {\n    return resolved.returnType\n  }\n}\n\nexport function resolveUnionType(\n  ctx: TypeResolveContext,\n  node: Node & MaybeWithScope & { _resolvedElements?: ResolvedElements },\n  scope?: TypeScope,\n): Node[] {\n  if (node.type === 'TSTypeReference') {\n    const resolved = resolveTypeReference(ctx, node, scope)\n    if (resolved) node = resolved\n  }\n\n  let types: Node[]\n  if (node.type === 'TSUnionType') {\n    types = node.types.flatMap(node => resolveUnionType(ctx, node, scope))\n  } else {\n    types = [node]\n  }\n\n  return types\n}\n"
  },
  {
    "path": "packages/compiler-sfc/src/script/topLevelAwait.ts",
    "content": "import type { AwaitExpression } from '@babel/types'\nimport type { ScriptCompileContext } from './context'\n\n/**\n * Support context-persistence between top-level await expressions:\n *\n * ```js\n * const instance = getCurrentInstance()\n * await foo()\n * expect(getCurrentInstance()).toBe(instance)\n * ```\n *\n * In the future we can potentially get rid of this when Async Context\n * becomes generally available: https://github.com/tc39/proposal-async-context\n *\n * ```js\n * // input\n * await foo()\n * // output\n * ;(\n *   ([__temp,__restore] = withAsyncContext(() => foo())),\n *   await __temp,\n *   __restore()\n * )\n *\n * // input\n * const a = await foo()\n * // output\n * const a = (\n *   ([__temp, __restore] = withAsyncContext(() => foo())),\n *   __temp = await __temp,\n *   __restore(),\n *   __temp\n * )\n * ```\n */\nexport function processAwait(\n  ctx: ScriptCompileContext,\n  node: AwaitExpression,\n  needSemi: boolean,\n  isStatement: boolean,\n): void {\n  const argumentStart =\n    node.argument.extra && node.argument.extra.parenthesized\n      ? (node.argument.extra.parenStart as number)\n      : node.argument.start!\n\n  const startOffset = ctx.startOffset!\n  const argumentStr = ctx.descriptor.source.slice(\n    argumentStart + startOffset,\n    node.argument.end! + startOffset,\n  )\n\n  const containsNestedAwait = /\\bawait\\b/.test(argumentStr)\n\n  ctx.s.overwrite(\n    node.start! + startOffset,\n    argumentStart + startOffset,\n    `${needSemi ? `;` : ``}(\\n  ([__temp,__restore] = ${ctx.helper(\n      `withAsyncContext`,\n    )}(${containsNestedAwait ? `async ` : ``}() => `,\n  )\n  ctx.s.appendLeft(\n    node.end! + startOffset,\n    `)),\\n  ${isStatement ? `` : `__temp = `}await __temp,\\n  __restore()${\n      isStatement ? `` : `,\\n  __temp`\n    }\\n)`,\n  )\n}\n"
  },
  {
    "path": "packages/compiler-sfc/src/script/utils.ts",
    "content": "import type {\n  CallExpression,\n  Expression,\n  Identifier,\n  ImportDefaultSpecifier,\n  ImportNamespaceSpecifier,\n  ImportSpecifier,\n  Node,\n  StringLiteral,\n  TSMethodSignature,\n  TSPropertySignature,\n} from '@babel/types'\nimport path from 'path'\n\nexport const UNKNOWN_TYPE = 'Unknown'\n\nexport function resolveObjectKey(\n  node: Node,\n  computed: boolean,\n): string | undefined {\n  switch (node.type) {\n    case 'StringLiteral':\n    case 'NumericLiteral':\n      return String(node.value)\n    case 'Identifier':\n      if (!computed) return node.name\n  }\n  return undefined\n}\n\nexport function concatStrings(\n  strs: Array<string | null | undefined | false>,\n): string {\n  return strs.filter((s): s is string => !!s).join(', ')\n}\n\nexport function isLiteralNode(node: Node): boolean {\n  return node.type.endsWith('Literal')\n}\n\nexport function isCallOf(\n  node: Node | null | undefined,\n  test: string | ((id: string) => boolean) | null | undefined,\n): node is CallExpression {\n  return !!(\n    node &&\n    test &&\n    node.type === 'CallExpression' &&\n    node.callee.type === 'Identifier' &&\n    (typeof test === 'string'\n      ? node.callee.name === test\n      : test(node.callee.name))\n  )\n}\n\nexport function toRuntimeTypeString(types: string[]): string {\n  return types.length > 1 ? `[${types.join(', ')}]` : types[0]\n}\n\nexport function getImportedName(\n  specifier:\n    | ImportSpecifier\n    | ImportDefaultSpecifier\n    | ImportNamespaceSpecifier,\n): string {\n  if (specifier.type === 'ImportSpecifier')\n    return specifier.imported.type === 'Identifier'\n      ? specifier.imported.name\n      : specifier.imported.value\n  else if (specifier.type === 'ImportNamespaceSpecifier') return '*'\n  return 'default'\n}\n\nexport function getId(node: Identifier | StringLiteral): string\nexport function getId(node: Expression): string | null\nexport function getId(node: Expression) {\n  return node.type === 'Identifier'\n    ? node.name\n    : node.type === 'StringLiteral'\n      ? node.value\n      : null\n}\n\nexport function getStringLiteralKey(\n  node: TSPropertySignature | TSMethodSignature,\n): string | null {\n  return node.computed\n    ? node.key.type === 'TemplateLiteral' && !node.key.expressions.length\n      ? node.key.quasis.map(q => q.value.cooked).join('')\n      : null\n    : node.key.type === 'Identifier'\n      ? node.key.name\n      : node.key.type === 'StringLiteral'\n        ? node.key.value\n        : node.key.type === 'NumericLiteral'\n          ? String(node.key.value)\n          : null\n}\n\nconst identity = (str: string) => str\nconst fileNameLowerCaseRegExp = /[^\\u0130\\u0131\\u00DFa-z0-9\\\\/:\\-_\\. ]+/g\nconst toLowerCase = (str: string) => str.toLowerCase()\n\nfunction toFileNameLowerCase(x: string) {\n  return fileNameLowerCaseRegExp.test(x)\n    ? x.replace(fileNameLowerCaseRegExp, toLowerCase)\n    : x\n}\n\n/**\n * We need `getCanonicalFileName` when creating ts module resolution cache,\n * but TS does not expose it directly. This implementation is replicated from\n * the TS source code.\n */\nexport function createGetCanonicalFileName(\n  useCaseSensitiveFileNames: boolean,\n): (str: string) => string {\n  return useCaseSensitiveFileNames ? identity : toFileNameLowerCase\n}\n\n// in the browser build, the polyfill doesn't expose posix, but defaults to\n// posix behavior.\nconst normalize = (path.posix || path).normalize\nconst windowsSlashRE = /\\\\/g\nexport function normalizePath(p: string): string {\n  return normalize(p.replace(windowsSlashRE, '/'))\n}\n\nexport const joinPaths: (...paths: string[]) => string = (path.posix || path)\n  .join\n\n/**\n * key may contain symbols\n * e.g. onUpdate:modelValue -> \"onUpdate:modelValue\"\n */\nexport const propNameEscapeSymbolsRE: RegExp =\n  /[ !\"#$%&'()*+,./:;<=>?@[\\\\\\]^`{|}~\\-]/\n\nexport function getEscapedPropName(key: string): string {\n  return propNameEscapeSymbolsRE.test(key) ? JSON.stringify(key) : key\n}\n\nexport const isJS = (...langs: (string | null | undefined)[]): boolean =>\n  langs.some(lang => lang === 'js' || lang === 'jsx')\nexport const isTS = (...langs: (string | null | undefined)[]): boolean =>\n  langs.some(lang => lang === 'ts' || lang === 'tsx')\n"
  },
  {
    "path": "packages/compiler-sfc/src/shims.d.ts",
    "content": "declare module 'merge-source-map' {\n  export default function merge(oldMap: object, newMap: object): object\n}\n"
  },
  {
    "path": "packages/compiler-sfc/src/style/cssVars.ts",
    "content": "import {\n  type BindingMetadata,\n  NodeTypes,\n  type SimpleExpressionNode,\n  createRoot,\n  createSimpleExpression,\n  createTransformContext,\n  processExpression,\n} from '@vue/compiler-dom'\nimport type { SFCDescriptor } from '../parse'\nimport type { PluginCreator } from 'postcss'\nimport hash from 'hash-sum'\nimport { getEscapedCssVarName } from '@vue/shared'\n\nexport const CSS_VARS_HELPER = `useCssVars`\n\nexport function genCssVarsFromList(\n  vars: string[],\n  id: string,\n  isProd: boolean,\n  isSSR = false,\n): string {\n  return `{\\n  ${vars\n    .map(\n      key =>\n        // The `:` prefix here is used in `ssrRenderStyle` to distinguish whether\n        // a custom property comes from `ssrCssVars`. If it does, we need to reset\n        // its value to `initial` on the component instance to avoid unintentionally\n        // inheriting the same property value from a different instance of the same\n        // component in the outer scope.\n        `\"${isSSR ? `:--` : ``}${genVarName(id, key, isProd, isSSR)}\": (${key})`,\n    )\n    .join(',\\n  ')}\\n}`\n}\n\nfunction genVarName(\n  id: string,\n  raw: string,\n  isProd: boolean,\n  isSSR = false,\n): string {\n  if (isProd) {\n    // hash must not start with a digit to comply with CSS custom property naming rules\n    return hash(id + raw).replace(/^\\d/, r => `v${r}`)\n  } else {\n    // escape ASCII Punctuation & Symbols\n    // #7823 need to double-escape in SSR because the attributes are rendered\n    // into an HTML string\n    return `${id}-${getEscapedCssVarName(raw, isSSR)}`\n  }\n}\n\nfunction normalizeExpression(exp: string) {\n  exp = exp.trim()\n  if (\n    (exp[0] === `'` && exp[exp.length - 1] === `'`) ||\n    (exp[0] === `\"` && exp[exp.length - 1] === `\"`)\n  ) {\n    return exp.slice(1, -1)\n  }\n  return exp\n}\n\nconst vBindRE = /v-bind\\s*\\(/g\n\nexport function parseCssVars(sfc: SFCDescriptor): string[] {\n  const vars: string[] = []\n  sfc.styles.forEach(style => {\n    let match\n    // ignore v-bind() in comments, eg /* ... */\n    // and // (Less, Sass and Stylus all support the use of // to comment)\n    const content = style.content.replace(/\\/\\*([\\s\\S]*?)\\*\\/|\\/\\/.*/g, '')\n    while ((match = vBindRE.exec(content))) {\n      const start = match.index + match[0].length\n      const end = lexBinding(content, start)\n      if (end !== null) {\n        const variable = normalizeExpression(content.slice(start, end))\n        if (!vars.includes(variable)) {\n          vars.push(variable)\n        }\n      }\n    }\n  })\n  return vars\n}\n\nenum LexerState {\n  inParens,\n  inSingleQuoteString,\n  inDoubleQuoteString,\n}\n\nfunction lexBinding(content: string, start: number): number | null {\n  let state: LexerState = LexerState.inParens\n  let parenDepth = 0\n\n  for (let i = start; i < content.length; i++) {\n    const char = content.charAt(i)\n    switch (state) {\n      case LexerState.inParens:\n        if (char === `'`) {\n          state = LexerState.inSingleQuoteString\n        } else if (char === `\"`) {\n          state = LexerState.inDoubleQuoteString\n        } else if (char === `(`) {\n          parenDepth++\n        } else if (char === `)`) {\n          if (parenDepth > 0) {\n            parenDepth--\n          } else {\n            return i\n          }\n        }\n        break\n      case LexerState.inSingleQuoteString:\n        if (char === `'`) {\n          state = LexerState.inParens\n        }\n        break\n      case LexerState.inDoubleQuoteString:\n        if (char === `\"`) {\n          state = LexerState.inParens\n        }\n        break\n    }\n  }\n  return null\n}\n\n// for compileStyle\nexport interface CssVarsPluginOptions {\n  id: string\n  isProd: boolean\n}\n\nexport const cssVarsPlugin: PluginCreator<CssVarsPluginOptions> = opts => {\n  const { id, isProd } = opts!\n  return {\n    postcssPlugin: 'vue-sfc-vars',\n    Declaration(decl) {\n      // rewrite CSS variables\n      const value = decl.value\n      if (vBindRE.test(value)) {\n        vBindRE.lastIndex = 0\n        let transformed = ''\n        let lastIndex = 0\n        let match\n        while ((match = vBindRE.exec(value))) {\n          const start = match.index + match[0].length\n          const end = lexBinding(value, start)\n          if (end !== null) {\n            const variable = normalizeExpression(value.slice(start, end))\n            transformed +=\n              value.slice(lastIndex, match.index) +\n              `var(--${genVarName(id, variable, isProd)})`\n            lastIndex = end + 1\n          }\n        }\n        decl.value = transformed + value.slice(lastIndex)\n      }\n    },\n  }\n}\ncssVarsPlugin.postcss = true\n\nexport function genCssVarsCode(\n  vars: string[],\n  bindings: BindingMetadata,\n  id: string,\n  isProd: boolean,\n) {\n  const varsExp = genCssVarsFromList(vars, id, isProd)\n  const exp = createSimpleExpression(varsExp, false)\n  const context = createTransformContext(createRoot([]), {\n    prefixIdentifiers: true,\n    inline: true,\n    bindingMetadata: bindings.__isScriptSetup === false ? undefined : bindings,\n  })\n  const transformed = processExpression(exp, context)\n  const transformedString =\n    transformed.type === NodeTypes.SIMPLE_EXPRESSION\n      ? transformed.content\n      : transformed.children\n          .map(c => {\n            return typeof c === 'string'\n              ? c\n              : (c as SimpleExpressionNode).content\n          })\n          .join('')\n\n  return `_${CSS_VARS_HELPER}(_ctx => (${transformedString}))`\n}\n\n// <script setup> already gets the calls injected as part of the transform\n// this is only for single normal <script>\nexport function genNormalScriptCssVarsCode(\n  cssVars: string[],\n  bindings: BindingMetadata,\n  id: string,\n  isProd: boolean,\n  defaultVar: string,\n): string {\n  return (\n    `\\nimport { ${CSS_VARS_HELPER} as _${CSS_VARS_HELPER} } from 'vue'\\n` +\n    `const __injectCSSVars__ = () => {\\n${genCssVarsCode(\n      cssVars,\n      bindings,\n      id,\n      isProd,\n    )}}\\n` +\n    `const __setup__ = ${defaultVar}.setup\\n` +\n    `${defaultVar}.setup = __setup__\\n` +\n    `  ? (props, ctx) => { __injectCSSVars__();return __setup__(props, ctx) }\\n` +\n    `  : __injectCSSVars__\\n`\n  )\n}\n"
  },
  {
    "path": "packages/compiler-sfc/src/style/pluginScoped.ts",
    "content": "import {\n  type AtRule,\n  type Container,\n  type Document,\n  type PluginCreator,\n  Rule,\n} from 'postcss'\nimport selectorParser from 'postcss-selector-parser'\nimport { warn } from '../warn'\n\nconst animationNameRE = /^(?:-\\w+-)?animation-name$/\nconst animationRE = /^(?:-\\w+-)?animation$/\nconst keyframesRE = /^(?:-\\w+-)?keyframes$/\n\nconst scopedPlugin: PluginCreator<string> = (id = '') => {\n  const keyframes = Object.create(null)\n  const shortId = id.replace(/^data-v-/, '')\n\n  return {\n    postcssPlugin: 'vue-sfc-scoped',\n    Rule(rule) {\n      processRule(id, rule)\n    },\n    AtRule(node) {\n      if (keyframesRE.test(node.name) && !node.params.endsWith(`-${shortId}`)) {\n        // register keyframes\n        keyframes[node.params] = node.params = node.params + '-' + shortId\n      }\n    },\n    OnceExit(root) {\n      if (Object.keys(keyframes).length) {\n        // If keyframes are found in this <style>, find and rewrite animation names\n        // in declarations.\n        // Caveat: this only works for keyframes and animation rules in the same\n        // <style> element.\n        // individual animation-name declaration\n        root.walkDecls(decl => {\n          if (animationNameRE.test(decl.prop)) {\n            decl.value = decl.value\n              .split(',')\n              .map(v => keyframes[v.trim()] || v.trim())\n              .join(',')\n          }\n          // shorthand\n          if (animationRE.test(decl.prop)) {\n            decl.value = decl.value\n              .split(',')\n              .map(v => {\n                const vals = v.trim().split(/\\s+/)\n                const i = vals.findIndex(val => keyframes[val])\n                if (i !== -1) {\n                  vals.splice(i, 1, keyframes[vals[i]])\n                  return vals.join(' ')\n                } else {\n                  return v\n                }\n              })\n              .join(',')\n          }\n        })\n      }\n    },\n  }\n}\n\nconst processedRules = new WeakSet<Rule>()\n\nfunction processRule(id: string, rule: Rule) {\n  if (\n    processedRules.has(rule) ||\n    (rule.parent &&\n      rule.parent.type === 'atrule' &&\n      keyframesRE.test((rule.parent as AtRule).name))\n  ) {\n    return\n  }\n  processedRules.add(rule)\n  let deep = false\n  let parent: Document | Container | undefined = rule.parent\n  while (parent && parent.type !== 'root') {\n    if ((parent as any).__deep) {\n      deep = true\n      break\n    }\n    parent = parent.parent\n  }\n  rule.selector = selectorParser(selectorRoot => {\n    selectorRoot.each(selector => {\n      rewriteSelector(id, rule, selector, selectorRoot, deep)\n    })\n  }).processSync(rule.selector)\n}\n\nfunction rewriteSelector(\n  id: string,\n  rule: Rule,\n  selector: selectorParser.Selector,\n  selectorRoot: selectorParser.Root,\n  deep: boolean,\n  slotted = false,\n) {\n  let node: selectorParser.Node | null = null\n  let shouldInject = !deep\n  // find the last child node to insert attribute selector\n  selector.each(n => {\n    // DEPRECATED \">>>\" and \"/deep/\" combinator\n    if (\n      n.type === 'combinator' &&\n      (n.value === '>>>' || n.value === '/deep/')\n    ) {\n      n.value = ' '\n      n.spaces.before = n.spaces.after = ''\n      warn(\n        `the >>> and /deep/ combinators have been deprecated. ` +\n          `Use :deep() instead.`,\n      )\n      return false\n    }\n\n    if (n.type === 'pseudo') {\n      const { value } = n\n      // deep: inject [id] attribute at the node before the ::v-deep\n      // combinator.\n      if (value === ':deep' || value === '::v-deep') {\n        ;(rule as any).__deep = true\n        if (n.nodes.length) {\n          // .foo ::v-deep(.bar) -> .foo[xxxxxxx] .bar\n          // replace the current node with ::v-deep's inner selector\n          let last: selectorParser.Selector['nodes'][0] = n\n          n.nodes[0].each(ss => {\n            selector.insertAfter(last, ss)\n            last = ss\n          })\n          // insert a space combinator before if it doesn't already have one\n          const prev = selector.at(selector.index(n) - 1)\n          if (!prev || !isSpaceCombinator(prev)) {\n            selector.insertAfter(\n              n,\n              selectorParser.combinator({\n                value: ' ',\n              }),\n            )\n          }\n          selector.removeChild(n)\n        } else {\n          // DEPRECATED usage\n          // .foo ::v-deep .bar -> .foo[xxxxxxx] .bar\n          warn(\n            `${value} usage as a combinator has been deprecated. ` +\n              `Use :deep(<inner-selector>) instead of ${value} <inner-selector>.`,\n          )\n\n          const prev = selector.at(selector.index(n) - 1)\n          if (prev && isSpaceCombinator(prev)) {\n            selector.removeChild(prev)\n          }\n          selector.removeChild(n)\n        }\n        return false\n      }\n\n      // slot: use selector inside `::v-slotted` and inject [id + '-s']\n      // instead.\n      // ::v-slotted(.foo) -> .foo[xxxxxxx-s]\n      if (value === ':slotted' || value === '::v-slotted') {\n        rewriteSelector(\n          id,\n          rule,\n          n.nodes[0],\n          selectorRoot,\n          deep,\n          true /* slotted */,\n        )\n        let last: selectorParser.Selector['nodes'][0] = n\n        n.nodes[0].each(ss => {\n          selector.insertAfter(last, ss)\n          last = ss\n        })\n        // selector.insertAfter(n, n.nodes[0])\n        selector.removeChild(n)\n        // since slotted attribute already scopes the selector there's no\n        // need for the non-slot attribute.\n        shouldInject = false\n        return false\n      }\n\n      // global: replace with inner selector and do not inject [id].\n      // ::v-global(.foo) -> .foo\n      if (value === ':global' || value === '::v-global') {\n        selector.replaceWith(n.nodes[0])\n        return false\n      }\n    }\n\n    if (n.type === 'universal') {\n      const prev = selector.at(selector.index(n) - 1)\n      const next = selector.at(selector.index(n) + 1)\n      // * ... {}\n      if (!prev) {\n        // * .foo {} -> .foo[xxxxxxx] {}\n        if (next) {\n          if (next.type === 'combinator' && next.value === ' ') {\n            selector.removeChild(next)\n          }\n          selector.removeChild(n)\n          return\n        } else {\n          // * {} -> [xxxxxxx] {}\n          node = selectorParser.combinator({\n            value: '',\n          })\n          selector.insertBefore(n, node)\n          selector.removeChild(n)\n          return false\n        }\n      }\n      // .foo * -> .foo[xxxxxxx] *\n      if (node) return\n    }\n\n    if (\n      (n.type !== 'pseudo' && n.type !== 'combinator') ||\n      (n.type === 'pseudo' &&\n        (n.value === ':is' || n.value === ':where') &&\n        !node)\n    ) {\n      node = n\n    }\n  })\n\n  if (rule.nodes.some(node => node.type === 'rule')) {\n    const deep = (rule as any).__deep\n    if (!deep) {\n      extractAndWrapNodes(rule)\n      const atruleNodes = rule.nodes.filter(node => node.type === 'atrule')\n      for (const atnode of atruleNodes) {\n        extractAndWrapNodes(atnode)\n      }\n    }\n    shouldInject = deep\n  }\n\n  if (node) {\n    const { type, value } = node as selectorParser.Node\n    if (type === 'pseudo' && (value === ':is' || value === ':where')) {\n      ;(node as selectorParser.Pseudo).nodes.forEach(value =>\n        rewriteSelector(id, rule, value, selectorRoot, deep, slotted),\n      )\n      shouldInject = false\n    }\n  }\n\n  if (node) {\n    ;(node as selectorParser.Node).spaces.after = ''\n  } else {\n    // For deep selectors & standalone pseudo selectors,\n    // the attribute selectors are prepended rather than appended.\n    // So all leading spaces must be eliminated to avoid problems.\n    selector.first.spaces.before = ''\n  }\n\n  if (shouldInject) {\n    const idToAdd = slotted ? id + '-s' : id\n    selector.insertAfter(\n      // If node is null it means we need to inject [id] at the start\n      // insertAfter can handle `null` here\n      node as any,\n      selectorParser.attribute({\n        attribute: idToAdd,\n        value: idToAdd,\n        raws: {},\n        quoteMark: `\"`,\n      }),\n    )\n  }\n}\n\nfunction isSpaceCombinator(node: selectorParser.Node) {\n  return node.type === 'combinator' && /^\\s+$/.test(node.value)\n}\n\nfunction extractAndWrapNodes(parentNode: Rule | AtRule) {\n  if (!parentNode.nodes) return\n  const nodes = parentNode.nodes.filter(\n    node => node.type === 'decl' || node.type === 'comment',\n  )\n  if (nodes.length) {\n    for (const node of nodes) {\n      parentNode.removeChild(node)\n    }\n    const wrappedRule = new Rule({\n      nodes: nodes,\n      selector: '&',\n    })\n    parentNode.prepend(wrappedRule)\n  }\n}\n\nscopedPlugin.postcss = true\nexport default scopedPlugin\n"
  },
  {
    "path": "packages/compiler-sfc/src/style/pluginTrim.ts",
    "content": "import type { PluginCreator } from 'postcss'\n\nconst trimPlugin: PluginCreator<{}> = () => {\n  return {\n    postcssPlugin: 'vue-sfc-trim',\n    Once(root) {\n      root.walk(({ type, raws }) => {\n        if (type === 'rule' || type === 'atrule') {\n          if (raws.before) raws.before = '\\n'\n          if ('after' in raws && raws.after) raws.after = '\\n'\n        }\n      })\n    },\n  }\n}\n\ntrimPlugin.postcss = true\nexport default trimPlugin\n"
  },
  {
    "path": "packages/compiler-sfc/src/style/preprocessors.ts",
    "content": "import merge from 'merge-source-map'\nimport type { RawSourceMap } from '@vue/compiler-core'\nimport type { SFCStyleCompileOptions } from '../compileStyle'\nimport { isFunction } from '@vue/shared'\n\nexport type StylePreprocessor = (\n  source: string,\n  map: RawSourceMap | undefined,\n  options: {\n    [key: string]: any\n    additionalData?: string | ((source: string, filename: string) => string)\n    filename: string\n  },\n  customRequire: SFCStyleCompileOptions['preprocessCustomRequire'],\n) => StylePreprocessorResults\n\nexport interface StylePreprocessorResults {\n  code: string\n  map?: object\n  errors: Error[]\n  dependencies: string[]\n}\n\n// .scss/.sass processor\nconst scss: StylePreprocessor = (source, map, options, load = require) => {\n  const nodeSass: typeof import('sass') = load('sass')\n  const { compileString, renderSync } = nodeSass\n\n  const data = getSource(source, options.filename, options.additionalData)\n  let css: string\n  let dependencies: string[]\n  let sourceMap: any\n\n  try {\n    if (compileString) {\n      const { pathToFileURL, fileURLToPath }: typeof import('url') = load('url')\n\n      const result = compileString(data, {\n        ...options,\n        url: pathToFileURL(options.filename),\n        sourceMap: !!map,\n      })\n      css = result.css\n      dependencies = result.loadedUrls.map(url => fileURLToPath(url))\n      sourceMap = map ? result.sourceMap! : undefined\n    } else {\n      const result = renderSync({\n        ...options,\n        data,\n        file: options.filename,\n        outFile: options.filename,\n        sourceMap: !!map,\n      })\n      css = result.css.toString()\n      dependencies = result.stats.includedFiles\n      sourceMap = map ? JSON.parse(result.map!.toString()) : undefined\n    }\n\n    if (map) {\n      return {\n        code: css,\n        errors: [],\n        dependencies,\n        map: merge(map, sourceMap!),\n      }\n    }\n    return { code: css, errors: [], dependencies }\n  } catch (e: any) {\n    return { code: '', errors: [e], dependencies: [] }\n  }\n}\n\nconst sass: StylePreprocessor = (source, map, options, load) =>\n  scss(\n    source,\n    map,\n    {\n      ...options,\n      indentedSyntax: true,\n    },\n    load,\n  )\n\n// .less\nconst less: StylePreprocessor = (source, map, options, load = require) => {\n  const nodeLess = load('less')\n\n  let result: any\n  let error: Error | null = null\n  nodeLess.render(\n    getSource(source, options.filename, options.additionalData),\n    { ...options, syncImport: true },\n    (err: Error | null, output: any) => {\n      error = err\n      result = output\n    },\n  )\n\n  if (error) return { code: '', errors: [error], dependencies: [] }\n  const dependencies = result.imports\n  if (map) {\n    return {\n      code: result.css.toString(),\n      map: merge(map, result.map),\n      errors: [],\n      dependencies: dependencies,\n    }\n  }\n\n  return {\n    code: result.css.toString(),\n    errors: [],\n    dependencies: dependencies,\n  }\n}\n\n// .styl\nconst styl: StylePreprocessor = (source, map, options, load = require) => {\n  const nodeStylus = load('stylus')\n  try {\n    const ref = nodeStylus(source, options)\n    if (map) ref.set('sourcemap', { inline: false, comment: false })\n\n    const result = ref.render()\n    const dependencies = ref.deps()\n    if (map) {\n      return {\n        code: result,\n        map: merge(map, ref.sourcemap),\n        errors: [],\n        dependencies,\n      }\n    }\n\n    return { code: result, errors: [], dependencies }\n  } catch (e: any) {\n    return { code: '', errors: [e], dependencies: [] }\n  }\n}\n\nfunction getSource(\n  source: string,\n  filename: string,\n  additionalData?: string | ((source: string, filename: string) => string),\n) {\n  if (!additionalData) return source\n  if (isFunction(additionalData)) {\n    return additionalData(source, filename)\n  }\n  return additionalData + source\n}\n\nexport type PreprocessLang = 'less' | 'sass' | 'scss' | 'styl' | 'stylus'\n\nexport const processors: Record<PreprocessLang, StylePreprocessor> = {\n  less,\n  sass,\n  scss,\n  styl,\n  stylus: styl,\n}\n"
  },
  {
    "path": "packages/compiler-sfc/src/template/templateUtils.ts",
    "content": "import { type UrlWithStringQuery, parse as uriParse } from 'url'\nimport { isString } from '@vue/shared'\n\nexport function isRelativeUrl(url: string): boolean {\n  const firstChar = url.charAt(0)\n  return firstChar === '.' || firstChar === '~' || firstChar === '@'\n}\n\nconst externalRE = /^(?:https?:)?\\/\\//\nexport function isExternalUrl(url: string): boolean {\n  return externalRE.test(url)\n}\n\nconst dataUrlRE = /^\\s*data:/i\nexport function isDataUrl(url: string): boolean {\n  return dataUrlRE.test(url)\n}\n\n/**\n * Parses string url into URL object.\n */\nexport function parseUrl(url: string): UrlWithStringQuery {\n  const firstChar = url.charAt(0)\n  if (firstChar === '~') {\n    const secondChar = url.charAt(1)\n    url = url.slice(secondChar === '/' ? 2 : 1)\n  }\n  return parseUriParts(url)\n}\n\n/**\n * vuejs/component-compiler-utils#22 Support uri fragment in transformed require\n * @param urlString - an url as a string\n */\nfunction parseUriParts(urlString: string): UrlWithStringQuery {\n  // A TypeError is thrown if urlString is not a string\n  // @see https://nodejs.org/api/url.html#url_url_parse_urlstring_parsequerystring_slashesdenotehost\n  return uriParse(isString(urlString) ? urlString : '', false, true)\n}\n"
  },
  {
    "path": "packages/compiler-sfc/src/template/transformAssetUrl.ts",
    "content": "import path from 'path'\nimport {\n  ConstantTypes,\n  type ExpressionNode,\n  type NodeTransform,\n  NodeTypes,\n  type SimpleExpressionNode,\n  type SourceLocation,\n  type TransformContext,\n  createSimpleExpression,\n} from '@vue/compiler-core'\nimport {\n  isDataUrl,\n  isExternalUrl,\n  isRelativeUrl,\n  parseUrl,\n} from './templateUtils'\nimport { isArray } from '@vue/shared'\n\nexport interface AssetURLTagConfig {\n  [name: string]: string[]\n}\n\nexport interface AssetURLOptions {\n  /**\n   * If base is provided, instead of transforming relative asset urls into\n   * imports, they will be directly rewritten to absolute urls.\n   */\n  base?: string | null\n  /**\n   * If true, also processes absolute urls.\n   */\n  includeAbsolute?: boolean\n  tags?: AssetURLTagConfig\n}\n\nexport const defaultAssetUrlOptions: Required<AssetURLOptions> = {\n  base: null,\n  includeAbsolute: false,\n  tags: {\n    video: ['src', 'poster'],\n    source: ['src'],\n    img: ['src'],\n    image: ['xlink:href', 'href'],\n    use: ['xlink:href', 'href'],\n  },\n}\n\nexport const normalizeOptions = (\n  options: AssetURLOptions | AssetURLTagConfig,\n): Required<AssetURLOptions> => {\n  if (Object.keys(options).some(key => isArray((options as any)[key]))) {\n    // legacy option format which directly passes in tags config\n    return {\n      ...defaultAssetUrlOptions,\n      tags: options as any,\n    }\n  }\n  return {\n    ...defaultAssetUrlOptions,\n    ...options,\n  }\n}\n\nexport const createAssetUrlTransformWithOptions = (\n  options: Required<AssetURLOptions>,\n): NodeTransform => {\n  return (node, context) =>\n    (transformAssetUrl as Function)(node, context, options)\n}\n\n/**\n * A `@vue/compiler-core` plugin that transforms relative asset urls into\n * either imports or absolute urls.\n *\n * ``` js\n * // Before\n * createVNode('img', { src: './logo.png' })\n *\n * // After\n * import _imports_0 from './logo.png'\n * createVNode('img', { src: _imports_0 })\n * ```\n */\nexport const transformAssetUrl: NodeTransform = (\n  node,\n  context,\n  options: AssetURLOptions = defaultAssetUrlOptions,\n) => {\n  if (node.type === NodeTypes.ELEMENT) {\n    if (!node.props.length) {\n      return\n    }\n\n    const tags = options.tags || defaultAssetUrlOptions.tags\n    const attrs = tags[node.tag]\n    const wildCardAttrs = tags['*']\n    if (!attrs && !wildCardAttrs) {\n      return\n    }\n\n    const assetAttrs = (attrs || []).concat(wildCardAttrs || [])\n    node.props.forEach((attr, index) => {\n      if (\n        attr.type !== NodeTypes.ATTRIBUTE ||\n        !assetAttrs.includes(attr.name) ||\n        !attr.value ||\n        isExternalUrl(attr.value.content) ||\n        isDataUrl(attr.value.content) ||\n        attr.value.content[0] === '#' ||\n        (!options.includeAbsolute && !isRelativeUrl(attr.value.content))\n      ) {\n        return\n      }\n\n      const url = parseUrl(attr.value.content)\n      if (options.base && attr.value.content[0] === '.') {\n        // explicit base - directly rewrite relative urls into absolute url\n        // to avoid generating extra imports\n        // Allow for full hostnames provided in options.base\n        const base = parseUrl(options.base)\n        const protocol = base.protocol || ''\n        const host = base.host ? protocol + '//' + base.host : ''\n        const basePath = base.path || '/'\n\n        // when packaged in the browser, path will be using the posix-\n        // only version provided by rollup-plugin-node-builtins.\n        attr.value.content =\n          host +\n          (path.posix || path).join(basePath, url.path + (url.hash || ''))\n        return\n      }\n\n      // otherwise, transform the url into an import.\n      // this assumes a bundler will resolve the import into the correct\n      // absolute url (e.g. webpack file-loader)\n      const exp = getImportsExpressionExp(url.path, url.hash, attr.loc, context)\n      node.props[index] = {\n        type: NodeTypes.DIRECTIVE,\n        name: 'bind',\n        arg: createSimpleExpression(attr.name, true, attr.loc),\n        exp,\n        modifiers: [],\n        loc: attr.loc,\n      }\n    })\n  }\n}\n\nfunction getImportsExpressionExp(\n  path: string | null,\n  hash: string | null,\n  loc: SourceLocation,\n  context: TransformContext,\n): ExpressionNode {\n  if (path) {\n    let name: string\n    let exp: SimpleExpressionNode\n    const existingIndex = context.imports.findIndex(i => i.path === path)\n    if (existingIndex > -1) {\n      name = `_imports_${existingIndex}`\n      exp = context.imports[existingIndex].exp as SimpleExpressionNode\n    } else {\n      name = `_imports_${context.imports.length}`\n      exp = createSimpleExpression(\n        name,\n        false,\n        loc,\n        ConstantTypes.CAN_STRINGIFY,\n      )\n\n      // We need to ensure the path is not encoded (to %2F),\n      // so we decode it back in case it is encoded\n      context.imports.push({\n        exp,\n        path: decodeURIComponent(path),\n      })\n    }\n\n    if (!hash) {\n      return exp\n    }\n\n    const hashExp = `${name} + '${hash}'`\n    const finalExp = createSimpleExpression(\n      hashExp,\n      false,\n      loc,\n      ConstantTypes.CAN_STRINGIFY,\n    )\n\n    if (!context.hoistStatic) {\n      return finalExp\n    }\n\n    const existingHoistIndex = context.hoists.findIndex(h => {\n      return (\n        h &&\n        h.type === NodeTypes.SIMPLE_EXPRESSION &&\n        !h.isStatic &&\n        h.content === hashExp\n      )\n    })\n    if (existingHoistIndex > -1) {\n      return createSimpleExpression(\n        `_hoisted_${existingHoistIndex + 1}`,\n        false,\n        loc,\n        ConstantTypes.CAN_STRINGIFY,\n      )\n    }\n    return context.hoist(finalExp)\n  } else {\n    return createSimpleExpression(`''`, false, loc, ConstantTypes.CAN_STRINGIFY)\n  }\n}\n"
  },
  {
    "path": "packages/compiler-sfc/src/template/transformSrcset.ts",
    "content": "import path from 'path'\nimport {\n  ConstantTypes,\n  type ExpressionNode,\n  type NodeTransform,\n  NodeTypes,\n  type SimpleExpressionNode,\n  createCompoundExpression,\n  createSimpleExpression,\n} from '@vue/compiler-core'\nimport {\n  isDataUrl,\n  isExternalUrl,\n  isRelativeUrl,\n  parseUrl,\n} from './templateUtils'\nimport {\n  type AssetURLOptions,\n  defaultAssetUrlOptions,\n} from './transformAssetUrl'\n\nconst srcsetTags = ['img', 'source']\n\ninterface ImageCandidate {\n  url: string\n  descriptor: string\n}\n\n// http://w3c.github.io/html/semantics-embedded-content.html#ref-for-image-candidate-string-5\nconst escapedSpaceCharacters = /( |\\\\t|\\\\n|\\\\f|\\\\r)+/g\n\nexport const createSrcsetTransformWithOptions = (\n  options: Required<AssetURLOptions>,\n): NodeTransform => {\n  return (node, context) =>\n    (transformSrcset as Function)(node, context, options)\n}\n\nexport const transformSrcset: NodeTransform = (\n  node,\n  context,\n  options: Required<AssetURLOptions> = defaultAssetUrlOptions,\n) => {\n  if (node.type === NodeTypes.ELEMENT) {\n    if (srcsetTags.includes(node.tag) && node.props.length) {\n      node.props.forEach((attr, index) => {\n        if (attr.name === 'srcset' && attr.type === NodeTypes.ATTRIBUTE) {\n          if (!attr.value) return\n          const value = attr.value.content\n          if (!value) return\n          const imageCandidates: ImageCandidate[] = value.split(',').map(s => {\n            // The attribute value arrives here with all whitespace, except\n            // normal spaces, represented by escape sequences\n            const [url, descriptor] = s\n              .replace(escapedSpaceCharacters, ' ')\n              .trim()\n              .split(' ', 2)\n            return { url, descriptor }\n          })\n\n          // data urls contains comma after the encoding so we need to re-merge\n          // them\n          for (let i = 0; i < imageCandidates.length; i++) {\n            const { url } = imageCandidates[i]\n            if (isDataUrl(url)) {\n              imageCandidates[i + 1].url =\n                url + ',' + imageCandidates[i + 1].url\n              imageCandidates.splice(i, 1)\n            }\n          }\n\n          const shouldProcessUrl = (url: string) => {\n            return (\n              url &&\n              !isExternalUrl(url) &&\n              !isDataUrl(url) &&\n              (options.includeAbsolute || isRelativeUrl(url))\n            )\n          }\n          // When srcset does not contain any qualified URLs, skip transforming\n          if (!imageCandidates.some(({ url }) => shouldProcessUrl(url))) {\n            return\n          }\n\n          if (options.base) {\n            const base = options.base\n            const set: string[] = []\n            let needImportTransform = false\n\n            imageCandidates.forEach(candidate => {\n              let { url, descriptor } = candidate\n              descriptor = descriptor ? ` ${descriptor}` : ``\n              if (url[0] === '.') {\n                candidate.url = (path.posix || path).join(base, url)\n                set.push(candidate.url + descriptor)\n              } else if (shouldProcessUrl(url)) {\n                needImportTransform = true\n              } else {\n                set.push(url + descriptor)\n              }\n            })\n\n            if (!needImportTransform) {\n              attr.value.content = set.join(', ')\n              return\n            }\n          }\n\n          const compoundExpression = createCompoundExpression([], attr.loc)\n          imageCandidates.forEach(({ url, descriptor }, index) => {\n            if (shouldProcessUrl(url)) {\n              const { path } = parseUrl(url)\n              let exp: SimpleExpressionNode\n              if (path) {\n                const existingImportsIndex = context.imports.findIndex(\n                  i => i.path === path,\n                )\n                if (existingImportsIndex > -1) {\n                  exp = createSimpleExpression(\n                    `_imports_${existingImportsIndex}`,\n                    false,\n                    attr.loc,\n                    ConstantTypes.CAN_STRINGIFY,\n                  )\n                } else {\n                  exp = createSimpleExpression(\n                    `_imports_${context.imports.length}`,\n                    false,\n                    attr.loc,\n                    ConstantTypes.CAN_STRINGIFY,\n                  )\n                  context.imports.push({ exp, path })\n                }\n                compoundExpression.children.push(exp)\n              }\n            } else {\n              const exp = createSimpleExpression(\n                `\"${url}\"`,\n                false,\n                attr.loc,\n                ConstantTypes.CAN_STRINGIFY,\n              )\n              compoundExpression.children.push(exp)\n            }\n            const isNotLast = imageCandidates.length - 1 > index\n            if (descriptor && isNotLast) {\n              compoundExpression.children.push(` + ' ${descriptor}, ' + `)\n            } else if (descriptor) {\n              compoundExpression.children.push(` + ' ${descriptor}'`)\n            } else if (isNotLast) {\n              compoundExpression.children.push(` + ', ' + `)\n            }\n          })\n\n          let exp: ExpressionNode = compoundExpression\n          if (context.hoistStatic) {\n            exp = context.hoist(compoundExpression)\n            exp.constType = ConstantTypes.CAN_STRINGIFY\n          }\n\n          node.props[index] = {\n            type: NodeTypes.DIRECTIVE,\n            name: 'bind',\n            arg: createSimpleExpression('srcset', true, attr.loc),\n            exp,\n            modifiers: [],\n            loc: attr.loc,\n          }\n        }\n      })\n    }\n  }\n}\n"
  },
  {
    "path": "packages/compiler-sfc/src/warn.ts",
    "content": "const hasWarned: Record<string, boolean> = {}\n\nexport function warnOnce(msg: string): void {\n  const isNodeProd =\n    typeof process !== 'undefined' && process.env.NODE_ENV === 'production'\n  if (!isNodeProd && !__TEST__ && !hasWarned[msg]) {\n    hasWarned[msg] = true\n    warn(msg)\n  }\n}\n\nexport function warn(msg: string): void {\n  console.warn(\n    `\\x1b[1m\\x1b[33m[@vue/compiler-sfc]\\x1b[0m\\x1b[33m ${msg}\\x1b[0m\\n`,\n  )\n}\n"
  },
  {
    "path": "packages/compiler-ssr/LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2018-present, Yuxi (Evan) You\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "packages/compiler-ssr/README.md",
    "content": "# @vue/compiler-ssr\n"
  },
  {
    "path": "packages/compiler-ssr/__tests__/ssrComponent.spec.ts",
    "content": "import { compile } from '../src'\n\ndescribe('ssr: components', () => {\n  test('basic', () => {\n    expect(compile(`<foo id=\"a\" :prop=\"b\" />`).code).toMatchInlineSnapshot(`\n      \"const { resolveComponent: _resolveComponent, mergeProps: _mergeProps } = require(\"vue\")\n      const { ssrRenderComponent: _ssrRenderComponent } = require(\"vue/server-renderer\")\n\n      return function ssrRender(_ctx, _push, _parent, _attrs) {\n        const _component_foo = _resolveComponent(\"foo\")\n\n        _push(_ssrRenderComponent(_component_foo, _mergeProps({\n          id: \"a\",\n          prop: _ctx.b\n        }, _attrs), null, _parent))\n      }\"\n    `)\n  })\n\n  // event listeners should still be passed\n  test('event listeners', () => {\n    expect(compile(`<foo @click=\"bar\" />`).code).toMatchInlineSnapshot(`\n      \"const { resolveComponent: _resolveComponent, mergeProps: _mergeProps } = require(\"vue\")\n      const { ssrRenderComponent: _ssrRenderComponent } = require(\"vue/server-renderer\")\n\n      return function ssrRender(_ctx, _push, _parent, _attrs) {\n        const _component_foo = _resolveComponent(\"foo\")\n\n        _push(_ssrRenderComponent(_component_foo, _mergeProps({ onClick: _ctx.bar }, _attrs), null, _parent))\n      }\"\n    `)\n  })\n\n  test('dynamic component', () => {\n    expect(compile(`<component is=\"foo\" prop=\"b\" />`).code)\n      .toMatchInlineSnapshot(`\n        \"const { resolveDynamicComponent: _resolveDynamicComponent, mergeProps: _mergeProps, createVNode: _createVNode } = require(\"vue\")\n        const { ssrRenderVNode: _ssrRenderVNode } = require(\"vue/server-renderer\")\n\n        return function ssrRender(_ctx, _push, _parent, _attrs) {\n          _ssrRenderVNode(_push, _createVNode(_resolveDynamicComponent(\"foo\"), _mergeProps({ prop: \"b\" }, _attrs), null), _parent)\n        }\"\n      `)\n\n    expect(compile(`<component :is=\"foo\" prop=\"b\" />`).code)\n      .toMatchInlineSnapshot(`\n        \"const { resolveDynamicComponent: _resolveDynamicComponent, mergeProps: _mergeProps, createVNode: _createVNode } = require(\"vue\")\n        const { ssrRenderVNode: _ssrRenderVNode } = require(\"vue/server-renderer\")\n\n        return function ssrRender(_ctx, _push, _parent, _attrs) {\n          _ssrRenderVNode(_push, _createVNode(_resolveDynamicComponent(_ctx.foo), _mergeProps({ prop: \"b\" }, _attrs), null), _parent)\n        }\"\n      `)\n  })\n\n  describe('slots', () => {\n    test('implicit default slot', () => {\n      expect(compile(`<foo>hello<div/></foo>`).code).toMatchInlineSnapshot(`\n        \"const { resolveComponent: _resolveComponent, withCtx: _withCtx, createVNode: _createVNode, createTextVNode: _createTextVNode } = require(\"vue\")\n        const { ssrRenderComponent: _ssrRenderComponent } = require(\"vue/server-renderer\")\n\n        return function ssrRender(_ctx, _push, _parent, _attrs) {\n          const _component_foo = _resolveComponent(\"foo\")\n\n          _push(_ssrRenderComponent(_component_foo, _attrs, {\n            default: _withCtx((_, _push, _parent, _scopeId) => {\n              if (_push) {\n                _push(\\`hello<div\\${_scopeId}></div>\\`)\n              } else {\n                return [\n                  _createTextVNode(\"hello\"),\n                  _createVNode(\"div\")\n                ]\n              }\n            }),\n            _: 1 /* STABLE */\n          }, _parent))\n        }\"\n      `)\n    })\n\n    test('explicit default slot', () => {\n      expect(compile(`<foo v-slot=\"{ msg }\">{{ msg + outer }}</foo>`).code)\n        .toMatchInlineSnapshot(`\n          \"const { resolveComponent: _resolveComponent, withCtx: _withCtx, toDisplayString: _toDisplayString, createTextVNode: _createTextVNode } = require(\"vue\")\n          const { ssrRenderComponent: _ssrRenderComponent, ssrInterpolate: _ssrInterpolate } = require(\"vue/server-renderer\")\n\n          return function ssrRender(_ctx, _push, _parent, _attrs) {\n            const _component_foo = _resolveComponent(\"foo\")\n\n            _push(_ssrRenderComponent(_component_foo, _attrs, {\n              default: _withCtx(({ msg }, _push, _parent, _scopeId) => {\n                if (_push) {\n                  _push(\\`\\${_ssrInterpolate(msg + _ctx.outer)}\\`)\n                } else {\n                  return [\n                    _createTextVNode(_toDisplayString(msg + _ctx.outer), 1 /* TEXT */)\n                  ]\n                }\n              }),\n              _: 1 /* STABLE */\n            }, _parent))\n          }\"\n        `)\n    })\n\n    test('empty attribute should not produce syntax error', () => {\n      // previously this would produce syntax error `default: _withCtx((, _push, ...)`\n      expect(compile(`<foo v-slot=\"\">foo</foo>`).code).not.toMatch(`(,`)\n    })\n\n    test('named slots', () => {\n      expect(\n        compile(`<foo>\n        <template v-slot>foo</template>\n        <template v-slot:named>bar</template>\n      </foo>`).code,\n      ).toMatchInlineSnapshot(`\n        \"const { resolveComponent: _resolveComponent, withCtx: _withCtx, createTextVNode: _createTextVNode } = require(\"vue\")\n        const { ssrRenderComponent: _ssrRenderComponent } = require(\"vue/server-renderer\")\n\n        return function ssrRender(_ctx, _push, _parent, _attrs) {\n          const _component_foo = _resolveComponent(\"foo\")\n\n          _push(_ssrRenderComponent(_component_foo, _attrs, {\n            default: _withCtx((_, _push, _parent, _scopeId) => {\n              if (_push) {\n                _push(\\`foo\\`)\n              } else {\n                return [\n                  _createTextVNode(\"foo\")\n                ]\n              }\n            }),\n            named: _withCtx((_, _push, _parent, _scopeId) => {\n              if (_push) {\n                _push(\\`bar\\`)\n              } else {\n                return [\n                  _createTextVNode(\"bar\")\n                ]\n              }\n            }),\n            _: 1 /* STABLE */\n          }, _parent))\n        }\"\n      `)\n    })\n\n    test('v-if slot', () => {\n      expect(\n        compile(`<foo>\n        <template v-slot:named v-if=\"ok\">foo</template>\n      </foo>`).code,\n      ).toMatchInlineSnapshot(`\n        \"const { resolveComponent: _resolveComponent, withCtx: _withCtx, createTextVNode: _createTextVNode, createSlots: _createSlots } = require(\"vue\")\n        const { ssrRenderComponent: _ssrRenderComponent } = require(\"vue/server-renderer\")\n\n        return function ssrRender(_ctx, _push, _parent, _attrs) {\n          const _component_foo = _resolveComponent(\"foo\")\n\n          _push(_ssrRenderComponent(_component_foo, _attrs, _createSlots({ _: 2 /* DYNAMIC */ }, [\n            (_ctx.ok)\n              ? {\n                  name: \"named\",\n                  fn: _withCtx((_, _push, _parent, _scopeId) => {\n                    if (_push) {\n                      _push(\\`foo\\`)\n                    } else {\n                      return [\n                        _createTextVNode(\"foo\")\n                      ]\n                    }\n                  }),\n                  key: \"0\"\n                }\n              : undefined\n          ]), _parent))\n        }\"\n      `)\n    })\n\n    test('v-for slot', () => {\n      const { code } = compile(`<foo>\n      <template v-for=\"(key, index) in names\" v-slot:[key]=\"{ msg }\">{{ msg + key + index + bar }}</template>\n    </foo>`)\n      expect(code).not.toMatch(`_ctx.msg`)\n      expect(code).not.toMatch(`_ctx.key`)\n      expect(code).not.toMatch(`_ctx.index`)\n      expect(code).toMatch(`_ctx.bar`)\n      expect(code).toMatchInlineSnapshot(`\n        \"const { resolveComponent: _resolveComponent, withCtx: _withCtx, toDisplayString: _toDisplayString, createTextVNode: _createTextVNode, renderList: _renderList, createSlots: _createSlots } = require(\"vue\")\n        const { ssrRenderComponent: _ssrRenderComponent, ssrInterpolate: _ssrInterpolate } = require(\"vue/server-renderer\")\n\n        return function ssrRender(_ctx, _push, _parent, _attrs) {\n          const _component_foo = _resolveComponent(\"foo\")\n\n          _push(_ssrRenderComponent(_component_foo, _attrs, _createSlots({ _: 2 /* DYNAMIC */ }, [\n            _renderList(_ctx.names, (key, index) => {\n              return {\n                name: key,\n                fn: _withCtx(({ msg }, _push, _parent, _scopeId) => {\n                  if (_push) {\n                    _push(\\`\\${_ssrInterpolate(msg + key + index + _ctx.bar)}\\`)\n                  } else {\n                    return [\n                      _createTextVNode(_toDisplayString(msg + key + index + _ctx.bar), 1 /* TEXT */)\n                    ]\n                  }\n                })\n              }\n            })\n          ]), _parent))\n        }\"\n      `)\n    })\n\n    test('nested transform scoping in vnode branch', () => {\n      expect(\n        compile(`<foo>\n        <template v-slot:foo=\"{ list }\">\n          <div v-if=\"ok\">\n            <span v-for=\"i in list\"></span>\n          </div>\n        </template>\n        <template v-slot:bar=\"{ ok }\">\n          <div v-if=\"ok\">\n            <span v-for=\"i in list\"></span>\n          </div>\n        </template>\n      </foo>`).code,\n      ).toMatchInlineSnapshot(`\n        \"const { resolveComponent: _resolveComponent, withCtx: _withCtx, renderList: _renderList, Fragment: _Fragment, openBlock: _openBlock, createBlock: _createBlock, createCommentVNode: _createCommentVNode } = require(\"vue\")\n        const { ssrRenderComponent: _ssrRenderComponent, ssrRenderList: _ssrRenderList } = require(\"vue/server-renderer\")\n\n        return function ssrRender(_ctx, _push, _parent, _attrs) {\n          const _component_foo = _resolveComponent(\"foo\")\n\n          _push(_ssrRenderComponent(_component_foo, _attrs, {\n            foo: _withCtx(({ list }, _push, _parent, _scopeId) => {\n              if (_push) {\n                if (_ctx.ok) {\n                  _push(\\`<div\\${_scopeId}><!--[-->\\`)\n                  _ssrRenderList(list, (i) => {\n                    _push(\\`<span\\${_scopeId}></span>\\`)\n                  })\n                  _push(\\`<!--]--></div>\\`)\n                } else {\n                  _push(\\`<!---->\\`)\n                }\n              } else {\n                return [\n                  (_ctx.ok)\n                    ? (_openBlock(), _createBlock(\"div\", { key: 0 }, [\n                        (_openBlock(true), _createBlock(_Fragment, null, _renderList(list, (i) => {\n                          return (_openBlock(), _createBlock(\"span\"))\n                        }), 256 /* UNKEYED_FRAGMENT */))\n                      ]))\n                    : _createCommentVNode(\"v-if\", true)\n                ]\n              }\n            }),\n            bar: _withCtx(({ ok }, _push, _parent, _scopeId) => {\n              if (_push) {\n                if (ok) {\n                  _push(\\`<div\\${_scopeId}><!--[-->\\`)\n                  _ssrRenderList(_ctx.list, (i) => {\n                    _push(\\`<span\\${_scopeId}></span>\\`)\n                  })\n                  _push(\\`<!--]--></div>\\`)\n                } else {\n                  _push(\\`<!---->\\`)\n                }\n              } else {\n                return [\n                  ok\n                    ? (_openBlock(), _createBlock(\"div\", { key: 0 }, [\n                        (_openBlock(true), _createBlock(_Fragment, null, _renderList(_ctx.list, (i) => {\n                          return (_openBlock(), _createBlock(\"span\"))\n                        }), 256 /* UNKEYED_FRAGMENT */))\n                      ]))\n                    : _createCommentVNode(\"v-if\", true)\n                ]\n              }\n            }),\n            _: 1 /* STABLE */\n          }, _parent))\n        }\"\n      `)\n    })\n\n    // #7644\n    test('slot content with v-once', () => {\n      const { code } = compile(`<foo><bar v-once /></foo>`)\n      expect(code).not.toMatch(`_cache`)\n      expect(compile(`<foo><bar v-once /></foo>`).code).toMatchInlineSnapshot(`\n        \"const { resolveComponent: _resolveComponent, withCtx: _withCtx, createVNode: _createVNode } = require(\"vue\")\n        const { ssrRenderComponent: _ssrRenderComponent } = require(\"vue/server-renderer\")\n\n        return function ssrRender(_ctx, _push, _parent, _attrs) {\n          const _component_foo = _resolveComponent(\"foo\")\n          const _component_bar = _resolveComponent(\"bar\")\n\n          _push(_ssrRenderComponent(_component_foo, _attrs, {\n            default: _withCtx((_, _push, _parent, _scopeId) => {\n              if (_push) {\n                _push(_ssrRenderComponent(_component_bar, null, null, _parent, _scopeId))\n              } else {\n                return [\n                  _createVNode(_component_bar)\n                ]\n              }\n            }),\n            _: 1 /* STABLE */\n          }, _parent))\n        }\"\n      `)\n    })\n\n    // #13724\n    test('slot content with v-memo', () => {\n      const { code } = compile(`<foo><bar v-memo=\"[]\" /></foo>`)\n      expect(code).not.toMatch(`_cache`)\n      expect(compile(`<foo><bar v-memo=\"[]\" /></foo>`).code)\n        .toMatchInlineSnapshot(`\n        \"const { resolveComponent: _resolveComponent, withCtx: _withCtx, createVNode: _createVNode } = require(\"vue\")\n        const { ssrRenderComponent: _ssrRenderComponent } = require(\"vue/server-renderer\")\n\n        return function ssrRender(_ctx, _push, _parent, _attrs) {\n          const _component_foo = _resolveComponent(\"foo\")\n          const _component_bar = _resolveComponent(\"bar\")\n\n          _push(_ssrRenderComponent(_component_foo, _attrs, {\n            default: _withCtx((_, _push, _parent, _scopeId) => {\n              if (_push) {\n                _push(_ssrRenderComponent(_component_bar, null, null, _parent, _scopeId))\n              } else {\n                return [\n                  _createVNode(_component_bar)\n                ]\n              }\n            }),\n            _: 1 /* STABLE */\n          }, _parent))\n        }\"\n      `)\n    })\n\n    describe('built-in fallthroughs', () => {\n      test('transition', () => {\n        expect(compile(`<transition><div/></transition>`).code)\n          .toMatchInlineSnapshot(`\n            \"const { ssrRenderAttrs: _ssrRenderAttrs } = require(\"vue/server-renderer\")\n\n            return function ssrRender(_ctx, _push, _parent, _attrs) {\n              _push(\\`<div\\${_ssrRenderAttrs(_attrs)}></div>\\`)\n            }\"\n          `)\n      })\n\n      test('keep-alive', () => {\n        expect(compile(`<keep-alive><foo/></keep-alive>`).code)\n          .toMatchInlineSnapshot(`\n            \"const { resolveComponent: _resolveComponent } = require(\"vue\")\n            const { ssrRenderComponent: _ssrRenderComponent } = require(\"vue/server-renderer\")\n\n            return function ssrRender(_ctx, _push, _parent, _attrs) {\n              const _component_foo = _resolveComponent(\"foo\")\n\n              _push(_ssrRenderComponent(_component_foo, _attrs, null, _parent))\n            }\"\n          `)\n      })\n\n      // #5352\n      test('should push marker string if is slot root', () => {\n        expect(\n          compile(`<foo><transition><div v-if=\"false\"/></transition></foo>`)\n            .code,\n        ).toMatchInlineSnapshot(`\n          \"const { resolveComponent: _resolveComponent, withCtx: _withCtx, openBlock: _openBlock, createBlock: _createBlock, createCommentVNode: _createCommentVNode, Transition: _Transition, createVNode: _createVNode } = require(\"vue\")\n          const { ssrRenderComponent: _ssrRenderComponent } = require(\"vue/server-renderer\")\n\n          return function ssrRender(_ctx, _push, _parent, _attrs) {\n            const _component_foo = _resolveComponent(\"foo\")\n\n            _push(_ssrRenderComponent(_component_foo, _attrs, {\n              default: _withCtx((_, _push, _parent, _scopeId) => {\n                if (_push) {\n                  _push(\\`\\`)\n                  if (false) {\n                    _push(\\`<div\\${_scopeId}></div>\\`)\n                  } else {\n                    _push(\\`<!---->\\`)\n                  }\n                } else {\n                  return [\n                    _createVNode(_Transition, null, {\n                      default: _withCtx(() => [\n                        false\n                          ? (_openBlock(), _createBlock(\"div\", { key: 0 }))\n                          : _createCommentVNode(\"v-if\", true)\n                      ]),\n                      _: 1 /* STABLE */\n                    })\n                  ]\n                }\n              }),\n              _: 1 /* STABLE */\n            }, _parent))\n          }\"\n        `)\n      })\n    })\n  })\n\n  describe('custom directive', () => {\n    test('basic', () => {\n      expect(compile(`<foo v-xxx:x.y=\"z\" />`).code).toMatchInlineSnapshot(`\n        \"const { resolveComponent: _resolveComponent, resolveDirective: _resolveDirective, mergeProps: _mergeProps } = require(\"vue\")\n        const { ssrGetDirectiveProps: _ssrGetDirectiveProps, ssrRenderComponent: _ssrRenderComponent } = require(\"vue/server-renderer\")\n\n        return function ssrRender(_ctx, _push, _parent, _attrs) {\n          const _component_foo = _resolveComponent(\"foo\")\n          const _directive_xxx = _resolveDirective(\"xxx\")\n\n          _push(_ssrRenderComponent(_component_foo, _mergeProps(_attrs, _ssrGetDirectiveProps(_ctx, _directive_xxx, _ctx.z, \"x\", { y: true })), null, _parent))\n        }\"\n      `)\n    })\n  })\n})\n"
  },
  {
    "path": "packages/compiler-ssr/__tests__/ssrElement.spec.ts",
    "content": "import { getCompiledString } from './utils'\nimport { compile } from '../src'\n\ndescribe('ssr: element', () => {\n  test('basic elements', () => {\n    expect(getCompiledString(`<div></div>`)).toMatchInlineSnapshot(\n      `\"\\`<div></div>\\`\"`,\n    )\n    expect(getCompiledString(`<div/>`)).toMatchInlineSnapshot(\n      `\"\\`<div></div>\\`\"`,\n    )\n  })\n\n  test('nested elements', () => {\n    expect(\n      getCompiledString(`<div><span></span><span></span></div>`),\n    ).toMatchInlineSnapshot(`\"\\`<div><span></span><span></span></div>\\`\"`)\n  })\n\n  test('void element', () => {\n    expect(getCompiledString(`<input>`)).toMatchInlineSnapshot(`\"\\`<input>\\`\"`)\n  })\n\n  describe('children override', () => {\n    test('v-html', () => {\n      expect(getCompiledString(`<div v-html=\"foo\"/>`)).toMatchInlineSnapshot(`\n        \"\\`<div>\\${\n            (_ctx.foo) ?? ''\n          }</div>\\`\"\n      `)\n    })\n\n    test('v-text', () => {\n      expect(getCompiledString(`<div v-text=\"foo\"/>`)).toMatchInlineSnapshot(`\n        \"\\`<div>\\${\n            _ssrInterpolate(_ctx.foo)\n          }</div>\\`\"\n      `)\n    })\n\n    test('<textarea> with dynamic value', () => {\n      expect(getCompiledString(`<textarea :value=\"foo\"/>`))\n        .toMatchInlineSnapshot(`\n        \"\\`<textarea>\\${\n            _ssrInterpolate(_ctx.foo)\n          }</textarea>\\`\"\n      `)\n    })\n\n    test('<textarea> with static value', () => {\n      expect(\n        getCompiledString(`<textarea value=\"fo&gt;o\"/>`),\n      ).toMatchInlineSnapshot(`\"\\`<textarea>fo&gt;o</textarea>\\`\"`)\n    })\n\n    test('<textarea> with dynamic v-bind', () => {\n      expect(compile(`<textarea v-bind=\"obj\">fallback</textarea>`).code)\n        .toMatchInlineSnapshot(`\n          \"const { mergeProps: _mergeProps } = require(\"vue\")\n          const { ssrRenderAttrs: _ssrRenderAttrs, ssrInterpolate: _ssrInterpolate } = require(\"vue/server-renderer\")\n\n          return function ssrRender(_ctx, _push, _parent, _attrs) {\n            let _temp0\n\n            _push(\\`<textarea\\${\n              _ssrRenderAttrs(_temp0 = _mergeProps(_ctx.obj, _attrs), \"textarea\")\n            }>\\${\n              _ssrInterpolate((\"value\" in _temp0) ? _temp0.value : \"fallback\")\n            }</textarea>\\`)\n          }\"\n        `)\n    })\n\n    test('multiple _ssrInterpolate at parent and child import dependency once', () => {\n      expect(\n        compile(`<div>{{ hello }}<textarea v-bind=\"a\"></textarea></div>`).code,\n      ).toMatchInlineSnapshot(`\n        \"const { ssrRenderAttrs: _ssrRenderAttrs, ssrInterpolate: _ssrInterpolate } = require(\"vue/server-renderer\")\n\n        return function ssrRender(_ctx, _push, _parent, _attrs) {\n          let _temp0\n\n          _push(\\`<div\\${\n            _ssrRenderAttrs(_attrs)\n          }>\\${\n            _ssrInterpolate(_ctx.hello)\n          }<textarea\\${\n            _ssrRenderAttrs(_temp0 = _ctx.a, \"textarea\")\n          }>\\${\n            _ssrInterpolate((\"value\" in _temp0) ? _temp0.value : \"\")\n          }</textarea></div>\\`)\n        }\"\n      `)\n    })\n\n    test('should pass tag to custom elements w/ dynamic v-bind', () => {\n      expect(\n        compile(`<my-foo v-bind=\"obj\"></my-foo>`, {\n          isCustomElement: () => true,\n        }).code,\n      ).toMatchInlineSnapshot(`\n        \"const { mergeProps: _mergeProps } = require(\"vue\")\n        const { ssrRenderAttrs: _ssrRenderAttrs } = require(\"vue/server-renderer\")\n\n        return function ssrRender(_ctx, _push, _parent, _attrs) {\n          _push(\\`<my-foo\\${_ssrRenderAttrs(_mergeProps(_ctx.obj, _attrs), \"my-foo\")}></my-foo>\\`)\n        }\"\n      `)\n    })\n  })\n\n  describe('attrs', () => {\n    test('static attrs', () => {\n      expect(\n        getCompiledString(`<div id=\"foo\" class=\"bar\"></div>`),\n      ).toMatchInlineSnapshot(`\"\\`<div id=\"foo\" class=\"bar\"></div>\\`\"`)\n    })\n\n    test('ignore static key/ref', () => {\n      expect(\n        getCompiledString(`<div key=\"1\" ref=\"el\"></div>`),\n      ).toMatchInlineSnapshot(`\"\\`<div></div>\\`\"`)\n    })\n\n    test('ignore v-bind key/ref', () => {\n      expect(\n        getCompiledString(`<div :key=\"1\" :ref=\"el\"></div>`),\n      ).toMatchInlineSnapshot(`\"\\`<div></div>\\`\"`)\n    })\n\n    test('v-bind:class', () => {\n      expect(getCompiledString(`<div id=\"foo\" :class=\"bar\"></div>`))\n        .toMatchInlineSnapshot(`\n          \"\\`<div id=\"foo\" class=\"\\${\n              _ssrRenderClass(_ctx.bar)\n            }\"></div>\\`\"\n        `)\n    })\n\n    test('static class + v-bind:class', () => {\n      expect(getCompiledString(`<div class=\"foo\" :class=\"bar\"></div>`))\n        .toMatchInlineSnapshot(`\n          \"\\`<div class=\"\\${\n              _ssrRenderClass([_ctx.bar, \"foo\"])\n            }\"></div>\\`\"\n        `)\n    })\n\n    test('v-bind:class + static class', () => {\n      expect(getCompiledString(`<div :class=\"bar\" class=\"foo\"></div>`))\n        .toMatchInlineSnapshot(`\n          \"\\`<div class=\"\\${\n              _ssrRenderClass([_ctx.bar, \"foo\"])\n            }\"></div>\\`\"\n        `)\n    })\n\n    test('v-bind:style', () => {\n      expect(getCompiledString(`<div id=\"foo\" :style=\"bar\"></div>`))\n        .toMatchInlineSnapshot(`\n          \"\\`<div id=\"foo\" style=\"\\${\n              _ssrRenderStyle(_ctx.bar)\n            }\"></div>\\`\"\n        `)\n    })\n\n    test('static style + v-bind:style', () => {\n      expect(getCompiledString(`<div style=\"color:red;\" :style=\"bar\"></div>`))\n        .toMatchInlineSnapshot(`\n          \"\\`<div style=\"\\${\n              _ssrRenderStyle([{\"color\":\"red\"}, _ctx.bar])\n            }\"></div>\\`\"\n        `)\n    })\n\n    test('v-bind:arg (boolean)', () => {\n      expect(getCompiledString(`<input type=\"checkbox\" :checked=\"checked\">`))\n        .toMatchInlineSnapshot(`\n          \"\\`<input type=\"checkbox\"\\${\n              (_ssrIncludeBooleanAttr(_ctx.checked)) ? \" checked\" : \"\"\n            }>\\`\"\n        `)\n    })\n\n    test('v-bind:arg (non-boolean)', () => {\n      expect(getCompiledString(`<div :id=\"id\" class=\"bar\"></div>`))\n        .toMatchInlineSnapshot(`\n          \"\\`<div\\${\n              _ssrRenderAttr(\"id\", _ctx.id)\n            } class=\"bar\"></div>\\`\"\n        `)\n    })\n\n    test('v-bind:[arg]', () => {\n      expect(getCompiledString(`<div v-bind:[key]=\"value\"></div>`))\n        .toMatchInlineSnapshot(`\n          \"\\`<div\\${\n              _ssrRenderAttrs({ [_ctx.key || \"\"]: _ctx.value })\n            }></div>\\`\"\n        `)\n\n      expect(getCompiledString(`<div class=\"foo\" v-bind:[key]=\"value\"></div>`))\n        .toMatchInlineSnapshot(`\n          \"\\`<div\\${\n              _ssrRenderAttrs({\n                class: \"foo\",\n                [_ctx.key || \"\"]: _ctx.value\n              })\n            }></div>\\`\"\n        `)\n\n      expect(getCompiledString(`<div :id=\"id\" v-bind:[key]=\"value\"></div>`))\n        .toMatchInlineSnapshot(`\n          \"\\`<div\\${\n              _ssrRenderAttrs({\n                id: _ctx.id,\n                [_ctx.key || \"\"]: _ctx.value\n              })\n            }></div>\\`\"\n        `)\n    })\n\n    test('v-bind=\"obj\"', () => {\n      expect(getCompiledString(`<div v-bind=\"obj\"></div>`))\n        .toMatchInlineSnapshot(`\n        \"\\`<div\\${\n            _ssrRenderAttrs(_ctx.obj)\n          }></div>\\`\"\n      `)\n\n      expect(getCompiledString(`<div class=\"foo\" v-bind=\"obj\"></div>`))\n        .toMatchInlineSnapshot(`\n          \"\\`<div\\${\n              _ssrRenderAttrs(_mergeProps({ class: \"foo\" }, _ctx.obj))\n            }></div>\\`\"\n        `)\n\n      expect(getCompiledString(`<div :id=\"id\" v-bind=\"obj\"></div>`))\n        .toMatchInlineSnapshot(`\n        \"\\`<div\\${\n            _ssrRenderAttrs(_mergeProps({ id: _ctx.id }, _ctx.obj))\n          }></div>\\`\"\n      `)\n\n      // dynamic key + v-bind=\"object\"\n      expect(getCompiledString(`<div :[key]=\"id\" v-bind=\"obj\"></div>`))\n        .toMatchInlineSnapshot(`\n          \"\\`<div\\${\n              _ssrRenderAttrs(_mergeProps({ [_ctx.key || \"\"]: _ctx.id }, _ctx.obj))\n            }></div>\\`\"\n        `)\n\n      // should merge class and :class\n      expect(getCompiledString(`<div class=\"a\" :class=\"b\" v-bind=\"obj\"></div>`))\n        .toMatchInlineSnapshot(`\n          \"\\`<div\\${\n              _ssrRenderAttrs(_mergeProps({\n                class: [\"a\", _ctx.b]\n              }, _ctx.obj))\n            }></div>\\`\"\n        `)\n\n      // should merge style and :style\n      expect(\n        getCompiledString(\n          `<div style=\"color:red;\" :style=\"b\" v-bind=\"obj\"></div>`,\n        ),\n      ).toMatchInlineSnapshot(`\n        \"\\`<div\\${\n            _ssrRenderAttrs(_mergeProps({\n              style: [{\"color\":\"red\"}, _ctx.b]\n            }, _ctx.obj))\n          }></div>\\`\"\n      `)\n    })\n\n    test('should ignore v-on', () => {\n      expect(\n        getCompiledString(`<div id=\"foo\" @click=\"bar\"/>`),\n      ).toMatchInlineSnapshot(`\"\\`<div id=\"foo\"></div>\\`\"`)\n      expect(\n        getCompiledString(`<div id=\"foo\" v-on=\"bar\"/>`),\n      ).toMatchInlineSnapshot(`\"\\`<div id=\"foo\"></div>\\`\"`)\n      expect(getCompiledString(`<div v-bind=\"foo\" v-on=\"bar\"/>`))\n        .toMatchInlineSnapshot(`\n        \"\\`<div\\${\n            _ssrRenderAttrs(_ctx.foo)\n          }></div>\\`\"\n      `)\n    })\n  })\n\n  describe('custom directives', () => {\n    // #8112 should respect textContent / innerHTML from directive getSSRProps\n    // if the element has no children\n    test('custom dir without children', () => {\n      expect(getCompiledString(`<div v-xxx:x.y=\"z\" />`)).toMatchInlineSnapshot(`\n        \"\\`<div\\${\n            _ssrRenderAttrs(_temp0 = _ssrGetDirectiveProps(_ctx, _directive_xxx, _ctx.z, \"x\", { y: true }))\n          }>\\${\n            (\"textContent\" in _temp0) ? _ssrInterpolate(_temp0.textContent) : _temp0.innerHTML ?? ''\n          }</div>\\`\"\n      `)\n    })\n\n    test('custom dir with children', () => {\n      expect(getCompiledString(`<div v-xxx:x.y=\"z\">hello</div>`))\n        .toMatchInlineSnapshot(`\n        \"\\`<div\\${\n            _ssrRenderAttrs(_ssrGetDirectiveProps(_ctx, _directive_xxx, _ctx.z, \"x\", { y: true }))\n          }>hello</div>\\`\"\n      `)\n    })\n\n    test('custom dir with normal attrs', () => {\n      expect(getCompiledString(`<div class=\"foo\" v-xxx />`))\n        .toMatchInlineSnapshot(`\n          \"\\`<div\\${\n              _ssrRenderAttrs(_temp0 = _mergeProps({ class: \"foo\" }, _ssrGetDirectiveProps(_ctx, _directive_xxx)))\n            }>\\${\n              (\"textContent\" in _temp0) ? _ssrInterpolate(_temp0.textContent) : _temp0.innerHTML ?? ''\n            }</div>\\`\"\n        `)\n    })\n\n    test('custom dir with v-bind', () => {\n      expect(getCompiledString(`<div :title=\"foo\" :class=\"bar\" v-xxx />`))\n        .toMatchInlineSnapshot(`\n          \"\\`<div\\${\n              _ssrRenderAttrs(_temp0 = _mergeProps({\n                title: _ctx.foo,\n                class: _ctx.bar\n              }, _ssrGetDirectiveProps(_ctx, _directive_xxx)))\n            }>\\${\n              (\"textContent\" in _temp0) ? _ssrInterpolate(_temp0.textContent) : _temp0.innerHTML ?? ''\n            }</div>\\`\"\n        `)\n    })\n\n    test('custom dir with v-text', () => {\n      expect(getCompiledString(`<div v-xxx v-text=\"foo\" />`))\n        .toMatchInlineSnapshot(`\n          \"\\`<div\\${\n              _ssrRenderAttrs(_ssrGetDirectiveProps(_ctx, _directive_xxx))\n            }>\\${\n              _ssrInterpolate(_ctx.foo)\n            }</div>\\`\"\n        `)\n    })\n\n    test('custom dir with v-text and normal attrs', () => {\n      expect(getCompiledString(`<div class=\"test\" v-xxx v-text=\"foo\" />`))\n        .toMatchInlineSnapshot(`\n          \"\\`<div\\${\n              _ssrRenderAttrs(_mergeProps({ class: \"test\" }, _ssrGetDirectiveProps(_ctx, _directive_xxx)))\n            }>\\${\n              _ssrInterpolate(_ctx.foo)\n            }</div>\\`\"\n        `)\n    })\n\n    test('mulptiple custom dirs with v-text', () => {\n      expect(getCompiledString(`<div v-xxx v-yyy v-text=\"foo\" />`))\n        .toMatchInlineSnapshot(`\n          \"\\`<div\\${\n              _ssrRenderAttrs(_mergeProps(_ssrGetDirectiveProps(_ctx, _directive_xxx), _ssrGetDirectiveProps(_ctx, _directive_yyy)))\n            }>\\${\n              _ssrInterpolate(_ctx.foo)\n            }</div>\\`\"\n        `)\n    })\n\n    test('custom dir with object v-bind', () => {\n      expect(getCompiledString(`<div v-bind=\"x\" v-xxx />`))\n        .toMatchInlineSnapshot(`\n          \"\\`<div\\${\n              _ssrRenderAttrs(_temp0 = _mergeProps(_ctx.x, _ssrGetDirectiveProps(_ctx, _directive_xxx)))\n            }>\\${\n              (\"textContent\" in _temp0) ? _ssrInterpolate(_temp0.textContent) : _temp0.innerHTML ?? ''\n            }</div>\\`\"\n        `)\n    })\n\n    test('custom dir with object v-bind + normal bindings', () => {\n      expect(\n        getCompiledString(`<div v-bind=\"x\" class=\"foo\" v-xxx title=\"bar\" />`),\n      ).toMatchInlineSnapshot(`\n        \"\\`<div\\${\n            _ssrRenderAttrs(_temp0 = _mergeProps(_ctx.x, {\n              class: \"foo\",\n              title: \"bar\"\n            }, _ssrGetDirectiveProps(_ctx, _directive_xxx)))\n          }>\\${\n            (\"textContent\" in _temp0) ? _ssrInterpolate(_temp0.textContent) : _temp0.innerHTML ?? ''\n          }</div>\\`\"\n      `)\n    })\n  })\n})\n"
  },
  {
    "path": "packages/compiler-ssr/__tests__/ssrFallthroughAttrs.spec.ts",
    "content": "import { compile } from '../src'\n\ndescribe('ssr: attrs fallthrough', () => {\n  test('basic', () => {\n    expect(compile(`<div/>`).code).toMatchInlineSnapshot(`\n      \"const { ssrRenderAttrs: _ssrRenderAttrs } = require(\"vue/server-renderer\")\n\n      return function ssrRender(_ctx, _push, _parent, _attrs) {\n        _push(\\`<div\\${_ssrRenderAttrs(_attrs)}></div>\\`)\n      }\"\n    `)\n  })\n\n  test('with comments', () => {\n    expect(compile(`<!--!--><div/>`).code).toMatchInlineSnapshot(`\n      \"const { ssrRenderAttrs: _ssrRenderAttrs } = require(\"vue/server-renderer\")\n\n      return function ssrRender(_ctx, _push, _parent, _attrs) {\n        _push(\\`<!--[--><!--!--><div\\${_ssrRenderAttrs(_attrs)}></div><!--]-->\\`)\n      }\"\n    `)\n  })\n\n  // #5140\n  test('should not inject to non-single-root if branches', () => {\n    expect(compile(`<div v-if=\"true\"/><div/>`).code).toMatchInlineSnapshot(`\n      \"\n      return function ssrRender(_ctx, _push, _parent, _attrs) {\n        _push(\\`<!--[-->\\`)\n        if (true) {\n          _push(\\`<div></div>\\`)\n        } else {\n          _push(\\`<!---->\\`)\n        }\n        _push(\\`<div></div><!--]-->\\`)\n      }\"\n    `)\n  })\n\n  test('fallthrough component content (root with comments)', () => {\n    expect(compile(`<!--root--><transition><div/></transition>`).code)\n      .toMatchInlineSnapshot(`\n        \"const { ssrRenderAttrs: _ssrRenderAttrs } = require(\"vue/server-renderer\")\n\n        return function ssrRender(_ctx, _push, _parent, _attrs) {\n          _push(\\`<!--[--><!--root--><div\\${_ssrRenderAttrs(_attrs)}></div><!--]-->\\`)\n        }\"\n      `)\n  })\n\n  //#8072\n  test(`fallthrough component content (with whitespace: 'preserve')`, () => {\n    expect(\n      compile(\n        `\n      <a v-if=\"to\">Foo</a>\n      <a v-else>Bar</a>\n    `,\n        {\n          whitespace: 'preserve',\n        },\n      ).code,\n    ).toMatchInlineSnapshot(`\n        \"const { ssrRenderAttrs: _ssrRenderAttrs } = require(\"vue/server-renderer\")\n\n        return function ssrRender(_ctx, _push, _parent, _attrs) {\n          if (_ctx.to) {\n            _push(\\`<a\\${_ssrRenderAttrs(_attrs)}>Foo</a>\\`)\n          } else {\n            _push(\\`<a\\${_ssrRenderAttrs(_attrs)}>Bar</a>\\`)\n          }\n        }\"\n      `)\n  })\n\n  test('should not inject to fallthrough component content if not root', () => {\n    expect(compile(`<div/><transition><div/></transition>`).code)\n      .toMatchInlineSnapshot(`\n              \"\n              return function ssrRender(_ctx, _push, _parent, _attrs) {\n                _push(\\`<!--[--><div></div><div></div><!--]-->\\`)\n              }\"\n          `)\n  })\n})\n"
  },
  {
    "path": "packages/compiler-ssr/__tests__/ssrInjectCssVars.spec.ts",
    "content": "import { BindingTypes } from '@vue/compiler-dom'\nimport { compile } from '../src'\n\ndescribe('ssr: inject <style vars>', () => {\n  test('basic', () => {\n    expect(\n      compile(`<div/>`, {\n        ssrCssVars: `{ color }`,\n      }).code,\n    ).toMatchInlineSnapshot(`\n      \"const { mergeProps: _mergeProps } = require(\"vue\")\n      const { ssrRenderAttrs: _ssrRenderAttrs } = require(\"vue/server-renderer\")\n\n      return function ssrRender(_ctx, _push, _parent, _attrs) {\n        const _cssVars = { style: { color: _ctx.color }}\n        _push(\\`<div\\${_ssrRenderAttrs(_mergeProps(_attrs, _cssVars))}></div>\\`)\n      }\"\n    `)\n  })\n\n  test('fragment', () => {\n    expect(\n      compile(`<div/><div/>`, {\n        ssrCssVars: `{ color }`,\n      }).code,\n    ).toMatchInlineSnapshot(`\n      \"const { ssrRenderAttrs: _ssrRenderAttrs } = require(\"vue/server-renderer\")\n\n      return function ssrRender(_ctx, _push, _parent, _attrs) {\n        const _cssVars = { style: { color: _ctx.color }}\n        _push(\\`<!--[--><div\\${\n          _ssrRenderAttrs(_cssVars)\n        }></div><div\\${\n          _ssrRenderAttrs(_cssVars)\n        }></div><!--]-->\\`)\n      }\"\n    `)\n  })\n\n  test('passing on to components', () => {\n    expect(\n      compile(`<div/><foo/>`, {\n        ssrCssVars: `{ color }`,\n      }).code,\n    ).toMatchInlineSnapshot(`\n      \"const { resolveComponent: _resolveComponent } = require(\"vue\")\n      const { ssrRenderAttrs: _ssrRenderAttrs, ssrRenderComponent: _ssrRenderComponent } = require(\"vue/server-renderer\")\n\n      return function ssrRender(_ctx, _push, _parent, _attrs) {\n        const _component_foo = _resolveComponent(\"foo\")\n\n        const _cssVars = { style: { color: _ctx.color }}\n        _push(\\`<!--[--><div\\${_ssrRenderAttrs(_cssVars)}></div>\\`)\n        _push(_ssrRenderComponent(_component_foo, _cssVars, null, _parent))\n        _push(\\`<!--]-->\\`)\n      }\"\n    `)\n  })\n\n  test('v-if branches', () => {\n    expect(\n      compile(`<div v-if=\"ok\"/><template v-else><div/><div/></template>`, {\n        ssrCssVars: `{ color }`,\n      }).code,\n    ).toMatchInlineSnapshot(`\n      \"const { mergeProps: _mergeProps } = require(\"vue\")\n      const { ssrRenderAttrs: _ssrRenderAttrs } = require(\"vue/server-renderer\")\n\n      return function ssrRender(_ctx, _push, _parent, _attrs) {\n        const _cssVars = { style: { color: _ctx.color }}\n        if (_ctx.ok) {\n          _push(\\`<div\\${_ssrRenderAttrs(_mergeProps(_attrs, _cssVars))}></div>\\`)\n        } else {\n          _push(\\`<!--[--><div\\${\n            _ssrRenderAttrs(_cssVars)\n          }></div><div\\${\n            _ssrRenderAttrs(_cssVars)\n          }></div><!--]-->\\`)\n        }\n      }\"\n    `)\n  })\n\n  test('w/ suspense', () => {\n    expect(\n      compile(\n        `<Suspense>\n          <div>ok</div>\n          <template #fallback>\n            <div>fallback</div>\n          </template>\n        </Suspense>`,\n        {\n          ssrCssVars: `{ color }`,\n        },\n      ).code,\n    ).toMatchInlineSnapshot(`\n      \"const { withCtx: _withCtx } = require(\"vue\")\n      const { ssrRenderAttrs: _ssrRenderAttrs, ssrRenderSuspense: _ssrRenderSuspense } = require(\"vue/server-renderer\")\n\n      return function ssrRender(_ctx, _push, _parent, _attrs) {\n        const _cssVars = { style: { color: _ctx.color }}\n        _ssrRenderSuspense(_push, {\n          fallback: () => {\n            _push(\\`<div\\${_ssrRenderAttrs(_cssVars)}>fallback</div>\\`)\n          },\n          default: () => {\n            _push(\\`<div\\${_ssrRenderAttrs(_cssVars)}>ok</div>\\`)\n          },\n          _: 1 /* STABLE */\n        })\n      }\"\n    `)\n  })\n\n  test('inject helpers', () => {\n    const result = compile(`<div/>`, {\n      inline: true,\n      bindingMetadata: { dynamic: BindingTypes.SETUP_MAYBE_REF },\n      ssrCssVars: '{ \"--hash\": (dynamic) }',\n    })\n\n    expect(result.code).toMatchInlineSnapshot(`\n      \"(_ctx, _push, _parent, _attrs) => {\n        const _cssVars = { style: { \"--hash\": (_unref(dynamic)) }}\n        _push(\\`<div\\${_ssrRenderAttrs(_mergeProps(_attrs, _cssVars))}></div>\\`)\n      }\"\n    `)\n    expect(result.ast.helpers).toMatchInlineSnapshot(`\n      Set {\n        Symbol(mergeProps),\n        Symbol(unref),\n      }\n    `)\n  })\n})\n"
  },
  {
    "path": "packages/compiler-ssr/__tests__/ssrPortal.spec.ts",
    "content": "import { compile } from '../src'\n\ndescribe('ssr compile: teleport', () => {\n  test('should work', () => {\n    expect(compile(`<teleport :to=\"target\"><div/></teleport>`).code)\n      .toMatchInlineSnapshot(`\n        \"const { ssrRenderTeleport: _ssrRenderTeleport } = require(\"vue/server-renderer\")\n\n        return function ssrRender(_ctx, _push, _parent, _attrs) {\n          _ssrRenderTeleport(_push, (_push) => {\n            _push(\\`<div></div>\\`)\n          }, _ctx.target, false, _parent)\n        }\"\n      `)\n  })\n\n  test('disabled prop handling', () => {\n    expect(compile(`<teleport :to=\"target\" disabled><div/></teleport>`).code)\n      .toMatchInlineSnapshot(`\n        \"const { ssrRenderTeleport: _ssrRenderTeleport } = require(\"vue/server-renderer\")\n\n        return function ssrRender(_ctx, _push, _parent, _attrs) {\n          _ssrRenderTeleport(_push, (_push) => {\n            _push(\\`<div></div>\\`)\n          }, _ctx.target, true, _parent)\n        }\"\n      `)\n\n    expect(\n      compile(`<teleport :to=\"target\" :disabled=\"foo\"><div/></teleport>`).code,\n    ).toMatchInlineSnapshot(`\n      \"const { ssrRenderTeleport: _ssrRenderTeleport } = require(\"vue/server-renderer\")\n\n      return function ssrRender(_ctx, _push, _parent, _attrs) {\n        _ssrRenderTeleport(_push, (_push) => {\n          _push(\\`<div></div>\\`)\n        }, _ctx.target, _ctx.foo, _parent)\n      }\"\n    `)\n  })\n})\n"
  },
  {
    "path": "packages/compiler-ssr/__tests__/ssrScopeId.spec.ts",
    "content": "import { compile } from '../src'\n\nconst scopeId = 'data-v-xxxxxxx'\n\ndescribe('ssr: scopeId', () => {\n  test('basic', () => {\n    expect(\n      compile(`<div><span>hello</span></div>`, {\n        scopeId,\n        mode: 'module',\n      }).code,\n    ).toMatchInlineSnapshot(`\n      \"import { ssrRenderAttrs as _ssrRenderAttrs } from \"vue/server-renderer\"\n\n      export function ssrRender(_ctx, _push, _parent, _attrs) {\n        _push(\\`<div\\${_ssrRenderAttrs(_attrs)} data-v-xxxxxxx><span data-v-xxxxxxx>hello</span></div>\\`)\n      }\"\n    `)\n  })\n\n  test('inside slots (only text)', () => {\n    // should have no branching inside slot\n    expect(\n      compile(`<foo>foo</foo>`, {\n        scopeId,\n        mode: 'module',\n      }).code,\n    ).toMatchInlineSnapshot(`\n      \"import { resolveComponent as _resolveComponent, withCtx as _withCtx, createTextVNode as _createTextVNode } from \"vue\"\n      import { ssrRenderComponent as _ssrRenderComponent } from \"vue/server-renderer\"\n\n      export function ssrRender(_ctx, _push, _parent, _attrs) {\n        const _component_foo = _resolveComponent(\"foo\")\n\n        _push(_ssrRenderComponent(_component_foo, _attrs, {\n          default: _withCtx((_, _push, _parent, _scopeId) => {\n            if (_push) {\n              _push(\\`foo\\`)\n            } else {\n              return [\n                _createTextVNode(\"foo\")\n              ]\n            }\n          }),\n          _: 1 /* STABLE */\n        }, _parent))\n      }\"\n    `)\n  })\n\n  test('inside slots (with elements)', () => {\n    expect(\n      compile(`<foo><span>hello</span></foo>`, {\n        scopeId,\n        mode: 'module',\n      }).code,\n    ).toMatchInlineSnapshot(`\n      \"import { resolveComponent as _resolveComponent, withCtx as _withCtx, createVNode as _createVNode } from \"vue\"\n      import { ssrRenderComponent as _ssrRenderComponent } from \"vue/server-renderer\"\n\n      export function ssrRender(_ctx, _push, _parent, _attrs) {\n        const _component_foo = _resolveComponent(\"foo\")\n\n        _push(_ssrRenderComponent(_component_foo, _attrs, {\n          default: _withCtx((_, _push, _parent, _scopeId) => {\n            if (_push) {\n              _push(\\`<span data-v-xxxxxxx\\${_scopeId}>hello</span>\\`)\n            } else {\n              return [\n                _createVNode(\"span\", null, \"hello\")\n              ]\n            }\n          }),\n          _: 1 /* STABLE */\n        }, _parent))\n      }\"\n    `)\n  })\n\n  test('nested slots', () => {\n    expect(\n      compile(`<foo><span>hello</span><bar><span/></bar></foo>`, {\n        scopeId,\n        mode: 'module',\n      }).code,\n    ).toMatchInlineSnapshot(`\n      \"import { resolveComponent as _resolveComponent, withCtx as _withCtx, createVNode as _createVNode } from \"vue\"\n      import { ssrRenderComponent as _ssrRenderComponent } from \"vue/server-renderer\"\n\n      export function ssrRender(_ctx, _push, _parent, _attrs) {\n        const _component_foo = _resolveComponent(\"foo\")\n        const _component_bar = _resolveComponent(\"bar\")\n\n        _push(_ssrRenderComponent(_component_foo, _attrs, {\n          default: _withCtx((_, _push, _parent, _scopeId) => {\n            if (_push) {\n              _push(\\`<span data-v-xxxxxxx\\${_scopeId}>hello</span>\\`)\n              _push(_ssrRenderComponent(_component_bar, null, {\n                default: _withCtx((_, _push, _parent, _scopeId) => {\n                  if (_push) {\n                    _push(\\`<span data-v-xxxxxxx\\${_scopeId}></span>\\`)\n                  } else {\n                    return [\n                      _createVNode(\"span\")\n                    ]\n                  }\n                }),\n                _: 1 /* STABLE */\n              }, _parent, _scopeId))\n            } else {\n              return [\n                _createVNode(\"span\", null, \"hello\"),\n                _createVNode(_component_bar, null, {\n                  default: _withCtx(() => [\n                    _createVNode(\"span\")\n                  ]),\n                  _: 1 /* STABLE */\n                })\n              ]\n            }\n          }),\n          _: 1 /* STABLE */\n        }, _parent))\n      }\"\n    `)\n  })\n\n  // #7554\n  test('scopeId is correctly transform to scope attribute of transition-group ', () => {\n    expect(\n      compile(\n        `<transition-group tag=\"div\" class=\"red\"><span>hello</span></transition-group>`,\n        {\n          scopeId,\n          mode: 'module',\n        },\n      ).code,\n    ).toMatchInlineSnapshot(`\n      \"import { mergeProps as _mergeProps } from \"vue\"\n      import { ssrRenderAttrs as _ssrRenderAttrs } from \"vue/server-renderer\"\n\n      export function ssrRender(_ctx, _push, _parent, _attrs) {\n        _push(\\`<div\\${_ssrRenderAttrs(_mergeProps({ class: \"red\" }, _attrs))} data-v-xxxxxxx><span data-v-xxxxxxx>hello</span></div>\\`)\n      }\"\n    `)\n\n    // with dynamic tag\n    expect(\n      compile(\n        `<transition-group :tag=\"someTag\" class=\"red\"><span>hello</span></transition-group>`,\n        {\n          scopeId,\n          mode: 'module',\n        },\n      ).code,\n    ).toMatchInlineSnapshot(`\n      \"import { mergeProps as _mergeProps } from \"vue\"\n      import { ssrRenderAttrs as _ssrRenderAttrs } from \"vue/server-renderer\"\n\n      export function ssrRender(_ctx, _push, _parent, _attrs) {\n        _push(\\`<\\${\n          _ctx.someTag\n        }\\${\n          _ssrRenderAttrs(_mergeProps({ class: \"red\" }, _attrs))\n        } data-v-xxxxxxx><span data-v-xxxxxxx>hello</span></\\${\n          _ctx.someTag\n        }>\\`)\n      }\"\n    `)\n  })\n})\n"
  },
  {
    "path": "packages/compiler-ssr/__tests__/ssrSlotOutlet.spec.ts",
    "content": "import { compile } from '../src'\nimport { SSR_RENDER_SLOT_INNER, ssrHelpers } from '../src/runtimeHelpers'\n\ndescribe('ssr: <slot>', () => {\n  test('basic', () => {\n    expect(compile(`<slot/>`).code).toMatchInlineSnapshot(`\n      \"const { ssrRenderSlot: _ssrRenderSlot } = require(\"vue/server-renderer\")\n\n      return function ssrRender(_ctx, _push, _parent, _attrs) {\n        _ssrRenderSlot(_ctx.$slots, \"default\", {}, null, _push, _parent)\n      }\"\n    `)\n  })\n\n  test('with name', () => {\n    expect(compile(`<slot name=\"foo\" />`).code).toMatchInlineSnapshot(`\n      \"const { ssrRenderSlot: _ssrRenderSlot } = require(\"vue/server-renderer\")\n\n      return function ssrRender(_ctx, _push, _parent, _attrs) {\n        _ssrRenderSlot(_ctx.$slots, \"foo\", {}, null, _push, _parent)\n      }\"\n    `)\n  })\n\n  test('with dynamic name', () => {\n    expect(compile(`<slot :name=\"bar.baz\" />`).code).toMatchInlineSnapshot(`\n      \"const { ssrRenderSlot: _ssrRenderSlot } = require(\"vue/server-renderer\")\n\n      return function ssrRender(_ctx, _push, _parent, _attrs) {\n        _ssrRenderSlot(_ctx.$slots, _ctx.bar.baz, {}, null, _push, _parent)\n      }\"\n    `)\n  })\n\n  test('with props', () => {\n    expect(compile(`<slot name=\"foo\" :p=\"1\" bar=\"2\" />`).code)\n      .toMatchInlineSnapshot(`\n        \"const { ssrRenderSlot: _ssrRenderSlot } = require(\"vue/server-renderer\")\n\n        return function ssrRender(_ctx, _push, _parent, _attrs) {\n          _ssrRenderSlot(_ctx.$slots, \"foo\", {\n            p: 1,\n            bar: \"2\"\n          }, null, _push, _parent)\n        }\"\n      `)\n  })\n\n  test('with fallback', () => {\n    expect(compile(`<slot>some {{ fallback }} content</slot>`).code)\n      .toMatchInlineSnapshot(`\n        \"const { ssrRenderSlot: _ssrRenderSlot, ssrInterpolate: _ssrInterpolate } = require(\"vue/server-renderer\")\n\n        return function ssrRender(_ctx, _push, _parent, _attrs) {\n          _ssrRenderSlot(_ctx.$slots, \"default\", {}, () => {\n            _push(\\`some \\${_ssrInterpolate(_ctx.fallback)} content\\`)\n          }, _push, _parent)\n        }\"\n      `)\n  })\n\n  test('with scopeId', async () => {\n    expect(\n      compile(`<slot/>`, {\n        scopeId: 'hello',\n      }).code,\n    ).toMatchInlineSnapshot(`\n      \"const { ssrRenderSlot: _ssrRenderSlot } = require(\"vue/server-renderer\")\n\n      return function ssrRender(_ctx, _push, _parent, _attrs) {\n        _ssrRenderSlot(_ctx.$slots, \"default\", {}, null, _push, _parent, \"hello-s\")\n      }\"\n    `)\n  })\n\n  test('with scopeId + slotted:false', async () => {\n    expect(\n      compile(`<slot/>`, {\n        scopeId: 'hello',\n        slotted: false,\n      }).code,\n    ).toMatchInlineSnapshot(`\n      \"const { ssrRenderSlot: _ssrRenderSlot } = require(\"vue/server-renderer\")\n\n      return function ssrRender(_ctx, _push, _parent, _attrs) {\n        _ssrRenderSlot(_ctx.$slots, \"default\", {}, null, _push, _parent)\n      }\"\n    `)\n  })\n\n  test('with forwarded scopeId', async () => {\n    expect(\n      compile(`<Comp><slot/></Comp>`, {\n        scopeId: 'hello',\n      }).code,\n    ).toMatchInlineSnapshot(`\n      \"const { resolveComponent: _resolveComponent, withCtx: _withCtx, renderSlot: _renderSlot } = require(\"vue\")\n      const { ssrRenderSlot: _ssrRenderSlot, ssrRenderComponent: _ssrRenderComponent } = require(\"vue/server-renderer\")\n\n      return function ssrRender(_ctx, _push, _parent, _attrs) {\n        const _component_Comp = _resolveComponent(\"Comp\")\n\n        _push(_ssrRenderComponent(_component_Comp, _attrs, {\n          default: _withCtx((_, _push, _parent, _scopeId) => {\n            if (_push) {\n              _ssrRenderSlot(_ctx.$slots, \"default\", {}, null, _push, _parent, \"hello-s\" + _scopeId)\n            } else {\n              return [\n                _renderSlot(_ctx.$slots, \"default\")\n              ]\n            }\n          }),\n          _: 3 /* FORWARDED */\n        }, _parent))\n      }\"\n    `)\n  })\n\n  test('inside transition', () => {\n    const { code } = compile(`<transition><slot/></transition>`)\n    expect(code).toMatch(ssrHelpers[SSR_RENDER_SLOT_INNER])\n    expect(code).toMatchInlineSnapshot(`\n      \"const { ssrRenderSlotInner: _ssrRenderSlotInner } = require(\"vue/server-renderer\")\n\n      return function ssrRender(_ctx, _push, _parent, _attrs) {\n        _ssrRenderSlotInner(_ctx.$slots, \"default\", {}, null, _push, _parent, null, true)\n      }\"\n    `)\n  })\n\n  test('inside transition-group', () => {\n    const { code } = compile(\n      `<TransitionGroup tag=\"div\"><slot/></TransitionGroup>`,\n    )\n    expect(code).toMatch(ssrHelpers[SSR_RENDER_SLOT_INNER])\n    expect(code).toMatchInlineSnapshot(`\n      \"const { ssrRenderSlotInner: _ssrRenderSlotInner, ssrRenderAttrs: _ssrRenderAttrs } = require(\"vue/server-renderer\")\n\n      return function ssrRender(_ctx, _push, _parent, _attrs) {\n        _push(\\`<div\\${_ssrRenderAttrs(_attrs)}>\\`)\n        _ssrRenderSlotInner(_ctx.$slots, \"default\", {}, null, _push, _parent, null, true)\n        _push(\\`</div>\\`)\n      }\"\n    `)\n  })\n\n  test('with v-if inside transition', () => {\n    const { code } = compile(`<transition><slot v-if=\"true\"/></transition>`)\n    expect(code).toMatch(ssrHelpers[SSR_RENDER_SLOT_INNER])\n    expect(code).toMatchInlineSnapshot(`\n      \"const { ssrRenderSlotInner: _ssrRenderSlotInner } = require(\"vue/server-renderer\")\n\n      return function ssrRender(_ctx, _push, _parent, _attrs) {\n        if (true) {\n          _ssrRenderSlotInner(_ctx.$slots, \"default\", {}, null, _push, _parent, null, true)\n        } else {\n          _push(\\`<!---->\\`)\n        }\n      }\"\n    `)\n  })\n})\n"
  },
  {
    "path": "packages/compiler-ssr/__tests__/ssrSuspense.spec.ts",
    "content": "import { compile } from '../src'\n\ndescribe('ssr compile: suspense', () => {\n  test('implicit default', () => {\n    expect(compile(`<suspense><foo/></suspense>`).code).toMatchInlineSnapshot(`\n      \"const { resolveComponent: _resolveComponent, withCtx: _withCtx } = require(\"vue\")\n      const { ssrRenderComponent: _ssrRenderComponent, ssrRenderSuspense: _ssrRenderSuspense } = require(\"vue/server-renderer\")\n\n      return function ssrRender(_ctx, _push, _parent, _attrs) {\n        const _component_foo = _resolveComponent(\"foo\")\n\n        _ssrRenderSuspense(_push, {\n          default: () => {\n            _push(_ssrRenderComponent(_component_foo, null, null, _parent))\n          },\n          _: 1 /* STABLE */\n        })\n      }\"\n    `)\n  })\n\n  test('explicit slots', () => {\n    expect(\n      compile(`<suspense>\n      <template #default>\n        <foo/>\n      </template>\n      <template #fallback>\n        loading...\n      </template>\n    </suspense>`).code,\n    ).toMatchInlineSnapshot(`\n      \"const { resolveComponent: _resolveComponent, withCtx: _withCtx } = require(\"vue\")\n      const { ssrRenderComponent: _ssrRenderComponent, ssrRenderSuspense: _ssrRenderSuspense } = require(\"vue/server-renderer\")\n\n      return function ssrRender(_ctx, _push, _parent, _attrs) {\n        const _component_foo = _resolveComponent(\"foo\")\n\n        _ssrRenderSuspense(_push, {\n          default: () => {\n            _push(_ssrRenderComponent(_component_foo, null, null, _parent))\n          },\n          fallback: () => {\n            _push(\\` loading... \\`)\n          },\n          _: 1 /* STABLE */\n        })\n      }\"\n    `)\n  })\n})\n"
  },
  {
    "path": "packages/compiler-ssr/__tests__/ssrText.spec.ts",
    "content": "import { compile } from '../src'\nimport { getCompiledString } from './utils'\n\ndescribe('ssr: text', () => {\n  test('static text', () => {\n    expect(getCompiledString(`foo`)).toMatchInlineSnapshot(`\"\\`foo\\`\"`)\n  })\n\n  test('static text with template string special chars', () => {\n    expect(getCompiledString(`\\`\\${foo}\\``)).toMatchInlineSnapshot(\n      `\"\\`\\\\\\`\\\\\\${foo}\\\\\\`\\`\"`,\n    )\n  })\n\n  test('static text with char escape', () => {\n    // the desired generated code should be `\\\\\\$foo`\n    // snapshot -> inline snapshot goes through two escapes\n    // so that makes a total of 3 * 2 * 2 = 12 back slashes\n    expect(getCompiledString(`\\\\$foo`)).toMatchInlineSnapshot(\n      `\"\\`\\\\\\\\\\\\$foo\\`\"`,\n    )\n  })\n\n  test('comments', () => {\n    expect(getCompiledString(`<!--bar-->`)).toMatchInlineSnapshot(\n      `\"\\`<!--bar-->\\`\"`,\n    )\n  })\n\n  test('static text escape', () => {\n    expect(getCompiledString(`&lt;foo&gt;`)).toMatchInlineSnapshot(\n      `\"\\`&lt;foo&gt;\\`\"`,\n    )\n  })\n\n  test('nested elements with static text', () => {\n    expect(\n      getCompiledString(`<div><span>hello</span><span>bye</span></div>`),\n    ).toMatchInlineSnapshot(\n      `\"\\`<div><span>hello</span><span>bye</span></div>\\`\"`,\n    )\n  })\n\n  test('interpolation', () => {\n    expect(compile(`foo {{ bar }} baz`).code).toMatchInlineSnapshot(`\n      \"const { ssrInterpolate: _ssrInterpolate } = require(\"vue/server-renderer\")\n\n      return function ssrRender(_ctx, _push, _parent, _attrs) {\n        _push(\\`foo \\${_ssrInterpolate(_ctx.bar)} baz\\`)\n      }\"\n    `)\n  })\n\n  test('nested elements with interpolation', () => {\n    expect(\n      compile(`<div><span>{{ foo }} bar</span><span>baz {{ qux }}</span></div>`)\n        .code,\n    ).toMatchInlineSnapshot(`\n      \"const { ssrRenderAttrs: _ssrRenderAttrs, ssrInterpolate: _ssrInterpolate } = require(\"vue/server-renderer\")\n\n      return function ssrRender(_ctx, _push, _parent, _attrs) {\n        _push(\\`<div\\${\n          _ssrRenderAttrs(_attrs)\n        }><span>\\${\n          _ssrInterpolate(_ctx.foo)\n        } bar</span><span>baz \\${\n          _ssrInterpolate(_ctx.qux)\n        }</span></div>\\`)\n      }\"\n    `)\n  })\n})\n"
  },
  {
    "path": "packages/compiler-ssr/__tests__/ssrTransition.spec.ts",
    "content": "import { compile } from '../src'\n\ndescribe('transition', () => {\n  test('basic', () => {\n    expect(compile(`<transition><div>foo</div></transition>`).code)\n      .toMatchInlineSnapshot(`\n        \"const { ssrRenderAttrs: _ssrRenderAttrs } = require(\"vue/server-renderer\")\n\n        return function ssrRender(_ctx, _push, _parent, _attrs) {\n          _push(\\`<div\\${_ssrRenderAttrs(_attrs)}>foo</div>\\`)\n        }\"\n      `)\n  })\n\n  test('with appear', () => {\n    expect(compile(`<transition appear><div>foo</div></transition>`).code)\n      .toMatchInlineSnapshot(`\n        \"const { ssrRenderAttrs: _ssrRenderAttrs } = require(\"vue/server-renderer\")\n\n        return function ssrRender(_ctx, _push, _parent, _attrs) {\n          _push(\\`<template><div\\${_ssrRenderAttrs(_attrs)}>foo</div></template>\\`)\n        }\"\n      `)\n  })\n})\n"
  },
  {
    "path": "packages/compiler-ssr/__tests__/ssrTransitionGroup.spec.ts",
    "content": "import { compile } from '../src'\n\n// transition-group should flatten and concat its children fragments into\n// a single one\ndescribe('transition-group', () => {\n  test('basic', () => {\n    expect(\n      compile(`<transition-group><div v-for=\"i in list\"/></transition-group>`)\n        .code,\n    ).toMatchInlineSnapshot(`\n      \"const { ssrRenderList: _ssrRenderList } = require(\"vue/server-renderer\")\n\n      return function ssrRender(_ctx, _push, _parent, _attrs) {\n        _push(\\`<!--[-->\\`)\n        _ssrRenderList(_ctx.list, (i) => {\n          _push(\\`<div></div>\\`)\n        })\n        _push(\\`<!--]-->\\`)\n      }\"\n    `)\n  })\n\n  test('with static tag', () => {\n    expect(\n      compile(\n        `<transition-group tag=\"ul\"><div v-for=\"i in list\"/></transition-group>`,\n      ).code,\n    ).toMatchInlineSnapshot(`\n      \"const { ssrRenderAttrs: _ssrRenderAttrs, ssrRenderList: _ssrRenderList } = require(\"vue/server-renderer\")\n\n      return function ssrRender(_ctx, _push, _parent, _attrs) {\n        _push(\\`<ul\\${_ssrRenderAttrs(_attrs)}>\\`)\n        _ssrRenderList(_ctx.list, (i) => {\n          _push(\\`<div></div>\\`)\n        })\n        _push(\\`</ul>\\`)\n      }\"\n    `)\n  })\n\n  // #11514\n  test('with static tag + v-if comment', () => {\n    expect(\n      compile(\n        `<transition-group tag=\"ul\"><div v-for=\"i in list\"/><div v-if=\"false\"></div></transition-group>`,\n      ).code,\n    ).toMatchInlineSnapshot(`\n      \"const { ssrRenderAttrs: _ssrRenderAttrs, ssrRenderList: _ssrRenderList } = require(\"vue/server-renderer\")\n\n      return function ssrRender(_ctx, _push, _parent, _attrs) {\n        _push(\\`<ul\\${_ssrRenderAttrs(_attrs)}>\\`)\n        _ssrRenderList(_ctx.list, (i) => {\n          _push(\\`<div></div>\\`)\n        })\n        if (false) {\n          _push(\\`<div></div>\\`)\n        }\n        _push(\\`</ul>\\`)\n      }\"\n    `)\n  })\n\n  // #11958\n  test('with static tag + comment', () => {\n    expect(\n      compile(\n        `<transition-group tag=\"ul\"><div v-for=\"i in list\"/><!--test--></transition-group>`,\n      ).code,\n    ).toMatchInlineSnapshot(`\n      \"const { ssrRenderAttrs: _ssrRenderAttrs, ssrRenderList: _ssrRenderList } = require(\"vue/server-renderer\")\n\n      return function ssrRender(_ctx, _push, _parent, _attrs) {\n        _push(\\`<ul\\${_ssrRenderAttrs(_attrs)}>\\`)\n        _ssrRenderList(_ctx.list, (i) => {\n          _push(\\`<div></div>\\`)\n        })\n        _push(\\`</ul>\\`)\n      }\"\n    `)\n  })\n\n  test('with dynamic tag', () => {\n    expect(\n      compile(\n        `<transition-group :tag=\"someTag\"><div v-for=\"i in list\"/></transition-group>`,\n      ).code,\n    ).toMatchInlineSnapshot(`\n      \"const { ssrRenderAttrs: _ssrRenderAttrs, ssrRenderList: _ssrRenderList } = require(\"vue/server-renderer\")\n\n      return function ssrRender(_ctx, _push, _parent, _attrs) {\n        _push(\\`<\\${\n          _ctx.someTag\n        }\\${\n          _ssrRenderAttrs(_attrs)\n        }>\\`)\n        _ssrRenderList(_ctx.list, (i) => {\n          _push(\\`<div></div>\\`)\n        })\n        _push(\\`</\\${_ctx.someTag}>\\`)\n      }\"\n    `)\n  })\n\n  test('with dynamic tag shorthand', () => {\n    expect(\n      compile(\n        `<transition-group :tag><div v-for=\"i in list\"/></transition-group>`,\n      ).code,\n    ).toMatchInlineSnapshot(`\n      \"const { ssrRenderAttrs: _ssrRenderAttrs, ssrRenderList: _ssrRenderList } = require(\"vue/server-renderer\")\n\n      return function ssrRender(_ctx, _push, _parent, _attrs) {\n        _push(\\`<\\${\n          _ctx.tag\n        }\\${\n          _ssrRenderAttrs(_attrs)\n        }>\\`)\n        _ssrRenderList(_ctx.list, (i) => {\n          _push(\\`<div></div>\\`)\n        })\n        _push(\\`</\\${_ctx.tag}>\\`)\n      }\"\n    `)\n  })\n\n  test('with multi fragments children', () => {\n    expect(\n      compile(\n        `<transition-group>\n              <div v-for=\"i in 10\"/>\n              <div v-for=\"i in 10\"/>\n              <template v-if=\"ok\"><div>ok</div></template>\n            </transition-group>`,\n      ).code,\n    ).toMatchInlineSnapshot(`\n      \"const { ssrRenderList: _ssrRenderList } = require(\"vue/server-renderer\")\n\n      return function ssrRender(_ctx, _push, _parent, _attrs) {\n        _push(\\`<!--[-->\\`)\n        _ssrRenderList(10, (i) => {\n          _push(\\`<div></div>\\`)\n        })\n        _ssrRenderList(10, (i) => {\n          _push(\\`<div></div>\\`)\n        })\n        if (_ctx.ok) {\n          _push(\\`<div>ok</div>\\`)\n        }\n        _push(\\`<!--]-->\\`)\n      }\"\n    `)\n  })\n\n  test('attribute fallthrough', () => {\n    expect(\n      compile(\n        `<transition-group tag=\"ul\" class=\"red\" id=\"ok\">\n        </transition-group>`,\n      ).code,\n    ).toMatchInlineSnapshot(`\n      \"const { mergeProps: _mergeProps } = require(\"vue\")\n      const { ssrRenderAttrs: _ssrRenderAttrs } = require(\"vue/server-renderer\")\n\n      return function ssrRender(_ctx, _push, _parent, _attrs) {\n        _push(\\`<ul\\${_ssrRenderAttrs(_mergeProps({\n          class: \"red\",\n          id: \"ok\"\n        }, _attrs))}></ul>\\`)\n      }\"\n    `)\n  })\n})\n"
  },
  {
    "path": "packages/compiler-ssr/__tests__/ssrVFor.spec.ts",
    "content": "import { compile } from '../src'\n\ndescribe('ssr: v-for', () => {\n  test('basic', () => {\n    expect(compile(`<div v-for=\"i in list\" />`).code).toMatchInlineSnapshot(`\n      \"const { ssrRenderList: _ssrRenderList } = require(\"vue/server-renderer\")\n\n      return function ssrRender(_ctx, _push, _parent, _attrs) {\n        _push(\\`<!--[-->\\`)\n        _ssrRenderList(_ctx.list, (i) => {\n          _push(\\`<div></div>\\`)\n        })\n        _push(\\`<!--]-->\\`)\n      }\"\n    `)\n  })\n\n  test('nested content', () => {\n    expect(compile(`<div v-for=\"i in list\">foo<span>bar</span></div>`).code)\n      .toMatchInlineSnapshot(`\n        \"const { ssrRenderList: _ssrRenderList } = require(\"vue/server-renderer\")\n\n        return function ssrRender(_ctx, _push, _parent, _attrs) {\n          _push(\\`<!--[-->\\`)\n          _ssrRenderList(_ctx.list, (i) => {\n            _push(\\`<div>foo<span>bar</span></div>\\`)\n          })\n          _push(\\`<!--]-->\\`)\n        }\"\n      `)\n  })\n\n  test('nested v-for', () => {\n    expect(\n      compile(\n        `<div v-for=\"row, i in list\">` +\n          `<div v-for=\"j in row\">{{ i }},{{ j }}</div>` +\n          `</div>`,\n      ).code,\n    ).toMatchInlineSnapshot(`\n      \"const { ssrInterpolate: _ssrInterpolate, ssrRenderList: _ssrRenderList } = require(\"vue/server-renderer\")\n\n      return function ssrRender(_ctx, _push, _parent, _attrs) {\n        _push(\\`<!--[-->\\`)\n        _ssrRenderList(_ctx.list, (row, i) => {\n          _push(\\`<div><!--[-->\\`)\n          _ssrRenderList(row, (j) => {\n            _push(\\`<div>\\${\n              _ssrInterpolate(i)\n            },\\${\n              _ssrInterpolate(j)\n            }</div>\\`)\n          })\n          _push(\\`<!--]--></div>\\`)\n        })\n        _push(\\`<!--]-->\\`)\n      }\"\n    `)\n  })\n\n  test('template v-for (text)', () => {\n    expect(compile(`<template v-for=\"i in list\">{{ i }}</template>`).code)\n      .toMatchInlineSnapshot(`\n        \"const { ssrInterpolate: _ssrInterpolate, ssrRenderList: _ssrRenderList } = require(\"vue/server-renderer\")\n\n        return function ssrRender(_ctx, _push, _parent, _attrs) {\n          _push(\\`<!--[-->\\`)\n          _ssrRenderList(_ctx.list, (i) => {\n            _push(\\`<!--[-->\\${_ssrInterpolate(i)}<!--]-->\\`)\n          })\n          _push(\\`<!--]-->\\`)\n        }\"\n      `)\n  })\n\n  test('template v-for (single element)', () => {\n    expect(\n      compile(`<template v-for=\"i in list\"><span>{{ i }}</span></template>`)\n        .code,\n    ).toMatchInlineSnapshot(`\n      \"const { ssrInterpolate: _ssrInterpolate, ssrRenderList: _ssrRenderList } = require(\"vue/server-renderer\")\n\n      return function ssrRender(_ctx, _push, _parent, _attrs) {\n        _push(\\`<!--[-->\\`)\n        _ssrRenderList(_ctx.list, (i) => {\n          _push(\\`<span>\\${_ssrInterpolate(i)}</span>\\`)\n        })\n        _push(\\`<!--]-->\\`)\n      }\"\n    `)\n  })\n\n  test('template v-for (multi element)', () => {\n    expect(\n      compile(\n        `<template v-for=\"i in list\"><span>{{ i }}</span><span>{{ i + 1 }}</span></template>`,\n      ).code,\n    ).toMatchInlineSnapshot(`\n      \"const { ssrInterpolate: _ssrInterpolate, ssrRenderList: _ssrRenderList } = require(\"vue/server-renderer\")\n\n      return function ssrRender(_ctx, _push, _parent, _attrs) {\n        _push(\\`<!--[-->\\`)\n        _ssrRenderList(_ctx.list, (i) => {\n          _push(\\`<!--[--><span>\\${\n            _ssrInterpolate(i)\n          }</span><span>\\${\n            _ssrInterpolate(i + 1)\n          }</span><!--]-->\\`)\n        })\n        _push(\\`<!--]-->\\`)\n      }\"\n    `)\n  })\n\n  test('render loop args should not be prefixed', () => {\n    const { code } = compile(\n      `<div v-for=\"{ foo }, index in list\">{{ foo + bar + index }}</div>`,\n    )\n    expect(code).toMatch(`_ctx.bar`)\n    expect(code).not.toMatch(`_ctx.foo`)\n    expect(code).not.toMatch(`_ctx.index`)\n    expect(code).toMatchInlineSnapshot(`\n      \"const { ssrInterpolate: _ssrInterpolate, ssrRenderList: _ssrRenderList } = require(\"vue/server-renderer\")\n\n      return function ssrRender(_ctx, _push, _parent, _attrs) {\n        _push(\\`<!--[-->\\`)\n        _ssrRenderList(_ctx.list, ({ foo }, index) => {\n          _push(\\`<div>\\${_ssrInterpolate(foo + _ctx.bar + index)}</div>\\`)\n        })\n        _push(\\`<!--]-->\\`)\n      }\"\n    `)\n  })\n})\n"
  },
  {
    "path": "packages/compiler-ssr/__tests__/ssrVIf.spec.ts",
    "content": "import { compile } from '../src'\n\ndescribe('ssr: v-if', () => {\n  test('basic', () => {\n    expect(compile(`<div v-if=\"foo\"></div>`).code).toMatchInlineSnapshot(`\n      \"const { ssrRenderAttrs: _ssrRenderAttrs } = require(\"vue/server-renderer\")\n\n      return function ssrRender(_ctx, _push, _parent, _attrs) {\n        if (_ctx.foo) {\n          _push(\\`<div\\${_ssrRenderAttrs(_attrs)}></div>\\`)\n        } else {\n          _push(\\`<!---->\\`)\n        }\n      }\"\n    `)\n  })\n\n  test('with nested content', () => {\n    expect(compile(`<div v-if=\"foo\">hello<span>ok</span></div>`).code)\n      .toMatchInlineSnapshot(`\n        \"const { ssrRenderAttrs: _ssrRenderAttrs } = require(\"vue/server-renderer\")\n\n        return function ssrRender(_ctx, _push, _parent, _attrs) {\n          if (_ctx.foo) {\n            _push(\\`<div\\${_ssrRenderAttrs(_attrs)}>hello<span>ok</span></div>\\`)\n          } else {\n            _push(\\`<!---->\\`)\n          }\n        }\"\n      `)\n  })\n\n  test('v-if + v-else', () => {\n    expect(compile(`<div v-if=\"foo\"/><span v-else/>`).code)\n      .toMatchInlineSnapshot(`\n        \"const { ssrRenderAttrs: _ssrRenderAttrs } = require(\"vue/server-renderer\")\n\n        return function ssrRender(_ctx, _push, _parent, _attrs) {\n          if (_ctx.foo) {\n            _push(\\`<div\\${_ssrRenderAttrs(_attrs)}></div>\\`)\n          } else {\n            _push(\\`<span\\${_ssrRenderAttrs(_attrs)}></span>\\`)\n          }\n        }\"\n      `)\n  })\n\n  test('v-if + v-else-if', () => {\n    expect(compile(`<div v-if=\"foo\"/><span v-else-if=\"bar\"/>`).code)\n      .toMatchInlineSnapshot(`\n        \"const { ssrRenderAttrs: _ssrRenderAttrs } = require(\"vue/server-renderer\")\n\n        return function ssrRender(_ctx, _push, _parent, _attrs) {\n          if (_ctx.foo) {\n            _push(\\`<div\\${_ssrRenderAttrs(_attrs)}></div>\\`)\n          } else if (_ctx.bar) {\n            _push(\\`<span\\${_ssrRenderAttrs(_attrs)}></span>\\`)\n          } else {\n            _push(\\`<!---->\\`)\n          }\n        }\"\n      `)\n  })\n\n  test('v-if + v-else-if + v-else', () => {\n    expect(compile(`<div v-if=\"foo\"/><span v-else-if=\"bar\"/><p v-else/>`).code)\n      .toMatchInlineSnapshot(`\n        \"const { ssrRenderAttrs: _ssrRenderAttrs } = require(\"vue/server-renderer\")\n\n        return function ssrRender(_ctx, _push, _parent, _attrs) {\n          if (_ctx.foo) {\n            _push(\\`<div\\${_ssrRenderAttrs(_attrs)}></div>\\`)\n          } else if (_ctx.bar) {\n            _push(\\`<span\\${_ssrRenderAttrs(_attrs)}></span>\\`)\n          } else {\n            _push(\\`<p\\${_ssrRenderAttrs(_attrs)}></p>\\`)\n          }\n        }\"\n      `)\n  })\n\n  test('<template v-if> (text)', () => {\n    expect(compile(`<template v-if=\"foo\">hello</template>`).code)\n      .toMatchInlineSnapshot(`\n      \"\n      return function ssrRender(_ctx, _push, _parent, _attrs) {\n        if (_ctx.foo) {\n          _push(\\`<!--[-->hello<!--]-->\\`)\n        } else {\n          _push(\\`<!---->\\`)\n        }\n      }\"\n    `)\n  })\n\n  test('<template v-if> (single element)', () => {\n    // single element should not wrap with fragment\n    expect(compile(`<template v-if=\"foo\"><div>hi</div></template>`).code)\n      .toMatchInlineSnapshot(`\n        \"const { ssrRenderAttrs: _ssrRenderAttrs } = require(\"vue/server-renderer\")\n\n        return function ssrRender(_ctx, _push, _parent, _attrs) {\n          if (_ctx.foo) {\n            _push(\\`<div\\${_ssrRenderAttrs(_attrs)}>hi</div>\\`)\n          } else {\n            _push(\\`<!---->\\`)\n          }\n        }\"\n      `)\n  })\n\n  test('<template v-if> (multiple element)', () => {\n    expect(\n      compile(`<template v-if=\"foo\"><div>hi</div><div>ho</div></template>`)\n        .code,\n    ).toMatchInlineSnapshot(`\n      \"\n      return function ssrRender(_ctx, _push, _parent, _attrs) {\n        if (_ctx.foo) {\n          _push(\\`<!--[--><div>hi</div><div>ho</div><!--]-->\\`)\n        } else {\n          _push(\\`<!---->\\`)\n        }\n      }\"\n    `)\n  })\n\n  test('<template v-if> (with v-for inside)', () => {\n    expect(\n      compile(`<template v-if=\"foo\"><div v-for=\"i in list\"/></template>`).code,\n    ).toMatchInlineSnapshot(`\n      \"const { ssrRenderList: _ssrRenderList } = require(\"vue/server-renderer\")\n\n      return function ssrRender(_ctx, _push, _parent, _attrs) {\n        if (_ctx.foo) {\n          _push(\\`<!--[-->\\`)\n          _ssrRenderList(_ctx.list, (i) => {\n            _push(\\`<div></div>\\`)\n          })\n          _push(\\`<!--]-->\\`)\n        } else {\n          _push(\\`<!---->\\`)\n        }\n      }\"\n    `)\n  })\n\n  test('<template v-if> + normal v-else', () => {\n    expect(\n      compile(\n        `<template v-if=\"foo\"><div>hi</div><div>ho</div></template><div v-else/>`,\n      ).code,\n    ).toMatchInlineSnapshot(`\n      \"const { ssrRenderAttrs: _ssrRenderAttrs } = require(\"vue/server-renderer\")\n\n      return function ssrRender(_ctx, _push, _parent, _attrs) {\n        if (_ctx.foo) {\n          _push(\\`<!--[--><div>hi</div><div>ho</div><!--]-->\\`)\n        } else {\n          _push(\\`<div\\${_ssrRenderAttrs(_attrs)}></div>\\`)\n        }\n      }\"\n    `)\n  })\n})\n"
  },
  {
    "path": "packages/compiler-ssr/__tests__/ssrVModel.spec.ts",
    "content": "import { compile } from '../src'\n\nfunction compileWithWrapper(src: string) {\n  return compile(`<div>${src}</div>`)\n}\n\ndescribe('ssr: v-model', () => {\n  test('<input> (text types)', () => {\n    expect(compileWithWrapper(`<input v-model=\"bar\">`).code)\n      .toMatchInlineSnapshot(`\n        \"const { ssrRenderAttr: _ssrRenderAttr, ssrRenderAttrs: _ssrRenderAttrs } = require(\"vue/server-renderer\")\n\n        return function ssrRender(_ctx, _push, _parent, _attrs) {\n          _push(\\`<div\\${\n            _ssrRenderAttrs(_attrs)\n          }><input\\${\n            _ssrRenderAttr(\"value\", _ctx.bar)\n          }></div>\\`)\n        }\"\n      `)\n\n    expect(compileWithWrapper(`<input type=\"email\" v-model=\"bar\">`).code)\n      .toMatchInlineSnapshot(`\n        \"const { ssrRenderAttr: _ssrRenderAttr, ssrRenderAttrs: _ssrRenderAttrs } = require(\"vue/server-renderer\")\n\n        return function ssrRender(_ctx, _push, _parent, _attrs) {\n          _push(\\`<div\\${\n            _ssrRenderAttrs(_attrs)\n          }><input type=\"email\"\\${\n            _ssrRenderAttr(\"value\", _ctx.bar)\n          }></div>\\`)\n        }\"\n      `)\n  })\n\n  test('<select v-model>', () => {\n    expect(\n      compileWithWrapper(\n        `<select v-model=\"model\"><option value=\"1\"></option></select>`,\n      ).code,\n    ).toMatchInlineSnapshot(`\n      \"const { ssrIncludeBooleanAttr: _ssrIncludeBooleanAttr, ssrLooseContain: _ssrLooseContain, ssrLooseEqual: _ssrLooseEqual, ssrRenderAttrs: _ssrRenderAttrs } = require(\"vue/server-renderer\")\n\n      return function ssrRender(_ctx, _push, _parent, _attrs) {\n        _push(\\`<div\\${\n          _ssrRenderAttrs(_attrs)\n        }><select><option value=\"1\"\\${\n          (_ssrIncludeBooleanAttr((Array.isArray(_ctx.model))\n            ? _ssrLooseContain(_ctx.model, \"1\")\n            : _ssrLooseEqual(_ctx.model, \"1\"))) ? \" selected\" : \"\"\n        }></option></select></div>\\`)\n      }\"\n    `)\n\n    expect(\n      compileWithWrapper(\n        `<select v-model=\"model\"><option v-for=\"i in items\" :value=\"i\"></option></select>`,\n      ).code,\n    ).toMatchInlineSnapshot(`\n      \"const { ssrRenderAttr: _ssrRenderAttr, ssrIncludeBooleanAttr: _ssrIncludeBooleanAttr, ssrLooseContain: _ssrLooseContain, ssrLooseEqual: _ssrLooseEqual, ssrRenderAttrs: _ssrRenderAttrs, ssrRenderList: _ssrRenderList } = require(\"vue/server-renderer\")\n\n      return function ssrRender(_ctx, _push, _parent, _attrs) {\n        _push(\\`<div\\${_ssrRenderAttrs(_attrs)}><select><!--[-->\\`)\n        _ssrRenderList(_ctx.items, (i) => {\n          _push(\\`<option\\${\n            _ssrRenderAttr(\"value\", i)\n          }\\${\n            (_ssrIncludeBooleanAttr((Array.isArray(_ctx.model))\n              ? _ssrLooseContain(_ctx.model, i)\n              : _ssrLooseEqual(_ctx.model, i))) ? \" selected\" : \"\"\n          }></option>\\`)\n        })\n        _push(\\`<!--]--></select></div>\\`)\n      }\"\n    `)\n\n    expect(\n      compileWithWrapper(\n        `<select v-model=\"model\"><option v-if=\"true\" :value=\"i\"></option></select>`,\n      ).code,\n    ).toMatchInlineSnapshot(`\n      \"const { ssrRenderAttr: _ssrRenderAttr, ssrIncludeBooleanAttr: _ssrIncludeBooleanAttr, ssrLooseContain: _ssrLooseContain, ssrLooseEqual: _ssrLooseEqual, ssrRenderAttrs: _ssrRenderAttrs } = require(\"vue/server-renderer\")\n\n      return function ssrRender(_ctx, _push, _parent, _attrs) {\n        _push(\\`<div\\${_ssrRenderAttrs(_attrs)}><select>\\`)\n        if (true) {\n          _push(\\`<option\\${\n            _ssrRenderAttr(\"value\", _ctx.i)\n          }\\${\n            (_ssrIncludeBooleanAttr((Array.isArray(_ctx.model))\n              ? _ssrLooseContain(_ctx.model, _ctx.i)\n              : _ssrLooseEqual(_ctx.model, _ctx.i))) ? \" selected\" : \"\"\n          }></option>\\`)\n        } else {\n          _push(\\`<!---->\\`)\n        }\n        _push(\\`</select></div>\\`)\n      }\"\n    `)\n\n    expect(\n      compileWithWrapper(\n        `<select multiple v-model=\"model\"><option value=\"1\" selected></option><option value=\"2\"></option></select>`,\n      ).code,\n    ).toMatchInlineSnapshot(`\n      \"const { ssrIncludeBooleanAttr: _ssrIncludeBooleanAttr, ssrLooseContain: _ssrLooseContain, ssrLooseEqual: _ssrLooseEqual, ssrRenderAttrs: _ssrRenderAttrs } = require(\"vue/server-renderer\")\n\n      return function ssrRender(_ctx, _push, _parent, _attrs) {\n        _push(\\`<div\\${\n          _ssrRenderAttrs(_attrs)\n        }><select multiple><option value=\"1\" selected></option><option value=\"2\"\\${\n          (_ssrIncludeBooleanAttr((Array.isArray(_ctx.model))\n            ? _ssrLooseContain(_ctx.model, \"2\")\n            : _ssrLooseEqual(_ctx.model, \"2\"))) ? \" selected\" : \"\"\n        }></option></select></div>\\`)\n      }\"\n    `)\n\n    expect(\n      compileWithWrapper(`<select multiple v-model=\"model\"><slot/></select>`)\n        .code,\n    ).toMatchInlineSnapshot(`\n      \"const { ssrRenderSlot: _ssrRenderSlot, ssrRenderAttrs: _ssrRenderAttrs } = require(\"vue/server-renderer\")\n\n      return function ssrRender(_ctx, _push, _parent, _attrs) {\n        _push(\\`<div\\${_ssrRenderAttrs(_attrs)}><select multiple>\\`)\n        _ssrRenderSlot(_ctx.$slots, \"default\", {}, null, _push, _parent)\n        _push(\\`</select></div>\\`)\n      }\"\n    `)\n\n    expect(\n      compileWithWrapper(`\n        <select multiple v-model=\"model\">\n          <optgroup label=\"foo\">\n            <option value=\"bar\">bar</option>\n          </optgroup>\n        </select>`).code,\n    ).toMatchInlineSnapshot(`\n      \"const { ssrIncludeBooleanAttr: _ssrIncludeBooleanAttr, ssrLooseContain: _ssrLooseContain, ssrLooseEqual: _ssrLooseEqual, ssrRenderAttrs: _ssrRenderAttrs } = require(\"vue/server-renderer\")\n\n      return function ssrRender(_ctx, _push, _parent, _attrs) {\n        _push(\\`<div\\${\n          _ssrRenderAttrs(_attrs)\n        }><select multiple><optgroup label=\"foo\"><option value=\"bar\"\\${\n          (_ssrIncludeBooleanAttr((Array.isArray(_ctx.model))\n            ? _ssrLooseContain(_ctx.model, \"bar\")\n            : _ssrLooseEqual(_ctx.model, \"bar\"))) ? \" selected\" : \"\"\n        }>bar</option></optgroup></select></div>\\`)\n      }\"\n    `)\n\n    expect(\n      compileWithWrapper(`\n        <select multiple v-model=\"model\">\n          <optgroup label=\"foo\">\n            <slot/>\n          </optgroup>\n        </select>`).code,\n    ).toMatchInlineSnapshot(`\n      \"const { ssrRenderSlot: _ssrRenderSlot, ssrRenderAttrs: _ssrRenderAttrs } = require(\"vue/server-renderer\")\n\n      return function ssrRender(_ctx, _push, _parent, _attrs) {\n        _push(\\`<div\\${_ssrRenderAttrs(_attrs)}><select multiple><optgroup label=\"foo\">\\`)\n        _ssrRenderSlot(_ctx.$slots, \"default\", {}, null, _push, _parent)\n        _push(\\`</optgroup></select></div>\\`)\n      }\"\n    `)\n\n    expect(\n      compileWithWrapper(`\n        <select multiple v-model=\"model\">\n          <optgroup>\n            <option v-for=\"item in items\" :value=\"item\">{{item}}</option>\n          </optgroup>\n        </select>`).code,\n    ).toMatchInlineSnapshot(`\n      \"const { ssrRenderAttr: _ssrRenderAttr, ssrIncludeBooleanAttr: _ssrIncludeBooleanAttr, ssrLooseContain: _ssrLooseContain, ssrLooseEqual: _ssrLooseEqual, ssrRenderAttrs: _ssrRenderAttrs, ssrInterpolate: _ssrInterpolate, ssrRenderList: _ssrRenderList } = require(\"vue/server-renderer\")\n\n      return function ssrRender(_ctx, _push, _parent, _attrs) {\n        _push(\\`<div\\${_ssrRenderAttrs(_attrs)}><select multiple><optgroup><!--[-->\\`)\n        _ssrRenderList(_ctx.items, (item) => {\n          _push(\\`<option\\${\n            _ssrRenderAttr(\"value\", item)\n          }\\${\n            (_ssrIncludeBooleanAttr((Array.isArray(_ctx.model))\n              ? _ssrLooseContain(_ctx.model, item)\n              : _ssrLooseEqual(_ctx.model, item))) ? \" selected\" : \"\"\n          }>\\${\n            _ssrInterpolate(item)\n          }</option>\\`)\n        })\n        _push(\\`<!--]--></optgroup></select></div>\\`)\n      }\"\n    `)\n\n    expect(\n      compileWithWrapper(`\n        <select multiple v-model=\"model\">\n          <optgroup>\n            <option v-if=\"true\" :value=\"item\">{{item}}</option>\n          </optgroup>\n        </select>`).code,\n    ).toMatchInlineSnapshot(`\n      \"const { ssrRenderAttr: _ssrRenderAttr, ssrIncludeBooleanAttr: _ssrIncludeBooleanAttr, ssrLooseContain: _ssrLooseContain, ssrLooseEqual: _ssrLooseEqual, ssrRenderAttrs: _ssrRenderAttrs, ssrInterpolate: _ssrInterpolate } = require(\"vue/server-renderer\")\n\n      return function ssrRender(_ctx, _push, _parent, _attrs) {\n        _push(\\`<div\\${_ssrRenderAttrs(_attrs)}><select multiple><optgroup>\\`)\n        if (true) {\n          _push(\\`<option\\${\n            _ssrRenderAttr(\"value\", _ctx.item)\n          }\\${\n            (_ssrIncludeBooleanAttr((Array.isArray(_ctx.model))\n              ? _ssrLooseContain(_ctx.model, _ctx.item)\n              : _ssrLooseEqual(_ctx.model, _ctx.item))) ? \" selected\" : \"\"\n          }>\\${\n            _ssrInterpolate(_ctx.item)\n          }</option>\\`)\n        } else {\n          _push(\\`<!---->\\`)\n        }\n        _push(\\`</optgroup></select></div>\\`)\n      }\"\n    `)\n\n    expect(\n      compileWithWrapper(`\n        <select multiple v-model=\"model\">\n          <optgroup>\n            <template v-if=\"ok\">\n              <option v-for=\"item in items\" :value=\"item\">{{item}}</option>\n            </template>\n          </optgroup>\n        </select>`).code,\n    ).toMatchInlineSnapshot(`\n      \"const { ssrRenderAttr: _ssrRenderAttr, ssrIncludeBooleanAttr: _ssrIncludeBooleanAttr, ssrLooseContain: _ssrLooseContain, ssrLooseEqual: _ssrLooseEqual, ssrRenderAttrs: _ssrRenderAttrs, ssrInterpolate: _ssrInterpolate, ssrRenderList: _ssrRenderList } = require(\"vue/server-renderer\")\n\n      return function ssrRender(_ctx, _push, _parent, _attrs) {\n        _push(\\`<div\\${_ssrRenderAttrs(_attrs)}><select multiple><optgroup>\\`)\n        if (_ctx.ok) {\n          _push(\\`<!--[-->\\`)\n          _ssrRenderList(_ctx.items, (item) => {\n            _push(\\`<option\\${\n              _ssrRenderAttr(\"value\", item)\n            }\\${\n              (_ssrIncludeBooleanAttr((Array.isArray(_ctx.model))\n                ? _ssrLooseContain(_ctx.model, item)\n                : _ssrLooseEqual(_ctx.model, item))) ? \" selected\" : \"\"\n            }>\\${\n              _ssrInterpolate(item)\n            }</option>\\`)\n          })\n          _push(\\`<!--]-->\\`)\n        } else {\n          _push(\\`<!---->\\`)\n        }\n        _push(\\`</optgroup></select></div>\\`)\n      }\"\n    `)\n\n    expect(\n      compileWithWrapper(`\n        <select multiple v-model=\"model\">\n          <optgroup>\n            <template v-for=\"item in items\" :value=\"item\">\n              <option v-if=\"item===1\" :value=\"item\">{{item}}</option>\n            </template>\n          </optgroup>\n        </select>`).code,\n    ).toMatchInlineSnapshot(`\n      \"const { ssrRenderAttr: _ssrRenderAttr, ssrIncludeBooleanAttr: _ssrIncludeBooleanAttr, ssrLooseContain: _ssrLooseContain, ssrLooseEqual: _ssrLooseEqual, ssrRenderAttrs: _ssrRenderAttrs, ssrInterpolate: _ssrInterpolate, ssrRenderList: _ssrRenderList } = require(\"vue/server-renderer\")\n\n      return function ssrRender(_ctx, _push, _parent, _attrs) {\n        _push(\\`<div\\${_ssrRenderAttrs(_attrs)}><select multiple><optgroup><!--[-->\\`)\n        _ssrRenderList(_ctx.items, (item) => {\n          _push(\\`<!--[-->\\`)\n          if (item===1) {\n            _push(\\`<option\\${\n              _ssrRenderAttr(\"value\", item)\n            }\\${\n              (_ssrIncludeBooleanAttr((Array.isArray(_ctx.model))\n                ? _ssrLooseContain(_ctx.model, item)\n                : _ssrLooseEqual(_ctx.model, item))) ? \" selected\" : \"\"\n            }>\\${\n              _ssrInterpolate(item)\n            }</option>\\`)\n          } else {\n            _push(\\`<!---->\\`)\n          }\n          _push(\\`<!--]-->\\`)\n        })\n        _push(\\`<!--]--></optgroup></select></div>\\`)\n      }\"\n    `)\n  })\n\n  test('<input type=\"radio\">', () => {\n    expect(\n      compileWithWrapper(`<input type=\"radio\" value=\"foo\" v-model=\"bar\">`).code,\n    ).toMatchInlineSnapshot(`\n      \"const { ssrLooseEqual: _ssrLooseEqual, ssrIncludeBooleanAttr: _ssrIncludeBooleanAttr, ssrRenderAttrs: _ssrRenderAttrs } = require(\"vue/server-renderer\")\n\n      return function ssrRender(_ctx, _push, _parent, _attrs) {\n        _push(\\`<div\\${\n          _ssrRenderAttrs(_attrs)\n        }><input type=\"radio\" value=\"foo\"\\${\n          (_ssrIncludeBooleanAttr(_ssrLooseEqual(_ctx.bar, \"foo\"))) ? \" checked\" : \"\"\n        }></div>\\`)\n      }\"\n    `)\n  })\n\n  test('<input type=\"checkbox\">', () => {\n    expect(compileWithWrapper(`<input type=\"checkbox\" v-model=\"bar\">`).code)\n      .toMatchInlineSnapshot(`\n        \"const { ssrLooseContain: _ssrLooseContain, ssrIncludeBooleanAttr: _ssrIncludeBooleanAttr, ssrRenderAttrs: _ssrRenderAttrs } = require(\"vue/server-renderer\")\n\n        return function ssrRender(_ctx, _push, _parent, _attrs) {\n          _push(\\`<div\\${\n            _ssrRenderAttrs(_attrs)\n          }><input type=\"checkbox\"\\${\n            (_ssrIncludeBooleanAttr((Array.isArray(_ctx.bar))\n              ? _ssrLooseContain(_ctx.bar, null)\n              : _ctx.bar)) ? \" checked\" : \"\"\n          }></div>\\`)\n        }\"\n      `)\n\n    expect(\n      compileWithWrapper(`<input type=\"checkbox\" value=\"foo\" v-model=\"bar\">`)\n        .code,\n    ).toMatchInlineSnapshot(`\n      \"const { ssrLooseContain: _ssrLooseContain, ssrIncludeBooleanAttr: _ssrIncludeBooleanAttr, ssrRenderAttrs: _ssrRenderAttrs } = require(\"vue/server-renderer\")\n\n      return function ssrRender(_ctx, _push, _parent, _attrs) {\n        _push(\\`<div\\${\n          _ssrRenderAttrs(_attrs)\n        }><input type=\"checkbox\" value=\"foo\"\\${\n          (_ssrIncludeBooleanAttr((Array.isArray(_ctx.bar))\n            ? _ssrLooseContain(_ctx.bar, \"foo\")\n            : _ctx.bar)) ? \" checked\" : \"\"\n        }></div>\\`)\n      }\"\n    `)\n\n    expect(\n      compileWithWrapper(\n        `<input type=\"checkbox\" :true-value=\"foo\" :false-value=\"bar\" v-model=\"baz\">`,\n      ).code,\n    ).toMatchInlineSnapshot(`\n      \"const { ssrLooseEqual: _ssrLooseEqual, ssrIncludeBooleanAttr: _ssrIncludeBooleanAttr, ssrRenderAttrs: _ssrRenderAttrs } = require(\"vue/server-renderer\")\n\n      return function ssrRender(_ctx, _push, _parent, _attrs) {\n        _push(\\`<div\\${\n          _ssrRenderAttrs(_attrs)\n        }><input type=\"checkbox\"\\${\n          (_ssrIncludeBooleanAttr(_ssrLooseEqual(_ctx.baz, _ctx.foo))) ? \" checked\" : \"\"\n        }></div>\\`)\n      }\"\n    `)\n\n    expect(\n      compileWithWrapper(\n        `<input type=\"checkbox\" true-value=\"foo\" false-value=\"bar\" v-model=\"baz\">`,\n      ).code,\n    ).toMatchInlineSnapshot(`\n      \"const { ssrLooseEqual: _ssrLooseEqual, ssrIncludeBooleanAttr: _ssrIncludeBooleanAttr, ssrRenderAttrs: _ssrRenderAttrs } = require(\"vue/server-renderer\")\n\n      return function ssrRender(_ctx, _push, _parent, _attrs) {\n        _push(\\`<div\\${\n          _ssrRenderAttrs(_attrs)\n        }><input type=\"checkbox\"\\${\n          (_ssrIncludeBooleanAttr(_ssrLooseEqual(_ctx.baz, \"foo\"))) ? \" checked\" : \"\"\n        }></div>\\`)\n      }\"\n    `)\n  })\n\n  test('<textarea>', () => {\n    expect(compileWithWrapper(`<textarea v-model=\"foo\">bar</textarea>`).code)\n      .toMatchInlineSnapshot(`\n        \"const { ssrRenderAttrs: _ssrRenderAttrs, ssrInterpolate: _ssrInterpolate } = require(\"vue/server-renderer\")\n\n        return function ssrRender(_ctx, _push, _parent, _attrs) {\n          _push(\\`<div\\${\n            _ssrRenderAttrs(_attrs)\n          }><textarea>\\${\n            _ssrInterpolate(_ctx.foo)\n          }</textarea></div>\\`)\n        }\"\n      `)\n  })\n\n  test('<input :type=\"x\">', () => {\n    expect(compileWithWrapper(`<input :type=\"x\" v-model=\"foo\">`).code)\n      .toMatchInlineSnapshot(`\n        \"const { ssrRenderAttr: _ssrRenderAttr, ssrRenderDynamicModel: _ssrRenderDynamicModel, ssrRenderAttrs: _ssrRenderAttrs } = require(\"vue/server-renderer\")\n\n        return function ssrRender(_ctx, _push, _parent, _attrs) {\n          _push(\\`<div\\${\n            _ssrRenderAttrs(_attrs)\n          }><input\\${\n            _ssrRenderAttr(\"type\", _ctx.x)\n          }\\${\n            _ssrRenderDynamicModel(_ctx.x, _ctx.foo, null)\n          }></div>\\`)\n        }\"\n      `)\n\n    expect(\n      compileWithWrapper(`<input :type=\"x\" v-model=\"foo\" value=\"bar\">`).code,\n    ).toMatchInlineSnapshot(`\n      \"const { ssrRenderAttr: _ssrRenderAttr, ssrRenderDynamicModel: _ssrRenderDynamicModel, ssrRenderAttrs: _ssrRenderAttrs } = require(\"vue/server-renderer\")\n\n      return function ssrRender(_ctx, _push, _parent, _attrs) {\n        _push(\\`<div\\${\n          _ssrRenderAttrs(_attrs)\n        }><input\\${\n          _ssrRenderAttr(\"type\", _ctx.x)\n        }\\${\n          _ssrRenderDynamicModel(_ctx.x, _ctx.foo, \"bar\")\n        } value=\"bar\"></div>\\`)\n      }\"\n    `)\n\n    expect(\n      compileWithWrapper(`<input :type=\"x\" v-model=\"foo\" :value=\"bar\">`).code,\n    ).toMatchInlineSnapshot(`\n      \"const { ssrRenderAttr: _ssrRenderAttr, ssrRenderDynamicModel: _ssrRenderDynamicModel, ssrRenderAttrs: _ssrRenderAttrs } = require(\"vue/server-renderer\")\n\n      return function ssrRender(_ctx, _push, _parent, _attrs) {\n        _push(\\`<div\\${\n          _ssrRenderAttrs(_attrs)\n        }><input\\${\n          _ssrRenderAttr(\"type\", _ctx.x)\n        }\\${\n          _ssrRenderDynamicModel(_ctx.x, _ctx.foo, _ctx.bar)\n        }\\${\n          _ssrRenderAttr(\"value\", _ctx.bar)\n        }></div>\\`)\n      }\"\n    `)\n  })\n\n  test('<input v-bind=\"obj\">', () => {\n    expect(compileWithWrapper(`<input v-bind=\"obj\" v-model=\"foo\">`).code)\n      .toMatchInlineSnapshot(`\n        \"const { mergeProps: _mergeProps } = require(\"vue\")\n        const { ssrRenderAttrs: _ssrRenderAttrs, ssrGetDynamicModelProps: _ssrGetDynamicModelProps } = require(\"vue/server-renderer\")\n\n        return function ssrRender(_ctx, _push, _parent, _attrs) {\n          let _temp0\n\n          _push(\\`<div\\${\n            _ssrRenderAttrs(_attrs)\n          }><input\\${\n            _ssrRenderAttrs((_temp0 = _ctx.obj, _mergeProps(_temp0, _ssrGetDynamicModelProps(_temp0, _ctx.foo))))\n          }></div>\\`)\n        }\"\n      `)\n\n    expect(\n      compileWithWrapper(`<input id=\"x\" v-bind=\"obj\" v-model=\"foo\" class=\"y\">`)\n        .code,\n    ).toMatchInlineSnapshot(`\n      \"const { mergeProps: _mergeProps } = require(\"vue\")\n      const { ssrRenderAttrs: _ssrRenderAttrs, ssrGetDynamicModelProps: _ssrGetDynamicModelProps } = require(\"vue/server-renderer\")\n\n      return function ssrRender(_ctx, _push, _parent, _attrs) {\n        let _temp0\n\n        _push(\\`<div\\${\n          _ssrRenderAttrs(_attrs)\n        }><input\\${\n          _ssrRenderAttrs((_temp0 = _mergeProps({ id: \"x\" }, _ctx.obj, { class: \"y\" }), _mergeProps(_temp0, _ssrGetDynamicModelProps(_temp0, _ctx.foo))))\n        }></div>\\`)\n      }\"\n    `)\n  })\n})\n"
  },
  {
    "path": "packages/compiler-ssr/__tests__/ssrVShow.spec.ts",
    "content": "import { compile } from '../src'\n\nfunction compileWithWrapper(src: string) {\n  return compile(`<div>${src}</div>`)\n}\n\ndescribe('ssr: v-show', () => {\n  test('basic as root', () => {\n    expect(compile(`<div v-show=\"foo\"/>`).code).toMatchInlineSnapshot(`\n      \"const { mergeProps: _mergeProps } = require(\"vue\")\n      const { ssrRenderAttrs: _ssrRenderAttrs } = require(\"vue/server-renderer\")\n\n      return function ssrRender(_ctx, _push, _parent, _attrs) {\n        _push(\\`<div\\${_ssrRenderAttrs(_mergeProps(_attrs, {\n          style: (_ctx.foo) ? null : { display: \"none\" }\n        }))}></div>\\`)\n      }\"\n    `)\n  })\n\n  test('basic', () => {\n    expect(compileWithWrapper(`<div v-show=\"foo\"/>`).code)\n      .toMatchInlineSnapshot(`\n        \"const { ssrRenderStyle: _ssrRenderStyle, ssrRenderAttrs: _ssrRenderAttrs } = require(\"vue/server-renderer\")\n\n        return function ssrRender(_ctx, _push, _parent, _attrs) {\n          _push(\\`<div\\${\n            _ssrRenderAttrs(_attrs)\n          }><div style=\"\\${\n            _ssrRenderStyle((_ctx.foo) ? null : { display: \"none\" })\n          }\"></div></div>\\`)\n        }\"\n      `)\n  })\n\n  test('with static style', () => {\n    expect(compileWithWrapper(`<div style=\"color:red\" v-show=\"foo\"/>`).code)\n      .toMatchInlineSnapshot(`\n        \"const { ssrRenderStyle: _ssrRenderStyle, ssrRenderAttrs: _ssrRenderAttrs } = require(\"vue/server-renderer\")\n\n        return function ssrRender(_ctx, _push, _parent, _attrs) {\n          _push(\\`<div\\${\n            _ssrRenderAttrs(_attrs)\n          }><div style=\"\\${\n            _ssrRenderStyle([\n              {\"color\":\"red\"},\n              (_ctx.foo) ? null : { display: \"none\" }\n            ])\n          }\"></div></div>\\`)\n        }\"\n      `)\n  })\n\n  test('with dynamic style', () => {\n    expect(\n      compileWithWrapper(`<div :style=\"{ color: 'red' }\" v-show=\"foo\"/>`).code,\n    ).toMatchInlineSnapshot(`\n      \"const { ssrRenderStyle: _ssrRenderStyle, ssrRenderAttrs: _ssrRenderAttrs } = require(\"vue/server-renderer\")\n\n      return function ssrRender(_ctx, _push, _parent, _attrs) {\n        _push(\\`<div\\${\n          _ssrRenderAttrs(_attrs)\n        }><div style=\"\\${\n          _ssrRenderStyle([\n            { color: 'red' },\n            (_ctx.foo) ? null : { display: \"none\" }\n          ])\n        }\"></div></div>\\`)\n      }\"\n    `)\n  })\n\n  test('with static + dynamic style', () => {\n    expect(\n      compileWithWrapper(\n        `<div style=\"color:red\" :style=\"{ fontSize: 14 }\" v-show=\"foo\"/>`,\n      ).code,\n    ).toMatchInlineSnapshot(`\n      \"const { ssrRenderStyle: _ssrRenderStyle, ssrRenderAttrs: _ssrRenderAttrs } = require(\"vue/server-renderer\")\n\n      return function ssrRender(_ctx, _push, _parent, _attrs) {\n        _push(\\`<div\\${\n          _ssrRenderAttrs(_attrs)\n        }><div style=\"\\${\n          _ssrRenderStyle([\n            {\"color\":\"red\"},\n            { fontSize: 14 },\n            (_ctx.foo) ? null : { display: \"none\" }\n          ])\n        }\"></div></div>\\`)\n      }\"\n    `)\n  })\n\n  test('with style + display', () => {\n    expect(compileWithWrapper(`<div v-show=\"foo\" style=\"display:flex\" />`).code)\n      .toMatchInlineSnapshot(`\n        \"const { ssrRenderStyle: _ssrRenderStyle, ssrRenderAttrs: _ssrRenderAttrs } = require(\"vue/server-renderer\")\n\n        return function ssrRender(_ctx, _push, _parent, _attrs) {\n          _push(\\`<div\\${\n            _ssrRenderAttrs(_attrs)\n          }><div style=\"\\${\n            _ssrRenderStyle([\n              {\"display\":\"flex\"},\n              (_ctx.foo) ? null : { display: \"none\" }\n            ])\n          }\"></div></div>\\`)\n        }\"\n      `)\n  })\n\n  test('with v-bind', () => {\n    expect(\n      compileWithWrapper(\n        `<div v-bind=\"baz\" style=\"color:red\" :style=\"{ fontSize: 14 }\" v-show=\"foo\"/>`,\n      ).code,\n    ).toMatchInlineSnapshot(`\n      \"const { mergeProps: _mergeProps } = require(\"vue\")\n      const { ssrRenderAttrs: _ssrRenderAttrs } = require(\"vue/server-renderer\")\n\n      return function ssrRender(_ctx, _push, _parent, _attrs) {\n        _push(\\`<div\\${\n          _ssrRenderAttrs(_attrs)\n        }><div\\${\n          _ssrRenderAttrs(_mergeProps(_ctx.baz, {\n            style: [\n              {\"color\":\"red\"},\n              { fontSize: 14 },\n              (_ctx.foo) ? null : { display: \"none\" }\n            ]\n          }))\n        }></div></div>\\`)\n      }\"\n    `)\n  })\n})\n"
  },
  {
    "path": "packages/compiler-ssr/__tests__/utils.ts",
    "content": "import { compile } from '../src'\n\nexport function getCompiledString(src: string): string {\n  // Wrap src template in a root div so that it doesn't get injected\n  // fallthrough attr. This results in less noise in generated snapshots\n  // but also means this util can only be used for non-root cases.\n  const { code } = compile(`<div>${src}</div>`)\n  const match = code.match(\n    /_push\\(\\`<div\\${\\s*_ssrRenderAttrs\\(_attrs\\)\\s*}>([^]*)<\\/div>\\`\\)/,\n  )\n\n  if (!match) {\n    throw new Error(`Unexpected compile result:\\n${code}`)\n  }\n\n  return `\\`${match[1]}\\``\n}\n"
  },
  {
    "path": "packages/compiler-ssr/package.json",
    "content": "{\n  \"name\": \"@vue/compiler-ssr\",\n  \"version\": \"3.5.30\",\n  \"description\": \"@vue/compiler-ssr\",\n  \"main\": \"dist/compiler-ssr.cjs.js\",\n  \"types\": \"dist/compiler-ssr.d.ts\",\n  \"files\": [\n    \"dist\"\n  ],\n  \"buildOptions\": {\n    \"prod\": false,\n    \"formats\": [\n      \"cjs\"\n    ]\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/vuejs/core.git\",\n    \"directory\": \"packages/compiler-ssr\"\n  },\n  \"keywords\": [\n    \"vue\"\n  ],\n  \"author\": \"Evan You\",\n  \"license\": \"MIT\",\n  \"bugs\": {\n    \"url\": \"https://github.com/vuejs/core/issues\"\n  },\n  \"homepage\": \"https://github.com/vuejs/core/tree/main/packages/compiler-ssr#readme\",\n  \"dependencies\": {\n    \"@vue/shared\": \"workspace:*\",\n    \"@vue/compiler-dom\": \"workspace:*\"\n  }\n}\n"
  },
  {
    "path": "packages/compiler-ssr/src/errors.ts",
    "content": "import {\n  type CompilerError,\n  DOMErrorCodes,\n  type SourceLocation,\n  createCompilerError,\n} from '@vue/compiler-dom'\n\nexport interface SSRCompilerError extends CompilerError {\n  code: SSRErrorCodes\n}\n\nexport function createSSRCompilerError(\n  code: SSRErrorCodes,\n  loc?: SourceLocation,\n) {\n  return createCompilerError(code, loc, SSRErrorMessages) as SSRCompilerError\n}\n\nexport enum SSRErrorCodes {\n  X_SSR_UNSAFE_ATTR_NAME = 65 /* DOMErrorCodes.__EXTEND_POINT__ */,\n  X_SSR_NO_TELEPORT_TARGET,\n  X_SSR_INVALID_AST_NODE,\n}\n\nif (__TEST__) {\n  // esbuild cannot infer enum increments if first value is from another\n  // file, so we have to manually keep them in sync. this check ensures it\n  // errors out if there are collisions.\n  if (SSRErrorCodes.X_SSR_UNSAFE_ATTR_NAME < DOMErrorCodes.__EXTEND_POINT__) {\n    throw new Error(\n      `SSRErrorCodes need to be updated to ${\n        DOMErrorCodes.__EXTEND_POINT__\n      } to match extension point from core DOMErrorCodes.`,\n    )\n  }\n}\n\nexport const SSRErrorMessages: { [code: number]: string } = {\n  [SSRErrorCodes.X_SSR_UNSAFE_ATTR_NAME]: `Unsafe attribute name for SSR.`,\n  [SSRErrorCodes.X_SSR_NO_TELEPORT_TARGET]: `Missing the 'to' prop on teleport element.`,\n  [SSRErrorCodes.X_SSR_INVALID_AST_NODE]: `Invalid AST node during SSR transform.`,\n}\n"
  },
  {
    "path": "packages/compiler-ssr/src/index.ts",
    "content": "import {\n  type CodegenResult,\n  type CompilerOptions,\n  type RootNode,\n  baseParse,\n  generate,\n  noopDirectiveTransform,\n  parserOptions,\n  trackSlotScopes,\n  trackVForSlotScopes,\n  transform,\n  transformBind,\n  transformExpression,\n  transformOn,\n  transformStyle,\n  transformVBindShorthand,\n} from '@vue/compiler-dom'\nimport { ssrCodegenTransform } from './ssrCodegenTransform'\nimport { ssrTransformElement } from './transforms/ssrTransformElement'\nimport {\n  rawOptionsMap,\n  ssrTransformComponent,\n} from './transforms/ssrTransformComponent'\nimport { ssrTransformSlotOutlet } from './transforms/ssrTransformSlotOutlet'\nimport { ssrTransformIf } from './transforms/ssrVIf'\nimport { ssrTransformFor } from './transforms/ssrVFor'\nimport { ssrTransformModel } from './transforms/ssrVModel'\nimport { ssrTransformShow } from './transforms/ssrVShow'\nimport { ssrInjectFallthroughAttrs } from './transforms/ssrInjectFallthroughAttrs'\nimport { ssrInjectCssVars } from './transforms/ssrInjectCssVars'\n\nexport function compile(\n  source: string | RootNode,\n  options: CompilerOptions = {},\n): CodegenResult {\n  options = {\n    ...options,\n    ...parserOptions,\n    ssr: true,\n    inSSR: true,\n    scopeId: options.mode === 'function' ? null : options.scopeId,\n    // always prefix since compiler-ssr doesn't have size concern\n    prefixIdentifiers: true,\n    // disable optimizations that are unnecessary for ssr\n    cacheHandlers: false,\n    hoistStatic: false,\n  }\n\n  const ast = typeof source === 'string' ? baseParse(source, options) : source\n\n  // Save raw options for AST. This is needed when performing sub-transforms\n  // on slot vnode branches.\n  rawOptionsMap.set(ast, options)\n\n  transform(ast, {\n    ...options,\n    hoistStatic: false,\n    nodeTransforms: [\n      transformVBindShorthand,\n      ssrTransformIf,\n      ssrTransformFor,\n      trackVForSlotScopes,\n      transformExpression,\n      ssrTransformSlotOutlet,\n      ssrInjectFallthroughAttrs,\n      ssrInjectCssVars,\n      ssrTransformElement,\n      ssrTransformComponent,\n      trackSlotScopes,\n      transformStyle,\n      ...(options.nodeTransforms || []), // user transforms\n    ],\n    directiveTransforms: {\n      // reusing core v-bind\n      bind: transformBind,\n      on: transformOn,\n      // model and show have dedicated SSR handling\n      model: ssrTransformModel,\n      show: ssrTransformShow,\n      // the following are ignored during SSR\n      // on: noopDirectiveTransform,\n      cloak: noopDirectiveTransform,\n      once: noopDirectiveTransform,\n      memo: noopDirectiveTransform,\n      ...(options.directiveTransforms || {}), // user transforms\n    },\n  })\n\n  // traverse the template AST and convert into SSR codegen AST\n  // by replacing ast.codegenNode.\n  ssrCodegenTransform(ast, options)\n\n  return generate(ast, options)\n}\n"
  },
  {
    "path": "packages/compiler-ssr/src/runtimeHelpers.ts",
    "content": "import { registerRuntimeHelpers } from '@vue/compiler-dom'\n\nexport const SSR_INTERPOLATE: unique symbol = Symbol(`ssrInterpolate`)\nexport const SSR_RENDER_VNODE: unique symbol = Symbol(`ssrRenderVNode`)\nexport const SSR_RENDER_COMPONENT: unique symbol = Symbol(`ssrRenderComponent`)\nexport const SSR_RENDER_SLOT: unique symbol = Symbol(`ssrRenderSlot`)\nexport const SSR_RENDER_SLOT_INNER: unique symbol = Symbol(`ssrRenderSlotInner`)\nexport const SSR_RENDER_CLASS: unique symbol = Symbol(`ssrRenderClass`)\nexport const SSR_RENDER_STYLE: unique symbol = Symbol(`ssrRenderStyle`)\nexport const SSR_RENDER_ATTRS: unique symbol = Symbol(`ssrRenderAttrs`)\nexport const SSR_RENDER_ATTR: unique symbol = Symbol(`ssrRenderAttr`)\nexport const SSR_RENDER_DYNAMIC_ATTR: unique symbol =\n  Symbol(`ssrRenderDynamicAttr`)\nexport const SSR_RENDER_LIST: unique symbol = Symbol(`ssrRenderList`)\nexport const SSR_INCLUDE_BOOLEAN_ATTR: unique symbol = Symbol(\n  `ssrIncludeBooleanAttr`,\n)\nexport const SSR_LOOSE_EQUAL: unique symbol = Symbol(`ssrLooseEqual`)\nexport const SSR_LOOSE_CONTAIN: unique symbol = Symbol(`ssrLooseContain`)\nexport const SSR_RENDER_DYNAMIC_MODEL: unique symbol = Symbol(\n  `ssrRenderDynamicModel`,\n)\nexport const SSR_GET_DYNAMIC_MODEL_PROPS: unique symbol = Symbol(\n  `ssrGetDynamicModelProps`,\n)\nexport const SSR_RENDER_TELEPORT: unique symbol = Symbol(`ssrRenderTeleport`)\nexport const SSR_RENDER_SUSPENSE: unique symbol = Symbol(`ssrRenderSuspense`)\nexport const SSR_GET_DIRECTIVE_PROPS: unique symbol =\n  Symbol(`ssrGetDirectiveProps`)\n\nexport const ssrHelpers: Record<symbol, string> = {\n  [SSR_INTERPOLATE]: `ssrInterpolate`,\n  [SSR_RENDER_VNODE]: `ssrRenderVNode`,\n  [SSR_RENDER_COMPONENT]: `ssrRenderComponent`,\n  [SSR_RENDER_SLOT]: `ssrRenderSlot`,\n  [SSR_RENDER_SLOT_INNER]: `ssrRenderSlotInner`,\n  [SSR_RENDER_CLASS]: `ssrRenderClass`,\n  [SSR_RENDER_STYLE]: `ssrRenderStyle`,\n  [SSR_RENDER_ATTRS]: `ssrRenderAttrs`,\n  [SSR_RENDER_ATTR]: `ssrRenderAttr`,\n  [SSR_RENDER_DYNAMIC_ATTR]: `ssrRenderDynamicAttr`,\n  [SSR_RENDER_LIST]: `ssrRenderList`,\n  [SSR_INCLUDE_BOOLEAN_ATTR]: `ssrIncludeBooleanAttr`,\n  [SSR_LOOSE_EQUAL]: `ssrLooseEqual`,\n  [SSR_LOOSE_CONTAIN]: `ssrLooseContain`,\n  [SSR_RENDER_DYNAMIC_MODEL]: `ssrRenderDynamicModel`,\n  [SSR_GET_DYNAMIC_MODEL_PROPS]: `ssrGetDynamicModelProps`,\n  [SSR_RENDER_TELEPORT]: `ssrRenderTeleport`,\n  [SSR_RENDER_SUSPENSE]: `ssrRenderSuspense`,\n  [SSR_GET_DIRECTIVE_PROPS]: `ssrGetDirectiveProps`,\n}\n\n// Note: these are helpers imported from @vue/server-renderer\n// make sure the names match!\nregisterRuntimeHelpers(ssrHelpers)\n"
  },
  {
    "path": "packages/compiler-ssr/src/ssrCodegenTransform.ts",
    "content": "import {\n  type BlockStatement,\n  type CallExpression,\n  type CompilerError,\n  type CompilerOptions,\n  ElementTypes,\n  type IfStatement,\n  type JSChildNode,\n  NodeTypes,\n  type RootNode,\n  type TemplateChildNode,\n  type TemplateLiteral,\n  createBlockStatement,\n  createCallExpression,\n  createCompoundExpression,\n  createRoot,\n  createSimpleExpression,\n  createTemplateLiteral,\n  createTransformContext,\n  isText,\n  processExpression,\n} from '@vue/compiler-dom'\nimport { escapeHtml, isString } from '@vue/shared'\nimport { SSR_INTERPOLATE, ssrHelpers } from './runtimeHelpers'\nimport { ssrProcessIf } from './transforms/ssrVIf'\nimport { ssrProcessFor } from './transforms/ssrVFor'\nimport { ssrProcessSlotOutlet } from './transforms/ssrTransformSlotOutlet'\nimport { ssrProcessComponent } from './transforms/ssrTransformComponent'\nimport { ssrProcessElement } from './transforms/ssrTransformElement'\nimport { SSRErrorCodes, createSSRCompilerError } from './errors'\n\n// Because SSR codegen output is completely different from client-side output\n// (e.g. multiple elements can be concatenated into a single template literal\n// instead of each getting a corresponding call), we need to apply an extra\n// transform pass to convert the template AST into a fresh JS AST before\n// passing it to codegen.\n\nexport function ssrCodegenTransform(\n  ast: RootNode,\n  options: CompilerOptions,\n): void {\n  const context = createSSRTransformContext(ast, options)\n\n  // inject SFC <style> CSS variables\n  // we do this instead of inlining the expression to ensure the vars are\n  // only resolved once per render\n  if (options.ssrCssVars) {\n    const cssContext = createTransformContext(createRoot([]), options)\n    const varsExp = processExpression(\n      createSimpleExpression(options.ssrCssVars, false),\n      cssContext,\n    )\n    context.body.push(\n      createCompoundExpression([`const _cssVars = { style: `, varsExp, `}`]),\n    )\n    Array.from(cssContext.helpers.keys()).forEach(helper => {\n      ast.helpers.add(helper)\n    })\n  }\n\n  const isFragment =\n    ast.children.length > 1 && ast.children.some(c => !isText(c))\n  processChildren(ast, context, isFragment)\n  ast.codegenNode = createBlockStatement(context.body)\n\n  // Finalize helpers.\n  // We need to separate helpers imported from 'vue' vs. '@vue/server-renderer'\n  ast.ssrHelpers = Array.from(\n    new Set([\n      ...Array.from(ast.helpers).filter(h => h in ssrHelpers),\n      ...context.helpers,\n    ]),\n  )\n\n  ast.helpers = new Set(Array.from(ast.helpers).filter(h => !(h in ssrHelpers)))\n}\n\nexport interface SSRTransformContext {\n  root: RootNode\n  options: CompilerOptions\n  body: (JSChildNode | IfStatement)[]\n  helpers: Set<symbol>\n  withSlotScopeId: boolean\n  onError: (error: CompilerError) => void\n  helper<T extends symbol>(name: T): T\n  pushStringPart(part: TemplateLiteral['elements'][0]): void\n  pushStatement(statement: IfStatement | CallExpression): void\n}\n\nfunction createSSRTransformContext(\n  root: RootNode,\n  options: CompilerOptions,\n  helpers: Set<symbol> = new Set(),\n  withSlotScopeId = false,\n): SSRTransformContext {\n  const body: BlockStatement['body'] = []\n  let currentString: TemplateLiteral | null = null\n\n  return {\n    root,\n    options,\n    body,\n    helpers,\n    withSlotScopeId,\n    onError:\n      options.onError ||\n      (e => {\n        throw e\n      }),\n    helper<T extends symbol>(name: T): T {\n      helpers.add(name)\n      return name\n    },\n    pushStringPart(part) {\n      if (!currentString) {\n        const currentCall = createCallExpression(`_push`)\n        body.push(currentCall)\n        currentString = createTemplateLiteral([])\n        currentCall.arguments.push(currentString)\n      }\n      const bufferedElements = currentString.elements\n      const lastItem = bufferedElements[bufferedElements.length - 1]\n      if (isString(part) && isString(lastItem)) {\n        bufferedElements[bufferedElements.length - 1] += part\n      } else {\n        bufferedElements.push(part)\n      }\n    },\n    pushStatement(statement) {\n      // close current string\n      currentString = null\n      body.push(statement)\n    },\n  }\n}\n\nfunction createChildContext(\n  parent: SSRTransformContext,\n  withSlotScopeId = parent.withSlotScopeId,\n): SSRTransformContext {\n  // ensure child inherits parent helpers\n  return createSSRTransformContext(\n    parent.root,\n    parent.options,\n    parent.helpers,\n    withSlotScopeId,\n  )\n}\n\ninterface Container {\n  children: TemplateChildNode[]\n}\n\nexport function processChildren(\n  parent: Container,\n  context: SSRTransformContext,\n  asFragment = false,\n  disableNestedFragments = false,\n  disableComment = false,\n): void {\n  if (asFragment) {\n    context.pushStringPart(`<!--[-->`)\n  }\n  const { children } = parent\n  for (let i = 0; i < children.length; i++) {\n    const child = children[i]\n    switch (child.type) {\n      case NodeTypes.ELEMENT:\n        switch (child.tagType) {\n          case ElementTypes.ELEMENT:\n            ssrProcessElement(child, context)\n            break\n          case ElementTypes.COMPONENT:\n            ssrProcessComponent(child, context, parent)\n            break\n          case ElementTypes.SLOT:\n            ssrProcessSlotOutlet(child, context)\n            break\n          case ElementTypes.TEMPLATE:\n            // TODO\n            break\n          default:\n            context.onError(\n              createSSRCompilerError(\n                SSRErrorCodes.X_SSR_INVALID_AST_NODE,\n                (child as any).loc,\n              ),\n            )\n            // make sure we exhaust all possible types\n            const exhaustiveCheck: never = child\n            return exhaustiveCheck\n        }\n        break\n      case NodeTypes.TEXT:\n        context.pushStringPart(escapeHtml(child.content))\n        break\n      case NodeTypes.COMMENT:\n        // no need to escape comment here because the AST can only\n        // contain valid comments.\n        if (!disableComment) {\n          context.pushStringPart(`<!--${child.content}-->`)\n        }\n        break\n      case NodeTypes.INTERPOLATION:\n        context.pushStringPart(\n          createCallExpression(context.helper(SSR_INTERPOLATE), [\n            child.content,\n          ]),\n        )\n        break\n      case NodeTypes.IF:\n        ssrProcessIf(child, context, disableNestedFragments, disableComment)\n        break\n      case NodeTypes.FOR:\n        ssrProcessFor(child, context, disableNestedFragments)\n        break\n      case NodeTypes.IF_BRANCH:\n        // no-op - handled by ssrProcessIf\n        break\n      case NodeTypes.TEXT_CALL:\n      case NodeTypes.COMPOUND_EXPRESSION:\n        // no-op - these two types can never appear as template child node since\n        // `transformText` is not used during SSR compile.\n        break\n      default:\n        context.onError(\n          createSSRCompilerError(\n            SSRErrorCodes.X_SSR_INVALID_AST_NODE,\n            (child as any).loc,\n          ),\n        )\n        // make sure we exhaust all possible types\n        const exhaustiveCheck: never = child\n        return exhaustiveCheck\n    }\n  }\n  if (asFragment) {\n    context.pushStringPart(`<!--]-->`)\n  }\n}\n\nexport function processChildrenAsStatement(\n  parent: Container,\n  parentContext: SSRTransformContext,\n  asFragment = false,\n  withSlotScopeId: boolean = parentContext.withSlotScopeId,\n): BlockStatement {\n  const childContext = createChildContext(parentContext, withSlotScopeId)\n  processChildren(parent, childContext, asFragment)\n  return createBlockStatement(childContext.body)\n}\n"
  },
  {
    "path": "packages/compiler-ssr/src/transforms/ssrInjectCssVars.ts",
    "content": "import {\n  ElementTypes,\n  type NodeTransform,\n  NodeTypes,\n  type RootNode,\n  type TemplateChildNode,\n  createSimpleExpression,\n  findDir,\n  locStub,\n} from '@vue/compiler-dom'\n\nexport const ssrInjectCssVars: NodeTransform = (node, context) => {\n  if (!context.ssrCssVars) {\n    return\n  }\n\n  // _cssVars is initialized once per render function\n  // the code is injected in ssrCodegenTransform when creating the\n  // ssr transform context\n  if (node.type === NodeTypes.ROOT) {\n    context.identifiers._cssVars = 1\n  }\n\n  const parent = context.parent\n  if (!parent || parent.type !== NodeTypes.ROOT) {\n    return\n  }\n\n  if (node.type === NodeTypes.IF_BRANCH) {\n    for (const child of node.children) {\n      injectCssVars(child)\n    }\n  } else {\n    injectCssVars(node)\n  }\n}\n\nfunction injectCssVars(node: RootNode | TemplateChildNode) {\n  if (\n    node.type === NodeTypes.ELEMENT &&\n    (node.tagType === ElementTypes.ELEMENT ||\n      node.tagType === ElementTypes.COMPONENT) &&\n    !findDir(node, 'for')\n  ) {\n    if (node.tag === 'suspense' || node.tag === 'Suspense') {\n      for (const child of node.children) {\n        if (\n          child.type === NodeTypes.ELEMENT &&\n          child.tagType === ElementTypes.TEMPLATE\n        ) {\n          // suspense slot\n          child.children.forEach(injectCssVars)\n        } else {\n          injectCssVars(child)\n        }\n      }\n    } else {\n      node.props.push({\n        type: NodeTypes.DIRECTIVE,\n        name: 'bind',\n        arg: undefined,\n        exp: createSimpleExpression(`_cssVars`, false),\n        modifiers: [],\n        loc: locStub,\n      })\n    }\n  }\n}\n"
  },
  {
    "path": "packages/compiler-ssr/src/transforms/ssrInjectFallthroughAttrs.ts",
    "content": "import {\n  ElementTypes,\n  type NodeTransform,\n  NodeTypes,\n  type ParentNode,\n  type RootNode,\n  type TemplateChildNode,\n  createSimpleExpression,\n  findDir,\n  isCommentOrWhitespace,\n  locStub,\n} from '@vue/compiler-dom'\n\nconst filterChild = (node: ParentNode) =>\n  node.children.filter(n => !isCommentOrWhitespace(n))\n\nconst hasSingleChild = (node: ParentNode): boolean =>\n  filterChild(node).length === 1\n\nexport const ssrInjectFallthroughAttrs: NodeTransform = (node, context) => {\n  // _attrs is provided as a function argument.\n  // mark it as a known identifier so that it doesn't get prefixed by\n  // transformExpression.\n  if (node.type === NodeTypes.ROOT) {\n    context.identifiers._attrs = 1\n  }\n\n  if (\n    node.type === NodeTypes.ELEMENT &&\n    node.tagType === ElementTypes.COMPONENT &&\n    (node.tag === 'transition' ||\n      node.tag === 'Transition' ||\n      node.tag === 'KeepAlive' ||\n      node.tag === 'keep-alive')\n  ) {\n    const rootChildren = filterChild(context.root)\n    if (rootChildren.length === 1 && rootChildren[0] === node) {\n      if (hasSingleChild(node)) {\n        injectFallthroughAttrs(node.children[0])\n      }\n      return\n    }\n  }\n\n  const parent = context.parent\n  if (!parent || parent.type !== NodeTypes.ROOT) {\n    return\n  }\n\n  if (node.type === NodeTypes.IF_BRANCH && hasSingleChild(node)) {\n    // detect cases where the parent v-if is not the only root level node\n    let hasEncounteredIf = false\n    for (const c of filterChild(parent)) {\n      if (\n        c.type === NodeTypes.IF ||\n        (c.type === NodeTypes.ELEMENT && findDir(c, 'if'))\n      ) {\n        // multiple root v-if\n        if (hasEncounteredIf) return\n        hasEncounteredIf = true\n      } else if (\n        // node before v-if\n        !hasEncounteredIf ||\n        // non else nodes\n        !(c.type === NodeTypes.ELEMENT && findDir(c, /else/, true))\n      ) {\n        return\n      }\n    }\n    injectFallthroughAttrs(node.children[0])\n  } else if (hasSingleChild(parent)) {\n    injectFallthroughAttrs(node)\n  }\n}\n\nfunction injectFallthroughAttrs(node: RootNode | TemplateChildNode) {\n  if (\n    node.type === NodeTypes.ELEMENT &&\n    (node.tagType === ElementTypes.ELEMENT ||\n      node.tagType === ElementTypes.COMPONENT) &&\n    !findDir(node, 'for')\n  ) {\n    node.props.push({\n      type: NodeTypes.DIRECTIVE,\n      name: 'bind',\n      arg: undefined,\n      exp: createSimpleExpression(`_attrs`, false),\n      modifiers: [],\n      loc: locStub,\n    })\n  }\n}\n"
  },
  {
    "path": "packages/compiler-ssr/src/transforms/ssrTransformComponent.ts",
    "content": "import {\n  CREATE_VNODE,\n  type CallExpression,\n  type CompilerOptions,\n  type ComponentNode,\n  DOMDirectiveTransforms,\n  DOMNodeTransforms,\n  type DirectiveNode,\n  ElementTypes,\n  type ExpressionNode,\n  type FunctionExpression,\n  type JSChildNode,\n  Namespaces,\n  type NodeTransform,\n  NodeTypes,\n  RESOLVE_DYNAMIC_COMPONENT,\n  type ReturnStatement,\n  type RootNode,\n  SUSPENSE,\n  type SlotFnBuilder,\n  TELEPORT,\n  TRANSITION,\n  TRANSITION_GROUP,\n  type TemplateChildNode,\n  type TemplateNode,\n  type TransformContext,\n  type TransformOptions,\n  buildProps,\n  buildSlots,\n  createCallExpression,\n  createFunctionExpression,\n  createIfStatement,\n  createReturnStatement,\n  createRoot,\n  createSimpleExpression,\n  createTransformContext,\n  getBaseTransformPreset,\n  locStub,\n  resolveComponentType,\n  stringifyExpression,\n  traverseNode,\n} from '@vue/compiler-dom'\nimport { SSR_RENDER_COMPONENT, SSR_RENDER_VNODE } from '../runtimeHelpers'\nimport {\n  type SSRTransformContext,\n  processChildren,\n  processChildrenAsStatement,\n} from '../ssrCodegenTransform'\nimport { ssrProcessTeleport } from './ssrTransformTeleport'\nimport {\n  ssrProcessSuspense,\n  ssrTransformSuspense,\n} from './ssrTransformSuspense'\nimport {\n  ssrProcessTransitionGroup,\n  ssrTransformTransitionGroup,\n} from './ssrTransformTransitionGroup'\nimport { extend, isArray, isObject, isPlainObject, isSymbol } from '@vue/shared'\nimport { buildSSRProps } from './ssrTransformElement'\nimport {\n  ssrProcessTransition,\n  ssrTransformTransition,\n} from './ssrTransformTransition'\n\n// We need to construct the slot functions in the 1st pass to ensure proper\n// scope tracking, but the children of each slot cannot be processed until\n// the 2nd pass, so we store the WIP slot functions in a weakMap during the 1st\n// pass and complete them in the 2nd pass.\nconst wipMap = new WeakMap<ComponentNode, WIPSlotEntry[]>()\n\nconst WIP_SLOT = Symbol()\n\ninterface WIPSlotEntry {\n  type: typeof WIP_SLOT\n  fn: FunctionExpression\n  children: TemplateChildNode[]\n  vnodeBranch: ReturnStatement\n}\n\nconst componentTypeMap = new WeakMap<\n  ComponentNode,\n  string | symbol | CallExpression\n>()\n\n// ssr component transform is done in two phases:\n// In phase 1. we use `buildSlot` to analyze the children of the component into\n// WIP slot functions (it must be done in phase 1 because `buildSlot` relies on\n// the core transform context).\n// In phase 2. we convert the WIP slots from phase 1 into ssr-specific codegen\n// nodes.\nexport const ssrTransformComponent: NodeTransform = (node, context) => {\n  if (\n    node.type !== NodeTypes.ELEMENT ||\n    node.tagType !== ElementTypes.COMPONENT\n  ) {\n    return\n  }\n\n  const component = resolveComponentType(node, context, true /* ssr */)\n  const isDynamicComponent =\n    isObject(component) && component.callee === RESOLVE_DYNAMIC_COMPONENT\n  componentTypeMap.set(node, component)\n\n  if (isSymbol(component)) {\n    if (component === SUSPENSE) {\n      return ssrTransformSuspense(node, context)\n    } else if (component === TRANSITION_GROUP) {\n      return ssrTransformTransitionGroup(node, context)\n    } else if (component === TRANSITION) {\n      return ssrTransformTransition(node, context)\n    }\n    return // other built-in components: fallthrough\n  }\n\n  // Build the fallback vnode-based branch for the component's slots.\n  // We need to clone the node into a fresh copy and use the buildSlots' logic\n  // to get access to the children of each slot. We then compile them with\n  // a child transform pipeline using vnode-based transforms (instead of ssr-\n  // based ones), and save the result branch (a ReturnStatement) in an array.\n  // The branch is retrieved when processing slots again in ssr mode.\n  const vnodeBranches: ReturnStatement[] = []\n  const clonedNode = clone(node)\n\n  return function ssrPostTransformComponent() {\n    // Using the cloned node, build the normal VNode-based branches (for\n    // fallback in case the child is render-fn based). Store them in an array\n    // for later use.\n    if (clonedNode.children.length) {\n      buildSlots(clonedNode, context, (props, vFor, children) => {\n        vnodeBranches.push(\n          createVNodeSlotBranch(props, vFor, children, context),\n        )\n        return createFunctionExpression(undefined)\n      })\n    }\n\n    let propsExp: string | JSChildNode = `null`\n    if (node.props.length) {\n      // note we are not passing ssr: true here because for components, v-on\n      // handlers should still be passed\n      const { props, directives } = buildProps(\n        node,\n        context,\n        undefined,\n        true,\n        isDynamicComponent,\n      )\n      if (props || directives.length) {\n        propsExp = buildSSRProps(props, directives, context)\n      }\n    }\n\n    const wipEntries: WIPSlotEntry[] = []\n    wipMap.set(node, wipEntries)\n\n    const buildSSRSlotFn: SlotFnBuilder = (props, _vForExp, children, loc) => {\n      const param0 = (props && stringifyExpression(props)) || `_`\n      const fn = createFunctionExpression(\n        [param0, `_push`, `_parent`, `_scopeId`],\n        undefined, // no return, assign body later\n        true, // newline\n        true, // isSlot\n        loc,\n      )\n      wipEntries.push({\n        type: WIP_SLOT,\n        fn,\n        children,\n        // also collect the corresponding vnode branch built earlier\n        vnodeBranch: vnodeBranches[wipEntries.length],\n      })\n      return fn\n    }\n\n    const slots = node.children.length\n      ? buildSlots(node, context, buildSSRSlotFn).slots\n      : `null`\n\n    if (typeof component !== 'string') {\n      // dynamic component that resolved to a `resolveDynamicComponent` call\n      // expression - since the resolved result may be a plain element (string)\n      // or a VNode, handle it with `renderVNode`.\n      node.ssrCodegenNode = createCallExpression(\n        context.helper(SSR_RENDER_VNODE),\n        [\n          `_push`,\n          createCallExpression(context.helper(CREATE_VNODE), [\n            component,\n            propsExp,\n            slots,\n          ]),\n          `_parent`,\n        ],\n      )\n    } else {\n      node.ssrCodegenNode = createCallExpression(\n        context.helper(SSR_RENDER_COMPONENT),\n        [component, propsExp, slots, `_parent`],\n      )\n    }\n  }\n}\n\nexport function ssrProcessComponent(\n  node: ComponentNode,\n  context: SSRTransformContext,\n  parent: { children: TemplateChildNode[] },\n): void {\n  const component = componentTypeMap.get(node)!\n  if (!node.ssrCodegenNode) {\n    // this is a built-in component that fell-through.\n    if (component === TELEPORT) {\n      return ssrProcessTeleport(node, context)\n    } else if (component === SUSPENSE) {\n      return ssrProcessSuspense(node, context)\n    } else if (component === TRANSITION_GROUP) {\n      return ssrProcessTransitionGroup(node, context)\n    } else {\n      // real fall-through: Transition / KeepAlive\n      // just render its children.\n      // #5352: if is at root level of a slot, push an empty string.\n      // this does not affect the final output, but avoids all-comment slot\n      // content of being treated as empty by ssrRenderSlot().\n      if ((parent as WIPSlotEntry).type === WIP_SLOT) {\n        context.pushStringPart(``)\n      }\n      if (component === TRANSITION) {\n        return ssrProcessTransition(node, context)\n      }\n      processChildren(node, context)\n    }\n  } else {\n    // finish up slot function expressions from the 1st pass.\n    const wipEntries = wipMap.get(node) || []\n    for (let i = 0; i < wipEntries.length; i++) {\n      const { fn, vnodeBranch } = wipEntries[i]\n      // For each slot, we generate two branches: one SSR-optimized branch and\n      // one normal vnode-based branch. The branches are taken based on the\n      // presence of the 2nd `_push` argument (which is only present if the slot\n      // is called by `_ssrRenderSlot`.\n      fn.body = createIfStatement(\n        createSimpleExpression(`_push`, false),\n        processChildrenAsStatement(\n          wipEntries[i],\n          context,\n          false,\n          true /* withSlotScopeId */,\n        ),\n        vnodeBranch,\n      )\n    }\n\n    // component is inside a slot, inherit slot scope Id\n    if (context.withSlotScopeId) {\n      node.ssrCodegenNode.arguments.push(`_scopeId`)\n    }\n\n    if (typeof component === 'string') {\n      // static component\n      context.pushStatement(\n        createCallExpression(`_push`, [node.ssrCodegenNode]),\n      )\n    } else {\n      // dynamic component (`resolveDynamicComponent` call)\n      // the codegen node is a `renderVNode` call\n      context.pushStatement(node.ssrCodegenNode)\n    }\n  }\n}\n\nexport const rawOptionsMap: WeakMap<RootNode, CompilerOptions> = new WeakMap<\n  RootNode,\n  CompilerOptions\n>()\n\nconst [baseNodeTransforms, baseDirectiveTransforms] =\n  getBaseTransformPreset(true)\nconst vnodeNodeTransforms = [...baseNodeTransforms, ...DOMNodeTransforms]\nconst vnodeDirectiveTransforms = {\n  ...baseDirectiveTransforms,\n  ...DOMDirectiveTransforms,\n}\n\nfunction createVNodeSlotBranch(\n  slotProps: ExpressionNode | undefined,\n  vFor: DirectiveNode | undefined,\n  children: TemplateChildNode[],\n  parentContext: TransformContext,\n): ReturnStatement {\n  // apply a sub-transform using vnode-based transforms.\n  const rawOptions = rawOptionsMap.get(parentContext.root)!\n\n  const subOptions = {\n    ...rawOptions,\n    // overwrite with vnode-based transforms\n    nodeTransforms: [\n      ...vnodeNodeTransforms,\n      ...(rawOptions.nodeTransforms || []),\n    ],\n    directiveTransforms: {\n      ...vnodeDirectiveTransforms,\n      ...(rawOptions.directiveTransforms || {}),\n    },\n  }\n\n  // wrap the children with a wrapper template for proper children treatment.\n  // important: provide v-slot=\"props\" and v-for=\"exp\" on the wrapper for\n  // proper scope analysis\n  const wrapperProps: TemplateNode['props'] = []\n  if (slotProps) {\n    wrapperProps.push({\n      type: NodeTypes.DIRECTIVE,\n      name: 'slot',\n      exp: slotProps,\n      arg: undefined,\n      modifiers: [],\n      loc: locStub,\n    })\n  }\n  if (vFor) {\n    wrapperProps.push(extend({}, vFor))\n  }\n  const wrapperNode: TemplateNode = {\n    type: NodeTypes.ELEMENT,\n    ns: Namespaces.HTML,\n    tag: 'template',\n    tagType: ElementTypes.TEMPLATE,\n    props: wrapperProps,\n    children,\n    loc: locStub,\n    codegenNode: undefined,\n  }\n  subTransform(wrapperNode, subOptions, parentContext)\n  return createReturnStatement(children)\n}\n\nfunction subTransform(\n  node: TemplateChildNode,\n  options: TransformOptions,\n  parentContext: TransformContext,\n) {\n  const childRoot = createRoot([node])\n  const childContext = createTransformContext(childRoot, options)\n  // this sub transform is for vnode fallback branch so it should be handled\n  // like normal render functions\n  childContext.ssr = false\n  // inherit parent scope analysis state\n  childContext.scopes = { ...parentContext.scopes }\n  childContext.identifiers = { ...parentContext.identifiers }\n  childContext.imports = parentContext.imports\n  // traverse\n  traverseNode(childRoot, childContext)\n  // merge helpers/components/directives into parent context\n  ;(['helpers', 'components', 'directives'] as const).forEach(key => {\n    childContext[key].forEach((value: any, helperKey: any) => {\n      if (key === 'helpers') {\n        const parentCount = parentContext.helpers.get(helperKey)\n        if (parentCount === undefined) {\n          parentContext.helpers.set(helperKey, value)\n        } else {\n          parentContext.helpers.set(helperKey, value + parentCount)\n        }\n      } else {\n        ;(parentContext[key] as any).add(value)\n      }\n    })\n  })\n  // imports/hoists are not merged because:\n  // - imports are only used for asset urls and should be consistent between\n  //   node/client branches\n  // - hoists are not enabled for the client branch here\n}\n\nfunction clone(v: any): any {\n  if (isArray(v)) {\n    return v.map(clone)\n  } else if (isPlainObject(v)) {\n    const res: any = {}\n    for (const key in v) {\n      res[key] = clone(v[key as keyof typeof v])\n    }\n    return res\n  } else {\n    return v\n  }\n}\n"
  },
  {
    "path": "packages/compiler-ssr/src/transforms/ssrTransformElement.ts",
    "content": "import {\n  type ArrayExpression,\n  type AttributeNode,\n  type CallExpression,\n  type DirectiveNode,\n  ElementTypes,\n  ErrorCodes,\n  type ExpressionNode,\n  type InterpolationNode,\n  type JSChildNode,\n  MERGE_PROPS,\n  type NodeTransform,\n  NodeTypes,\n  type PlainElementNode,\n  type PropsExpression,\n  type TemplateLiteral,\n  type TextNode,\n  type TransformContext,\n  buildDirectiveArgs,\n  buildProps,\n  createArrayExpression,\n  createAssignmentExpression,\n  createCallExpression,\n  createCompilerError,\n  createCompoundExpression,\n  createConditionalExpression,\n  createInterpolation,\n  createSequenceExpression,\n  createSimpleExpression,\n  createTemplateLiteral,\n  findDir,\n  hasDynamicKeyVBind,\n  isStaticArgOf,\n  isStaticExp,\n} from '@vue/compiler-dom'\nimport {\n  NO,\n  escapeHtml,\n  isBooleanAttr,\n  isBuiltInDirective,\n  isSSRSafeAttrName,\n  propsToAttrMap,\n} from '@vue/shared'\nimport { SSRErrorCodes, createSSRCompilerError } from '../errors'\nimport {\n  SSR_GET_DIRECTIVE_PROPS,\n  SSR_GET_DYNAMIC_MODEL_PROPS,\n  SSR_INCLUDE_BOOLEAN_ATTR,\n  SSR_INTERPOLATE,\n  SSR_RENDER_ATTR,\n  SSR_RENDER_ATTRS,\n  SSR_RENDER_CLASS,\n  SSR_RENDER_DYNAMIC_ATTR,\n  SSR_RENDER_STYLE,\n} from '../runtimeHelpers'\nimport {\n  type SSRTransformContext,\n  processChildren,\n} from '../ssrCodegenTransform'\n\n// for directives with children overwrite (e.g. v-html & v-text), we need to\n// store the raw children so that they can be added in the 2nd pass.\nconst rawChildrenMap = new WeakMap<\n  PlainElementNode,\n  TemplateLiteral['elements'][0]\n>()\n\nexport const ssrTransformElement: NodeTransform = (node, context) => {\n  if (\n    node.type !== NodeTypes.ELEMENT ||\n    node.tagType !== ElementTypes.ELEMENT\n  ) {\n    return\n  }\n\n  return function ssrPostTransformElement() {\n    // element\n    // generate the template literal representing the open tag.\n    const openTag: TemplateLiteral['elements'] = [`<${node.tag}`]\n    // some tags need to be passed to runtime for special checks\n    const needTagForRuntime =\n      node.tag === 'textarea' || node.tag.indexOf('-') > 0\n\n    // v-bind=\"obj\", v-bind:[key] and custom directives can potentially\n    // overwrite other static attrs and can affect final rendering result,\n    // so when they are present we need to bail out to full `renderAttrs`\n    const hasDynamicVBind = hasDynamicKeyVBind(node)\n    const hasCustomDir = node.props.some(\n      p => p.type === NodeTypes.DIRECTIVE && !isBuiltInDirective(p.name),\n    )\n\n    // v-show has a higher priority in ssr\n    const vShowPropIndex = node.props.findIndex(\n      i => i.type === NodeTypes.DIRECTIVE && i.name === 'show',\n    )\n    if (vShowPropIndex !== -1) {\n      const vShowProp = node.props[vShowPropIndex]\n      node.props.splice(vShowPropIndex, 1)\n      node.props.push(vShowProp)\n    }\n\n    const needMergeProps = hasDynamicVBind || hasCustomDir\n    if (needMergeProps) {\n      const { props, directives } = buildProps(\n        node,\n        context,\n        node.props,\n        false /* isComponent */,\n        false /* isDynamicComponent */,\n        true /* ssr */,\n      )\n      if (props || directives.length) {\n        const mergedProps = buildSSRProps(props, directives, context)\n        const propsExp = createCallExpression(\n          context.helper(SSR_RENDER_ATTRS),\n          [mergedProps],\n        )\n\n        if (node.tag === 'textarea') {\n          const existingText = node.children[0] as\n            | TextNode\n            | InterpolationNode\n            | undefined\n          // If interpolation, this is dynamic <textarea> content, potentially\n          // injected by v-model and takes higher priority than v-bind value.\n          // Additionally, directives with content overrides (v-text/v-html)\n          // have higher priority than the merged props.\n          if (\n            !hasContentOverrideDirective(node) &&\n            (!existingText || existingText.type !== NodeTypes.INTERPOLATION)\n          ) {\n            // <textarea> with dynamic v-bind. We don't know if the final props\n            // will contain .value, so we will have to do something special:\n            // assign the merged props to a temp variable, and check whether\n            // it contains value (if yes, render is as children).\n            const tempId = `_temp${context.temps++}`\n            propsExp.arguments = [\n              createAssignmentExpression(\n                createSimpleExpression(tempId, false),\n                mergedProps,\n              ),\n            ]\n            rawChildrenMap.set(\n              node,\n              createCallExpression(context.helper(SSR_INTERPOLATE), [\n                createConditionalExpression(\n                  createSimpleExpression(`\"value\" in ${tempId}`, false),\n                  createSimpleExpression(`${tempId}.value`, false),\n                  createSimpleExpression(\n                    existingText ? existingText.content : ``,\n                    true,\n                  ),\n                  false,\n                ),\n              ]),\n            )\n          }\n        } else if (node.tag === 'input') {\n          // <input v-bind=\"obj\" v-model>\n          // we need to determine the props to render for the dynamic v-model\n          // and merge it with the v-bind expression.\n          const vModel = findVModel(node)\n          if (vModel) {\n            // 1. save the props (san v-model) in a temp variable\n            const tempId = `_temp${context.temps++}`\n            const tempExp = createSimpleExpression(tempId, false)\n            propsExp.arguments = [\n              createSequenceExpression([\n                createAssignmentExpression(tempExp, mergedProps),\n                createCallExpression(context.helper(MERGE_PROPS), [\n                  tempExp,\n                  createCallExpression(\n                    context.helper(SSR_GET_DYNAMIC_MODEL_PROPS),\n                    [\n                      tempExp, // existing props\n                      vModel.exp!, // model\n                    ],\n                  ),\n                ]),\n              ]),\n            ]\n          }\n        } else if (directives.length && !node.children.length) {\n          // v-text/v-html have higher priority than the merged props\n          if (!hasContentOverrideDirective(node)) {\n            const tempId = `_temp${context.temps++}`\n            propsExp.arguments = [\n              createAssignmentExpression(\n                createSimpleExpression(tempId, false),\n                mergedProps,\n              ),\n            ]\n            rawChildrenMap.set(\n              node,\n              createConditionalExpression(\n                createSimpleExpression(`\"textContent\" in ${tempId}`, false),\n                createCallExpression(context.helper(SSR_INTERPOLATE), [\n                  createSimpleExpression(`${tempId}.textContent`, false),\n                ]),\n                createSimpleExpression(`${tempId}.innerHTML ?? ''`, false),\n                false,\n              ),\n            )\n          }\n        }\n\n        if (needTagForRuntime) {\n          propsExp.arguments.push(`\"${node.tag}\"`)\n        }\n\n        openTag.push(propsExp)\n      }\n    }\n\n    // book keeping static/dynamic class merging.\n    let dynamicClassBinding: CallExpression | undefined = undefined\n    let staticClassBinding: string | undefined = undefined\n    // all style bindings are converted to dynamic by transformStyle.\n    // but we need to make sure to merge them.\n    let dynamicStyleBinding: CallExpression | undefined = undefined\n\n    for (let i = 0; i < node.props.length; i++) {\n      const prop = node.props[i]\n      // ignore true-value/false-value on input\n      if (node.tag === 'input' && isTrueFalseValue(prop)) {\n        continue\n      }\n      // special cases with children override\n      if (prop.type === NodeTypes.DIRECTIVE) {\n        if (prop.name === 'html' && prop.exp) {\n          rawChildrenMap.set(\n            node,\n            createCompoundExpression([`(`, prop.exp, `) ?? ''`]),\n          )\n        } else if (prop.name === 'text' && prop.exp) {\n          node.children = [createInterpolation(prop.exp, prop.loc)]\n        } else if (prop.name === 'slot') {\n          context.onError(\n            createCompilerError(ErrorCodes.X_V_SLOT_MISPLACED, prop.loc),\n          )\n        } else if (isTextareaWithValue(node, prop) && prop.exp) {\n          if (!needMergeProps) {\n            node.children = [createInterpolation(prop.exp, prop.loc)]\n          }\n        } else if (!needMergeProps && prop.name !== 'on') {\n          // Directive transforms.\n          const directiveTransform = context.directiveTransforms[prop.name]\n          if (directiveTransform) {\n            const { props, ssrTagParts } = directiveTransform(\n              prop,\n              node,\n              context,\n            )\n            if (ssrTagParts) {\n              openTag.push(...ssrTagParts)\n            }\n            for (let j = 0; j < props.length; j++) {\n              const { key, value } = props[j]\n              if (isStaticExp(key)) {\n                let attrName = key.content\n                // static key attr\n                if (attrName === 'key' || attrName === 'ref') {\n                  continue\n                }\n                if (attrName === 'class') {\n                  openTag.push(\n                    ` class=\"`,\n                    (dynamicClassBinding = createCallExpression(\n                      context.helper(SSR_RENDER_CLASS),\n                      [value],\n                    )),\n                    `\"`,\n                  )\n                } else if (attrName === 'style') {\n                  if (dynamicStyleBinding) {\n                    // already has style binding, merge into it.\n                    mergeCall(dynamicStyleBinding, value)\n                  } else {\n                    openTag.push(\n                      ` style=\"`,\n                      (dynamicStyleBinding = createCallExpression(\n                        context.helper(SSR_RENDER_STYLE),\n                        [value],\n                      )),\n                      `\"`,\n                    )\n                  }\n                } else {\n                  attrName =\n                    node.tag.indexOf('-') > 0\n                      ? attrName // preserve raw name on custom elements\n                      : propsToAttrMap[attrName] || attrName.toLowerCase()\n                  if (isBooleanAttr(attrName)) {\n                    openTag.push(\n                      createConditionalExpression(\n                        createCallExpression(\n                          context.helper(SSR_INCLUDE_BOOLEAN_ATTR),\n                          [value],\n                        ),\n                        createSimpleExpression(' ' + attrName, true),\n                        createSimpleExpression('', true),\n                        false /* no newline */,\n                      ),\n                    )\n                  } else if (isSSRSafeAttrName(attrName)) {\n                    openTag.push(\n                      createCallExpression(context.helper(SSR_RENDER_ATTR), [\n                        key,\n                        value,\n                      ]),\n                    )\n                  } else {\n                    context.onError(\n                      createSSRCompilerError(\n                        SSRErrorCodes.X_SSR_UNSAFE_ATTR_NAME,\n                        key.loc,\n                      ),\n                    )\n                  }\n                }\n              } else {\n                // dynamic key attr\n                // this branch is only encountered for custom directive\n                // transforms that returns properties with dynamic keys\n                const args: CallExpression['arguments'] = [key, value]\n                if (needTagForRuntime) {\n                  args.push(`\"${node.tag}\"`)\n                }\n                openTag.push(\n                  createCallExpression(\n                    context.helper(SSR_RENDER_DYNAMIC_ATTR),\n                    args,\n                  ),\n                )\n              }\n            }\n          }\n        }\n      } else {\n        // special case: value on <textarea>\n        const name = prop.name\n        if (node.tag === 'textarea' && name === 'value' && prop.value) {\n          rawChildrenMap.set(node, escapeHtml(prop.value.content))\n        } else if (!needMergeProps) {\n          if (name === 'key' || name === 'ref') {\n            continue\n          }\n          // static prop\n          if (name === 'class' && prop.value) {\n            staticClassBinding = JSON.stringify(prop.value.content)\n          }\n          openTag.push(\n            ` ${prop.name}` +\n              (prop.value ? `=\"${escapeHtml(prop.value.content)}\"` : ``),\n          )\n        }\n      }\n    }\n\n    // handle co-existence of dynamic + static class bindings\n    if (dynamicClassBinding && staticClassBinding) {\n      mergeCall(dynamicClassBinding, staticClassBinding)\n      removeStaticBinding(openTag, 'class')\n    }\n\n    if (context.scopeId) {\n      openTag.push(` ${context.scopeId}`)\n    }\n\n    node.ssrCodegenNode = createTemplateLiteral(openTag)\n  }\n}\n\nexport function buildSSRProps(\n  props: PropsExpression | undefined,\n  directives: DirectiveNode[],\n  context: TransformContext,\n): JSChildNode {\n  let mergePropsArgs: JSChildNode[] = []\n  if (props) {\n    if (props.type === NodeTypes.JS_CALL_EXPRESSION) {\n      // already a mergeProps call\n      mergePropsArgs = props.arguments as JSChildNode[]\n    } else {\n      mergePropsArgs.push(props)\n    }\n  }\n  if (directives.length) {\n    for (const dir of directives) {\n      mergePropsArgs.push(\n        createCallExpression(context.helper(SSR_GET_DIRECTIVE_PROPS), [\n          `_ctx`,\n          ...buildDirectiveArgs(dir, context).elements,\n        ] as JSChildNode[]),\n      )\n    }\n  }\n\n  return mergePropsArgs.length > 1\n    ? createCallExpression(context.helper(MERGE_PROPS), mergePropsArgs)\n    : mergePropsArgs[0]\n}\n\nfunction isTrueFalseValue(prop: DirectiveNode | AttributeNode) {\n  if (prop.type === NodeTypes.DIRECTIVE) {\n    return (\n      prop.name === 'bind' &&\n      prop.arg &&\n      isStaticExp(prop.arg) &&\n      (prop.arg.content === 'true-value' || prop.arg.content === 'false-value')\n    )\n  } else {\n    return prop.name === 'true-value' || prop.name === 'false-value'\n  }\n}\n\nfunction isTextareaWithValue(\n  node: PlainElementNode,\n  prop: DirectiveNode,\n): boolean {\n  return !!(\n    node.tag === 'textarea' &&\n    prop.name === 'bind' &&\n    isStaticArgOf(prop.arg, 'value')\n  )\n}\n\nfunction mergeCall(call: CallExpression, arg: string | JSChildNode) {\n  const existing = call.arguments[0] as ExpressionNode | ArrayExpression\n  if (existing.type === NodeTypes.JS_ARRAY_EXPRESSION) {\n    existing.elements.push(arg)\n  } else {\n    call.arguments[0] = createArrayExpression([existing, arg])\n  }\n}\n\nfunction removeStaticBinding(\n  tag: TemplateLiteral['elements'],\n  binding: string,\n) {\n  const regExp = new RegExp(`^ ${binding}=\".+\"$`)\n\n  const i = tag.findIndex(e => typeof e === 'string' && regExp.test(e))\n\n  if (i > -1) {\n    tag.splice(i, 1)\n  }\n}\n\nfunction findVModel(node: PlainElementNode): DirectiveNode | undefined {\n  return node.props.find(\n    p => p.type === NodeTypes.DIRECTIVE && p.name === 'model' && p.exp,\n  ) as DirectiveNode | undefined\n}\n\nfunction hasContentOverrideDirective(node: PlainElementNode): boolean {\n  return !!findDir(node, 'text') || !!findDir(node, 'html')\n}\n\nexport function ssrProcessElement(\n  node: PlainElementNode,\n  context: SSRTransformContext,\n): void {\n  const isVoidTag = context.options.isVoidTag || NO\n  const elementsToAdd = node.ssrCodegenNode!.elements\n  for (let j = 0; j < elementsToAdd.length; j++) {\n    context.pushStringPart(elementsToAdd[j])\n  }\n\n  // Handle slot scopeId\n  if (context.withSlotScopeId) {\n    context.pushStringPart(createSimpleExpression(`_scopeId`, false))\n  }\n\n  // close open tag\n  context.pushStringPart(`>`)\n\n  const rawChildren = rawChildrenMap.get(node)\n  if (rawChildren) {\n    context.pushStringPart(rawChildren)\n  } else if (node.children.length) {\n    processChildren(node, context)\n  }\n\n  if (!isVoidTag(node.tag)) {\n    // push closing tag\n    context.pushStringPart(`</${node.tag}>`)\n  }\n}\n"
  },
  {
    "path": "packages/compiler-ssr/src/transforms/ssrTransformSlotOutlet.ts",
    "content": "import {\n  ElementTypes,\n  type NodeTransform,\n  NodeTypes,\n  type SlotOutletNode,\n  TRANSITION,\n  TRANSITION_GROUP,\n  createCallExpression,\n  createFunctionExpression,\n  isSlotOutlet,\n  processSlotOutlet,\n  resolveComponentType,\n} from '@vue/compiler-dom'\nimport { SSR_RENDER_SLOT, SSR_RENDER_SLOT_INNER } from '../runtimeHelpers'\nimport {\n  type SSRTransformContext,\n  processChildrenAsStatement,\n} from '../ssrCodegenTransform'\n\nexport const ssrTransformSlotOutlet: NodeTransform = (node, context) => {\n  if (isSlotOutlet(node)) {\n    const { slotName, slotProps } = processSlotOutlet(node, context)\n\n    const args = [\n      `_ctx.$slots`,\n      slotName,\n      slotProps || `{}`,\n      // fallback content placeholder. will be replaced in the process phase\n      `null`,\n      `_push`,\n      `_parent`,\n    ]\n\n    // inject slot scope id if current template uses :slotted\n    if (context.scopeId && context.slotted !== false) {\n      args.push(`\"${context.scopeId}-s\"`)\n    }\n\n    let method = SSR_RENDER_SLOT\n\n    // #3989, #9933\n    // check if this is a single slot inside a transition wrapper - since\n    // transition/transition-group will unwrap the slot fragment into vnode(s)\n    // at runtime, we need to avoid rendering the slot as a fragment.\n    let parent = context.parent!\n    if (parent) {\n      const children = parent.children\n      // #10743 <slot v-if> in <Transition>\n      if (parent.type === NodeTypes.IF_BRANCH) {\n        parent = context.grandParent!\n      }\n      let componentType\n      if (\n        parent.type === NodeTypes.ELEMENT &&\n        parent.tagType === ElementTypes.COMPONENT &&\n        ((componentType = resolveComponentType(parent, context, true)) ===\n          TRANSITION ||\n          componentType === TRANSITION_GROUP) &&\n        children.filter(c => c.type === NodeTypes.ELEMENT).length === 1\n      ) {\n        method = SSR_RENDER_SLOT_INNER\n        if (!(context.scopeId && context.slotted !== false)) {\n          args.push('null')\n        }\n        args.push('true')\n      }\n    }\n\n    node.ssrCodegenNode = createCallExpression(context.helper(method), args)\n  }\n}\n\nexport function ssrProcessSlotOutlet(\n  node: SlotOutletNode,\n  context: SSRTransformContext,\n): void {\n  const renderCall = node.ssrCodegenNode!\n\n  // has fallback content\n  if (node.children.length) {\n    const fallbackRenderFn = createFunctionExpression([])\n    fallbackRenderFn.body = processChildrenAsStatement(node, context)\n    // _renderSlot(slots, name, props, fallback, ...)\n    renderCall.arguments[3] = fallbackRenderFn\n  }\n\n  // Forwarded <slot/>. Merge slot scope ids\n  if (context.withSlotScopeId) {\n    const slotScopeId = renderCall.arguments[6]\n    renderCall.arguments[6] = slotScopeId\n      ? `${slotScopeId as string} + _scopeId`\n      : `_scopeId`\n  }\n\n  context.pushStatement(node.ssrCodegenNode!)\n}\n"
  },
  {
    "path": "packages/compiler-ssr/src/transforms/ssrTransformSuspense.ts",
    "content": "import {\n  type ComponentNode,\n  type FunctionExpression,\n  type SlotsExpression,\n  type TemplateChildNode,\n  type TransformContext,\n  buildSlots,\n  createCallExpression,\n  createFunctionExpression,\n} from '@vue/compiler-dom'\nimport {\n  type SSRTransformContext,\n  processChildrenAsStatement,\n} from '../ssrCodegenTransform'\nimport { SSR_RENDER_SUSPENSE } from '../runtimeHelpers'\n\nconst wipMap = new WeakMap<ComponentNode, WIPEntry>()\n\ninterface WIPEntry {\n  slotsExp: SlotsExpression\n  wipSlots: Array<{\n    fn: FunctionExpression\n    children: TemplateChildNode[]\n  }>\n}\n\n// phase 1\nexport function ssrTransformSuspense(\n  node: ComponentNode,\n  context: TransformContext,\n) {\n  return (): void => {\n    if (node.children.length) {\n      const wipEntry: WIPEntry = {\n        slotsExp: null!, // to be immediately set\n        wipSlots: [],\n      }\n      wipMap.set(node, wipEntry)\n      wipEntry.slotsExp = buildSlots(\n        node,\n        context,\n        (_props, _vForExp, children, loc) => {\n          const fn = createFunctionExpression(\n            [],\n            undefined, // no return, assign body later\n            true, // newline\n            false, // suspense slots are not treated as normal slots\n            loc,\n          )\n          wipEntry.wipSlots.push({\n            fn,\n            children,\n          })\n          return fn\n        },\n      ).slots\n    }\n  }\n}\n\n// phase 2\nexport function ssrProcessSuspense(\n  node: ComponentNode,\n  context: SSRTransformContext,\n): void {\n  // complete wip slots with ssr code\n  const wipEntry = wipMap.get(node)\n  if (!wipEntry) {\n    return\n  }\n  const { slotsExp, wipSlots } = wipEntry\n  for (let i = 0; i < wipSlots.length; i++) {\n    const slot = wipSlots[i]\n    slot.fn.body = processChildrenAsStatement(slot, context)\n  }\n  // _push(ssrRenderSuspense(slots))\n  context.pushStatement(\n    createCallExpression(context.helper(SSR_RENDER_SUSPENSE), [\n      `_push`,\n      slotsExp,\n    ]),\n  )\n}\n"
  },
  {
    "path": "packages/compiler-ssr/src/transforms/ssrTransformTeleport.ts",
    "content": "import {\n  type ComponentNode,\n  type ExpressionNode,\n  NodeTypes,\n  createCallExpression,\n  createFunctionExpression,\n  createSimpleExpression,\n  findProp,\n} from '@vue/compiler-dom'\nimport {\n  type SSRTransformContext,\n  processChildrenAsStatement,\n} from '../ssrCodegenTransform'\nimport { SSRErrorCodes, createSSRCompilerError } from '../errors'\nimport { SSR_RENDER_TELEPORT } from '../runtimeHelpers'\n\n// Note: this is a 2nd-pass codegen transform.\nexport function ssrProcessTeleport(\n  node: ComponentNode,\n  context: SSRTransformContext,\n): void {\n  const targetProp = findProp(node, 'to')\n  if (!targetProp) {\n    context.onError(\n      createSSRCompilerError(SSRErrorCodes.X_SSR_NO_TELEPORT_TARGET, node.loc),\n    )\n    return\n  }\n\n  let target: ExpressionNode | undefined\n  if (targetProp.type === NodeTypes.ATTRIBUTE) {\n    target =\n      targetProp.value && createSimpleExpression(targetProp.value.content, true)\n  } else {\n    target = targetProp.exp\n  }\n  if (!target) {\n    context.onError(\n      createSSRCompilerError(\n        SSRErrorCodes.X_SSR_NO_TELEPORT_TARGET,\n        targetProp.loc,\n      ),\n    )\n    return\n  }\n\n  const disabledProp = findProp(node, 'disabled', false, true /* allow empty */)\n  const disabled = disabledProp\n    ? disabledProp.type === NodeTypes.ATTRIBUTE\n      ? `true`\n      : disabledProp.exp || `false`\n    : `false`\n\n  const contentRenderFn = createFunctionExpression(\n    [`_push`],\n    undefined, // Body is added later\n    true, // newline\n    false, // isSlot\n    node.loc,\n  )\n  contentRenderFn.body = processChildrenAsStatement(node, context)\n  context.pushStatement(\n    createCallExpression(context.helper(SSR_RENDER_TELEPORT), [\n      `_push`,\n      contentRenderFn,\n      target,\n      disabled,\n      `_parent`,\n    ]),\n  )\n}\n"
  },
  {
    "path": "packages/compiler-ssr/src/transforms/ssrTransformTransition.ts",
    "content": "import {\n  type ComponentNode,\n  NodeTypes,\n  type TransformContext,\n  findProp,\n} from '@vue/compiler-dom'\nimport {\n  type SSRTransformContext,\n  processChildren,\n} from '../ssrCodegenTransform'\n\nconst wipMap = new WeakMap<ComponentNode, Boolean>()\n\nexport function ssrTransformTransition(\n  node: ComponentNode,\n  context: TransformContext,\n) {\n  return (): void => {\n    const appear = findProp(node, 'appear', false, true)\n    wipMap.set(node, !!appear)\n  }\n}\n\nexport function ssrProcessTransition(\n  node: ComponentNode,\n  context: SSRTransformContext,\n): void {\n  // #5351: filter out comment children inside transition\n  node.children = node.children.filter(c => c.type !== NodeTypes.COMMENT)\n\n  const appear = wipMap.get(node)\n  if (appear) {\n    context.pushStringPart(`<template>`)\n    processChildren(node, context, false, true)\n    context.pushStringPart(`</template>`)\n  } else {\n    processChildren(node, context, false, true)\n  }\n}\n"
  },
  {
    "path": "packages/compiler-ssr/src/transforms/ssrTransformTransitionGroup.ts",
    "content": "import {\n  type AttributeNode,\n  type ComponentNode,\n  type DirectiveNode,\n  type JSChildNode,\n  NodeTypes,\n  type TransformContext,\n  buildProps,\n  createCallExpression,\n  findProp,\n} from '@vue/compiler-dom'\nimport { SSR_RENDER_ATTRS } from '../runtimeHelpers'\nimport {\n  type SSRTransformContext,\n  processChildren,\n} from '../ssrCodegenTransform'\nimport { buildSSRProps } from './ssrTransformElement'\n\nconst wipMap = new WeakMap<ComponentNode, WIPEntry>()\n\ninterface WIPEntry {\n  tag: AttributeNode | DirectiveNode\n  propsExp: string | JSChildNode | null\n  scopeId: string | null\n}\n\n// phase 1: build props\nexport function ssrTransformTransitionGroup(\n  node: ComponentNode,\n  context: TransformContext,\n) {\n  return (): void => {\n    const tag = findProp(node, 'tag')\n    if (tag) {\n      const otherProps = node.props.filter(p => p !== tag)\n      const { props, directives } = buildProps(\n        node,\n        context,\n        otherProps,\n        true /* isComponent */,\n        false /* isDynamicComponent */,\n        true /* ssr (skip event listeners) */,\n      )\n      let propsExp = null\n      if (props || directives.length) {\n        propsExp = createCallExpression(context.helper(SSR_RENDER_ATTRS), [\n          buildSSRProps(props, directives, context),\n        ])\n      }\n      wipMap.set(node, {\n        tag,\n        propsExp,\n        scopeId: context.scopeId || null,\n      })\n    }\n  }\n}\n\n// phase 2: process children\nexport function ssrProcessTransitionGroup(\n  node: ComponentNode,\n  context: SSRTransformContext,\n): void {\n  const entry = wipMap.get(node)\n  if (entry) {\n    const { tag, propsExp, scopeId } = entry\n    if (tag.type === NodeTypes.DIRECTIVE) {\n      // dynamic :tag\n      context.pushStringPart(`<`)\n      context.pushStringPart(tag.exp!)\n      if (propsExp) {\n        context.pushStringPart(propsExp)\n      }\n      if (scopeId) {\n        context.pushStringPart(` ${scopeId}`)\n      }\n      context.pushStringPart(`>`)\n\n      processChildren(\n        node,\n        context,\n        false,\n        /**\n         * TransitionGroup has the special runtime behavior of flattening and\n         * concatenating all children into a single fragment (in order for them to\n         * be patched using the same key map) so we need to account for that here\n         * by disabling nested fragment wrappers from being generated.\n         */\n        true,\n        /**\n         * TransitionGroup filters out comment children at runtime and thus\n         * doesn't expect comments to be present during hydration. We need to\n         * account for that by disabling the empty comment that is otherwise\n         * rendered for a falsy v-if that has no v-else specified. (#6715)\n         */\n        true,\n      )\n      context.pushStringPart(`</`)\n      context.pushStringPart(tag.exp!)\n      context.pushStringPart(`>`)\n    } else {\n      // static tag\n      context.pushStringPart(`<${tag.value!.content}`)\n      if (propsExp) {\n        context.pushStringPart(propsExp)\n      }\n      if (scopeId) {\n        context.pushStringPart(` ${scopeId}`)\n      }\n      context.pushStringPart(`>`)\n      processChildren(node, context, false, true, true)\n      context.pushStringPart(`</${tag.value!.content}>`)\n    }\n  } else {\n    // fragment\n    processChildren(node, context, true, true, true)\n  }\n}\n"
  },
  {
    "path": "packages/compiler-ssr/src/transforms/ssrVFor.ts",
    "content": "import {\n  type ForNode,\n  type NodeTransform,\n  NodeTypes,\n  createCallExpression,\n  createForLoopParams,\n  createFunctionExpression,\n  createStructuralDirectiveTransform,\n  processFor,\n} from '@vue/compiler-dom'\nimport {\n  type SSRTransformContext,\n  processChildrenAsStatement,\n} from '../ssrCodegenTransform'\nimport { SSR_RENDER_LIST } from '../runtimeHelpers'\n\n// Plugin for the first transform pass, which simply constructs the AST node\nexport const ssrTransformFor: NodeTransform =\n  createStructuralDirectiveTransform('for', processFor)\n\n// This is called during the 2nd transform pass to construct the SSR-specific\n// codegen nodes.\nexport function ssrProcessFor(\n  node: ForNode,\n  context: SSRTransformContext,\n  disableNestedFragments = false,\n): void {\n  const needFragmentWrapper =\n    !disableNestedFragments &&\n    (node.children.length !== 1 || node.children[0].type !== NodeTypes.ELEMENT)\n  const renderLoop = createFunctionExpression(\n    createForLoopParams(node.parseResult),\n  )\n  renderLoop.body = processChildrenAsStatement(\n    node,\n    context,\n    needFragmentWrapper,\n  )\n  // v-for always renders a fragment unless explicitly disabled\n  if (!disableNestedFragments) {\n    context.pushStringPart(`<!--[-->`)\n  }\n  context.pushStatement(\n    createCallExpression(context.helper(SSR_RENDER_LIST), [\n      node.source,\n      renderLoop,\n    ]),\n  )\n  if (!disableNestedFragments) {\n    context.pushStringPart(`<!--]-->`)\n  }\n}\n"
  },
  {
    "path": "packages/compiler-ssr/src/transforms/ssrVIf.ts",
    "content": "import {\n  type BlockStatement,\n  type IfBranchNode,\n  type IfNode,\n  type NodeTransform,\n  NodeTypes,\n  createBlockStatement,\n  createCallExpression,\n  createIfStatement,\n  createStructuralDirectiveTransform,\n  processIf,\n} from '@vue/compiler-dom'\nimport {\n  type SSRTransformContext,\n  processChildrenAsStatement,\n} from '../ssrCodegenTransform'\n\n// Plugin for the first transform pass, which simply constructs the AST node\nexport const ssrTransformIf: NodeTransform = createStructuralDirectiveTransform(\n  /^(?:if|else|else-if)$/,\n  processIf,\n)\n\n// This is called during the 2nd transform pass to construct the SSR-specific\n// codegen nodes.\nexport function ssrProcessIf(\n  node: IfNode,\n  context: SSRTransformContext,\n  disableNestedFragments = false,\n  disableComment = false,\n): void {\n  const [rootBranch] = node.branches\n  const ifStatement = createIfStatement(\n    rootBranch.condition!,\n    processIfBranch(rootBranch, context, disableNestedFragments),\n  )\n  context.pushStatement(ifStatement)\n\n  let currentIf = ifStatement\n  for (let i = 1; i < node.branches.length; i++) {\n    const branch = node.branches[i]\n    const branchBlockStatement = processIfBranch(\n      branch,\n      context,\n      disableNestedFragments,\n    )\n    if (branch.condition) {\n      // else-if\n      currentIf = currentIf.alternate = createIfStatement(\n        branch.condition,\n        branchBlockStatement,\n      )\n    } else {\n      // else\n      currentIf.alternate = branchBlockStatement\n    }\n  }\n\n  if (!currentIf.alternate && !disableComment) {\n    currentIf.alternate = createBlockStatement([\n      createCallExpression(`_push`, ['`<!---->`']),\n    ])\n  }\n}\n\nfunction processIfBranch(\n  branch: IfBranchNode,\n  context: SSRTransformContext,\n  disableNestedFragments = false,\n): BlockStatement {\n  const { children } = branch\n  const needFragmentWrapper =\n    !disableNestedFragments &&\n    (children.length !== 1 || children[0].type !== NodeTypes.ELEMENT) &&\n    // optimize away nested fragments when the only child is a ForNode\n    !(children.length === 1 && children[0].type === NodeTypes.FOR)\n  return processChildrenAsStatement(branch, context, needFragmentWrapper)\n}\n"
  },
  {
    "path": "packages/compiler-ssr/src/transforms/ssrVModel.ts",
    "content": "import {\n  DOMErrorCodes,\n  type DirectiveTransform,\n  ElementTypes,\n  type ExpressionNode,\n  NodeTypes,\n  type PlainElementNode,\n  type TemplateChildNode,\n  createCallExpression,\n  createConditionalExpression,\n  createDOMCompilerError,\n  createInterpolation,\n  createObjectProperty,\n  createSimpleExpression,\n  findProp,\n  hasDynamicKeyVBind,\n  transformModel,\n} from '@vue/compiler-dom'\nimport {\n  SSR_INCLUDE_BOOLEAN_ATTR,\n  SSR_LOOSE_CONTAIN,\n  SSR_LOOSE_EQUAL,\n  SSR_RENDER_DYNAMIC_MODEL,\n} from '../runtimeHelpers'\nimport type { DirectiveTransformResult } from 'packages/compiler-core/src/transform'\n\nexport const ssrTransformModel: DirectiveTransform = (dir, node, context) => {\n  const model = dir.exp!\n\n  function checkDuplicatedValue() {\n    const value = findProp(node, 'value')\n    if (value) {\n      context.onError(\n        createDOMCompilerError(\n          DOMErrorCodes.X_V_MODEL_UNNECESSARY_VALUE,\n          value.loc,\n        ),\n      )\n    }\n  }\n\n  const processSelectChildren = (children: TemplateChildNode[]) => {\n    children.forEach(child => {\n      if (child.type === NodeTypes.ELEMENT) {\n        processOption(child as PlainElementNode)\n      } else if (child.type === NodeTypes.FOR) {\n        processSelectChildren(child.children)\n      } else if (child.type === NodeTypes.IF) {\n        child.branches.forEach(b => processSelectChildren(b.children))\n      }\n    })\n  }\n\n  function processOption(plainNode: PlainElementNode) {\n    if (plainNode.tag === 'option') {\n      if (plainNode.props.findIndex(p => p.name === 'selected') === -1) {\n        const value = findValueBinding(plainNode)\n        plainNode.ssrCodegenNode!.elements.push(\n          createConditionalExpression(\n            createCallExpression(context.helper(SSR_INCLUDE_BOOLEAN_ATTR), [\n              createConditionalExpression(\n                createCallExpression(`Array.isArray`, [model]),\n                createCallExpression(context.helper(SSR_LOOSE_CONTAIN), [\n                  model,\n                  value,\n                ]),\n                createCallExpression(context.helper(SSR_LOOSE_EQUAL), [\n                  model,\n                  value,\n                ]),\n              ),\n            ]),\n            createSimpleExpression(' selected', true),\n            createSimpleExpression('', true),\n            false /* no newline */,\n          ),\n        )\n      }\n    } else if (plainNode.tag === 'optgroup') {\n      processSelectChildren(plainNode.children)\n    }\n  }\n\n  if (node.tagType === ElementTypes.ELEMENT) {\n    const res: DirectiveTransformResult = { props: [] }\n    if (node.tag === 'input') {\n      const defaultProps = [\n        // default value binding for text type inputs\n        createObjectProperty(`value`, model),\n      ]\n      const type = findProp(node, 'type')\n      if (type) {\n        const value = findValueBinding(node)\n        if (type.type === NodeTypes.DIRECTIVE) {\n          // dynamic type\n          res.ssrTagParts = [\n            createCallExpression(context.helper(SSR_RENDER_DYNAMIC_MODEL), [\n              type.exp!,\n              model,\n              value,\n            ]),\n          ]\n        } else if (type.value) {\n          // static type\n          switch (type.value.content) {\n            case 'radio':\n              res.props = [\n                createObjectProperty(\n                  `checked`,\n                  createCallExpression(context.helper(SSR_LOOSE_EQUAL), [\n                    model,\n                    value,\n                  ]),\n                ),\n              ]\n              break\n            case 'checkbox':\n              const trueValueBinding = findProp(node, 'true-value')\n              if (trueValueBinding) {\n                const trueValue =\n                  trueValueBinding.type === NodeTypes.ATTRIBUTE\n                    ? JSON.stringify(trueValueBinding.value!.content)\n                    : trueValueBinding.exp!\n                res.props = [\n                  createObjectProperty(\n                    `checked`,\n                    createCallExpression(context.helper(SSR_LOOSE_EQUAL), [\n                      model,\n                      trueValue,\n                    ]),\n                  ),\n                ]\n              } else {\n                res.props = [\n                  createObjectProperty(\n                    `checked`,\n                    createConditionalExpression(\n                      createCallExpression(`Array.isArray`, [model]),\n                      createCallExpression(context.helper(SSR_LOOSE_CONTAIN), [\n                        model,\n                        value,\n                      ]),\n                      model,\n                    ),\n                  ),\n                ]\n              }\n              break\n            case 'file':\n              context.onError(\n                createDOMCompilerError(\n                  DOMErrorCodes.X_V_MODEL_ON_FILE_INPUT_ELEMENT,\n                  dir.loc,\n                ),\n              )\n              break\n            default:\n              checkDuplicatedValue()\n              res.props = defaultProps\n              break\n          }\n        }\n      } else if (hasDynamicKeyVBind(node)) {\n        // dynamic type due to dynamic v-bind\n        // NOOP, handled in ssrTransformElement due to need to rewrite\n        // the entire props expression\n      } else {\n        // text type\n        checkDuplicatedValue()\n        res.props = defaultProps\n      }\n    } else if (node.tag === 'textarea') {\n      checkDuplicatedValue()\n      node.children = [createInterpolation(model, model.loc)]\n    } else if (node.tag === 'select') {\n      processSelectChildren(node.children)\n    } else {\n      context.onError(\n        createDOMCompilerError(\n          DOMErrorCodes.X_V_MODEL_ON_INVALID_ELEMENT,\n          dir.loc,\n        ),\n      )\n    }\n\n    return res\n  } else {\n    // component v-model\n    return transformModel(dir, node, context)\n  }\n}\n\nfunction findValueBinding(node: PlainElementNode): ExpressionNode {\n  const valueBinding = findProp(node, 'value')\n  return valueBinding\n    ? valueBinding.type === NodeTypes.DIRECTIVE\n      ? valueBinding.exp!\n      : createSimpleExpression(valueBinding.value!.content, true)\n    : createSimpleExpression(`null`, false)\n}\n"
  },
  {
    "path": "packages/compiler-ssr/src/transforms/ssrVShow.ts",
    "content": "import {\n  DOMErrorCodes,\n  type DirectiveTransform,\n  createConditionalExpression,\n  createDOMCompilerError,\n  createObjectExpression,\n  createObjectProperty,\n  createSimpleExpression,\n} from '@vue/compiler-dom'\n\nexport const ssrTransformShow: DirectiveTransform = (dir, node, context) => {\n  if (!dir.exp) {\n    context.onError(\n      createDOMCompilerError(DOMErrorCodes.X_V_SHOW_NO_EXPRESSION),\n    )\n  }\n  return {\n    props: [\n      createObjectProperty(\n        `style`,\n        createConditionalExpression(\n          dir.exp!,\n          createSimpleExpression(`null`, false),\n          createObjectExpression([\n            createObjectProperty(\n              `display`,\n              createSimpleExpression(`none`, true),\n            ),\n          ]),\n          false /* no newline */,\n        ),\n      ),\n    ],\n  }\n}\n"
  },
  {
    "path": "packages/global.d.ts",
    "content": "// Global compile-time constants\ndeclare var __DEV__: boolean\ndeclare var __TEST__: boolean\ndeclare var __BROWSER__: boolean\ndeclare var __GLOBAL__: boolean\ndeclare var __ESM_BUNDLER__: boolean\ndeclare var __ESM_BROWSER__: boolean\ndeclare var __CJS__: boolean\ndeclare var __SSR__: boolean\ndeclare var __VERSION__: string\ndeclare var __COMPAT__: boolean\n\n// Feature flags\ndeclare var __FEATURE_OPTIONS_API__: boolean\ndeclare var __FEATURE_PROD_DEVTOOLS__: boolean\ndeclare var __FEATURE_SUSPENSE__: boolean\ndeclare var __FEATURE_PROD_HYDRATION_MISMATCH_DETAILS__: boolean\n\ndeclare module '*.vue' {}\n\ndeclare module 'estree-walker' {\n  export function walk<T>(\n    root: T,\n    options: {\n      enter?: (node: T, parent: T | null) => any\n      leave?: (node: T, parent: T | null) => any\n      exit?: (node: T) => any\n    } & ThisType<{ skip: () => void }>,\n  )\n}\n\ndeclare interface String {\n  /**\n   * @deprecated Please use String.prototype.slice instead of String.prototype.substring in the repository.\n   */\n  substring(start: number, end?: number): string\n}\n"
  },
  {
    "path": "packages/reactivity/LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2018-present, Yuxi (Evan) You\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "packages/reactivity/README.md",
    "content": "# @vue/reactivity\n\n## Usage Note\n\nThis package is inlined into Global & Browser ESM builds of user-facing renderers (e.g. `@vue/runtime-dom`), but also published as a package that can be used standalone. The standalone build should not be used alongside a pre-bundled build of a user-facing renderer, as they will have different internal storage for reactivity connections. A user-facing renderer should re-export all APIs from this package.\n\nFor full exposed APIs, see `src/index.ts`.\n\n## Credits\n\nThe implementation of this module is inspired by the following prior art in the JavaScript ecosystem:\n\n- [Meteor Tracker](https://docs.meteor.com/api/tracker.html)\n- [nx-js/observer-util](https://github.com/nx-js/observer-util)\n- [salesforce/observable-membrane](https://github.com/salesforce/observable-membrane)\n\n## Caveats\n\n- Built-in objects are not observed except for `Array`, `Map`, `WeakMap`, `Set` and `WeakSet`.\n"
  },
  {
    "path": "packages/reactivity/__benchmarks__/computed.bench.ts",
    "content": "import { bench, describe } from 'vitest'\nimport type { ComputedRef, Ref } from '../src'\nimport { computed, effect, ref } from '../dist/reactivity.esm-browser.prod'\n\ndeclare module '../dist/reactivity.esm-browser.prod' {\n  function computed(...args: any[]): any\n}\n\ndescribe('computed', () => {\n  bench('create computed', () => {\n    computed(() => 100)\n  })\n\n  {\n    const v = ref(100)\n    computed(() => v.value * 2)\n    let i = 0\n    bench(\"write ref, don't read computed (without effect)\", () => {\n      v.value = i++\n    })\n  }\n\n  {\n    const v = ref(100)\n    const c = computed(() => {\n      return v.value * 2\n    })\n    effect(() => c.value)\n    let i = 0\n    bench(\"write ref, don't read computed (with effect)\", () => {\n      v.value = i++\n    })\n  }\n\n  {\n    const v = ref(100)\n    const c = computed(() => {\n      return v.value * 2\n    })\n    let i = 0\n    bench('write ref, read computed (without effect)', () => {\n      v.value = i++\n      c.value\n    })\n  }\n\n  {\n    const v = ref(100)\n    const c = computed(() => {\n      return v.value * 2\n    })\n    effect(() => c.value)\n    let i = 0\n    bench('write ref, read computed (with effect)', () => {\n      v.value = i++\n      c.value\n    })\n  }\n\n  {\n    const v = ref(100)\n    const computeds: ComputedRef<number>[] = []\n    for (let i = 0, n = 1000; i < n; i++) {\n      const c = computed(() => {\n        return v.value * 2\n      })\n      computeds.push(c)\n    }\n    let i = 0\n    bench(\"write ref, don't read 1000 computeds (without effect)\", () => {\n      v.value = i++\n    })\n  }\n\n  {\n    const v = ref(100)\n    const computeds: ComputedRef<number>[] = []\n    for (let i = 0, n = 1000; i < n; i++) {\n      const c = computed(() => {\n        return v.value * 2\n      })\n      effect(() => c.value)\n      computeds.push(c)\n    }\n    let i = 0\n    bench(\n      \"write ref, don't read 1000 computeds (with multiple effects)\",\n      () => {\n        v.value = i++\n      },\n    )\n  }\n\n  {\n    const v = ref(100)\n    const computeds: ComputedRef<number>[] = []\n    for (let i = 0, n = 1000; i < n; i++) {\n      const c = computed(() => {\n        return v.value * 2\n      })\n      computeds.push(c)\n    }\n    effect(() => {\n      for (let i = 0; i < 1000; i++) {\n        computeds[i].value\n      }\n    })\n    let i = 0\n    bench(\"write ref, don't read 1000 computeds (with single effect)\", () => {\n      v.value = i++\n    })\n  }\n\n  {\n    const v = ref(100)\n    const computeds: ComputedRef<number>[] = []\n    for (let i = 0, n = 1000; i < n; i++) {\n      const c = computed(() => {\n        return v.value * 2\n      })\n      computeds.push(c)\n    }\n    let i = 0\n    bench('write ref, read 1000 computeds (no effect)', () => {\n      v.value = i++\n      computeds.forEach(c => c.value)\n    })\n  }\n\n  {\n    const v = ref(100)\n    const computeds: ComputedRef<number>[] = []\n    for (let i = 0, n = 1000; i < n; i++) {\n      const c = computed(() => {\n        return v.value * 2\n      })\n      effect(() => c.value)\n      computeds.push(c)\n    }\n    let i = 0\n    bench('write ref, read 1000 computeds (with multiple effects)', () => {\n      v.value = i++\n      computeds.forEach(c => c.value)\n    })\n  }\n\n  {\n    const v = ref(100)\n    const computeds: ComputedRef<number>[] = []\n    for (let i = 0, n = 1000; i < n; i++) {\n      const c = computed(() => {\n        return v.value * 2\n      })\n      effect(() => c.value)\n      computeds.push(c)\n    }\n    effect(() => {\n      for (let i = 0; i < 1000; i++) {\n        computeds[i].value\n      }\n    })\n    let i = 0\n    bench('write ref, read 1000 computeds (with single effect)', () => {\n      v.value = i++\n      computeds.forEach(c => c.value)\n    })\n  }\n\n  {\n    const refs: Ref<number>[] = []\n    for (let i = 0, n = 1000; i < n; i++) {\n      refs.push(ref(i))\n    }\n    const c = computed(() => {\n      let total = 0\n      refs.forEach(ref => (total += ref.value))\n      return total\n    })\n    let i = 0\n    const n = refs.length\n    bench('1000 refs, read 1 computed (without effect)', () => {\n      refs[i++ % n].value++\n      c.value\n    })\n  }\n\n  {\n    const refs: Ref<number>[] = []\n    for (let i = 0, n = 1000; i < n; i++) {\n      refs.push(ref(i))\n    }\n    const c = computed(() => {\n      let total = 0\n      refs.forEach(ref => (total += ref.value))\n      return total\n    })\n    effect(() => c.value)\n    let i = 0\n    const n = refs.length\n    bench('1000 refs, read 1 computed (with effect)', () => {\n      refs[i++ % n].value++\n      c.value\n    })\n  }\n})\n"
  },
  {
    "path": "packages/reactivity/__benchmarks__/effect.bench.ts",
    "content": "import { bench, describe } from 'vitest'\nimport type { Ref } from '../src'\nimport { effect, ref } from '../dist/reactivity.esm-browser.prod'\n\ndescribe('effect', () => {\n  {\n    let i = 0\n    const n = ref(0)\n    effect(() => n.value)\n    bench('single ref invoke', () => {\n      n.value = i++\n    })\n  }\n\n  function benchEffectCreate(size: number) {\n    bench(`create an effect that tracks ${size} refs`, () => {\n      const refs: Ref[] = []\n      for (let i = 0; i < size; i++) {\n        refs.push(ref(i))\n      }\n      effect(() => {\n        for (let i = 0; i < size; i++) {\n          refs[i].value\n        }\n      })\n    })\n  }\n\n  benchEffectCreate(1)\n  benchEffectCreate(10)\n  benchEffectCreate(100)\n  benchEffectCreate(1000)\n\n  function benchEffectCreateAndStop(size: number) {\n    bench(`create and stop an effect that tracks ${size} refs`, () => {\n      const refs: Ref[] = []\n      for (let i = 0; i < size; i++) {\n        refs.push(ref(i))\n      }\n      const e = effect(() => {\n        for (let i = 0; i < size; i++) {\n          refs[i].value\n        }\n      })\n      e.effect.stop()\n    })\n  }\n\n  benchEffectCreateAndStop(1)\n  benchEffectCreateAndStop(10)\n  benchEffectCreateAndStop(100)\n  benchEffectCreateAndStop(1000)\n\n  function benchWithRefs(size: number) {\n    let j = 0\n    const refs: Ref[] = []\n    for (let i = 0; i < size; i++) {\n      refs.push(ref(i))\n    }\n    effect(() => {\n      for (let i = 0; i < size; i++) {\n        refs[i].value\n      }\n    })\n    bench(`1 effect, mutate ${size} refs`, () => {\n      for (let i = 0; i < size; i++) {\n        refs[i].value = i + j++\n      }\n    })\n  }\n\n  benchWithRefs(10)\n  benchWithRefs(100)\n  benchWithRefs(1000)\n\n  function benchWithBranches(size: number) {\n    const toggle = ref(true)\n    const refs: Ref[] = []\n    for (let i = 0; i < size; i++) {\n      refs.push(ref(i))\n    }\n    effect(() => {\n      if (toggle.value) {\n        for (let i = 0; i < size; i++) {\n          refs[i].value\n        }\n      }\n    })\n    bench(`${size} refs branch toggle`, () => {\n      toggle.value = !toggle.value\n    })\n  }\n\n  benchWithBranches(10)\n  benchWithBranches(100)\n  benchWithBranches(1000)\n\n  function benchMultipleEffects(size: number) {\n    let i = 0\n    const n = ref(0)\n    for (let i = 0; i < size; i++) {\n      effect(() => n.value)\n    }\n    bench(`1 ref invoking ${size} effects`, () => {\n      n.value = i++\n    })\n  }\n\n  benchMultipleEffects(10)\n  benchMultipleEffects(100)\n  benchMultipleEffects(1000)\n})\n"
  },
  {
    "path": "packages/reactivity/__benchmarks__/reactiveArray.bench.ts",
    "content": "import { bench } from 'vitest'\nimport {\n  effect,\n  reactive,\n  shallowReadArray,\n} from '../dist/reactivity.esm-browser.prod'\n\nfor (let amount = 1e1; amount < 1e4; amount *= 10) {\n  {\n    const rawArray: number[] = []\n    for (let i = 0, n = amount; i < n; i++) {\n      rawArray.push(i)\n    }\n    const arr = reactive(rawArray)\n\n    bench(`track for loop, ${amount} elements`, () => {\n      let sum = 0\n      effect(() => {\n        for (let i = 0; i < arr.length; i++) {\n          sum += arr[i]\n        }\n      })\n    })\n  }\n\n  {\n    const rawArray: number[] = []\n    for (let i = 0, n = amount; i < n; i++) {\n      rawArray.push(i)\n    }\n    const arr = reactive(rawArray)\n\n    bench(`track manual reactiveReadArray, ${amount} elements`, () => {\n      let sum = 0\n      effect(() => {\n        const raw = shallowReadArray(arr)\n        for (let i = 0; i < raw.length; i++) {\n          sum += raw[i]\n        }\n      })\n    })\n  }\n\n  {\n    const rawArray: number[] = []\n    for (let i = 0, n = amount; i < n; i++) {\n      rawArray.push(i)\n    }\n    const arr = reactive(rawArray)\n\n    bench(`track iteration, ${amount} elements`, () => {\n      let sum = 0\n      effect(() => {\n        for (let x of arr) {\n          sum += x\n        }\n      })\n    })\n  }\n\n  {\n    const rawArray: number[] = []\n    for (let i = 0, n = amount; i < n; i++) {\n      rawArray.push(i)\n    }\n    const arr = reactive(rawArray)\n\n    bench(`track forEach, ${amount} elements`, () => {\n      let sum = 0\n      effect(() => {\n        arr.forEach(x => (sum += x))\n      })\n    })\n  }\n\n  {\n    const rawArray: number[] = []\n    for (let i = 0, n = amount; i < n; i++) {\n      rawArray.push(i)\n    }\n    const arr = reactive(rawArray)\n\n    bench(`track reduce, ${amount} elements`, () => {\n      let sum = 0\n      effect(() => {\n        sum = arr.reduce((v, a) => a + v, 0)\n      })\n    })\n  }\n\n  {\n    const rawArray: any[] = []\n    for (let i = 0, n = amount; i < n; i++) {\n      rawArray.push(i)\n    }\n    const r = reactive(rawArray)\n    effect(() => r.reduce((v, a) => a + v, 0))\n\n    bench(\n      `trigger index mutation (1st only), tracked with reduce, ${amount} elements`,\n      () => {\n        r[0]++\n      },\n    )\n  }\n\n  {\n    const rawArray: any[] = []\n    for (let i = 0, n = amount; i < n; i++) {\n      rawArray.push(i)\n    }\n    const r = reactive(rawArray)\n    effect(() => r.reduce((v, a) => a + v, 0))\n\n    bench(\n      `trigger index mutation (all), tracked with reduce, ${amount} elements`,\n      () => {\n        for (let i = 0, n = r.length; i < n; i++) {\n          r[i]++\n        }\n      },\n    )\n  }\n\n  {\n    const rawArray: number[] = []\n    for (let i = 0, n = amount; i < n; i++) {\n      rawArray.push(i)\n    }\n    const arr = reactive(rawArray)\n    let sum = 0\n    effect(() => {\n      for (let x of arr) {\n        sum += x\n      }\n    })\n\n    bench(`push() trigger, tracked via iteration, ${amount} elements`, () => {\n      arr.push(1)\n    })\n  }\n\n  {\n    const rawArray: number[] = []\n    for (let i = 0, n = amount; i < n; i++) {\n      rawArray.push(i)\n    }\n    const arr = reactive(rawArray)\n    let sum = 0\n    effect(() => {\n      arr.forEach(x => (sum += x))\n    })\n\n    bench(`push() trigger, tracked via forEach, ${amount} elements`, () => {\n      arr.push(1)\n    })\n  }\n}\n"
  },
  {
    "path": "packages/reactivity/__benchmarks__/reactiveMap.bench.ts",
    "content": "import { bench } from 'vitest'\nimport type { ComputedRef } from '../src'\nimport { computed, reactive } from '../dist/reactivity.esm-browser.prod'\n\nfunction createMap(obj: Record<string, any>) {\n  const map = new Map()\n  for (const key in obj) {\n    if (obj.hasOwnProperty(key)) {\n      map.set(key, obj[key])\n    }\n  }\n  return map\n}\n\nbench('create reactive map', () => {\n  reactive(createMap({ a: 1 }))\n})\n\n{\n  let i = 0\n  const r = reactive(createMap({ a: 1 }))\n  bench('write reactive map property', () => {\n    r.set('a', i++)\n  })\n}\n\n{\n  const r = reactive(createMap({ a: 1 }))\n  computed(() => {\n    return r.get('a') * 2\n  })\n  let i = 0\n  bench(\"write reactive map, don't read computed (never invoked)\", () => {\n    r.set('a', i++)\n  })\n}\n\n{\n  const r = reactive(createMap({ a: 1 }))\n  const c = computed(() => {\n    return r.get('a') * 2\n  })\n  c.value\n  let i = 0\n  bench(\"write reactive map, don't read computed (invoked)\", () => {\n    r.set('a', i++)\n  })\n}\n\n{\n  const r = reactive(createMap({ a: 1 }))\n  const c = computed(() => {\n    return r.get('a') * 2\n  })\n  let i = 0\n  bench('write reactive map, read computed', () => {\n    r.set('a', i++)\n    c.value\n  })\n}\n\n{\n  const _m = new Map()\n  for (let i = 0; i < 10000; i++) {\n    _m.set(i, i)\n  }\n  const r = reactive(_m)\n  const c = computed(() => {\n    let total = 0\n    r.forEach((value, key) => {\n      total += value\n    })\n    return total\n  })\n  bench(\"write reactive map (10'000 items), read computed\", () => {\n    r.set(5000, r.get(5000) + 1)\n    c.value\n  })\n}\n\n{\n  const r = reactive(createMap({ a: 1 }))\n  const computeds: any[] = []\n  for (let i = 0, n = 1000; i < n; i++) {\n    const c = computed(() => {\n      return r.get('a') * 2\n    })\n    computeds.push(c)\n  }\n  let i = 0\n  bench(\"write reactive map, don't read 1000 computeds (never invoked)\", () => {\n    r.set('a', i++)\n  })\n}\n\n{\n  const r = reactive(createMap({ a: 1 }))\n  const computeds: any[] = []\n  for (let i = 0, n = 1000; i < n; i++) {\n    const c = computed(() => {\n      return r.get('a') * 2\n    })\n    c.value\n    computeds.push(c)\n  }\n  let i = 0\n  bench(\"write reactive map, don't read 1000 computeds (invoked)\", () => {\n    r.set('a', i++)\n  })\n}\n\n{\n  const r = reactive(createMap({ a: 1 }))\n  const computeds: ComputedRef<number>[] = []\n  for (let i = 0, n = 1000; i < n; i++) {\n    const c = computed(() => {\n      return r.get('a') * 2\n    })\n    computeds.push(c)\n  }\n  let i = 0\n  bench('write reactive map, read 1000 computeds', () => {\n    r.set('a', i++)\n    computeds.forEach(c => c.value)\n  })\n}\n\n{\n  const reactives: Map<any, any>[] = []\n  for (let i = 0, n = 1000; i < n; i++) {\n    reactives.push(reactive(createMap({ a: i })))\n  }\n  const c = computed(() => {\n    let total = 0\n    reactives.forEach(r => (total += r.get('a')))\n    return total\n  })\n  let i = 0\n  const n = reactives.length\n  bench('1000 reactive maps, 1 computed', () => {\n    reactives[i++ % n].set('a', reactives[i++ % n].get('a') + 1)\n    c.value\n  })\n}\n"
  },
  {
    "path": "packages/reactivity/__benchmarks__/reactiveObject.bench.ts",
    "content": "import { bench } from 'vitest'\nimport { reactive } from '../dist/reactivity.esm-browser.prod'\n\nbench('create reactive obj', () => {\n  reactive({ a: 1 })\n})\n\n{\n  const r = reactive({ a: 1 })\n  bench('read reactive obj property', () => {\n    r.a\n  })\n}\n\n{\n  let i = 0\n  const r = reactive({ a: 1 })\n  bench('write reactive obj property', () => {\n    r.a = i++\n  })\n}\n"
  },
  {
    "path": "packages/reactivity/__benchmarks__/ref.bench.ts",
    "content": "import { bench, describe } from 'vitest'\nimport { ref } from '../dist/reactivity.esm-browser.prod'\n\ndescribe('ref', () => {\n  bench('create ref', () => {\n    ref(100)\n  })\n\n  {\n    let i = 0\n    const v = ref(100)\n    bench('write ref', () => {\n      v.value = i++\n    })\n  }\n\n  {\n    const v = ref(100)\n    bench('read ref', () => {\n      v.value\n    })\n  }\n\n  {\n    let i = 0\n    const v = ref(100)\n    bench('write/read ref', () => {\n      v.value = i++\n      v.value\n    })\n  }\n})\n"
  },
  {
    "path": "packages/reactivity/__tests__/collections/Map.spec.ts",
    "content": "import { effect, isReactive, reactive, toRaw } from '../../src'\n\ndescribe('reactivity/collections', () => {\n  function coverCollectionFn(collection: Map<any, any>, fnName: string) {\n    const spy = vi.fn()\n    let proxy = reactive(collection)\n    ;(collection as any)[fnName] = spy\n    return [proxy as any, spy]\n  }\n\n  describe('Map', () => {\n    test('instanceof', () => {\n      const original = new Map()\n      const observed = reactive(original)\n      expect(isReactive(observed)).toBe(true)\n      expect(original).toBeInstanceOf(Map)\n      expect(observed).toBeInstanceOf(Map)\n    })\n\n    it('should observe mutations', () => {\n      let dummy\n      const map = reactive(new Map())\n      effect(() => {\n        dummy = map.get('key')\n      })\n\n      expect(dummy).toBe(undefined)\n      map.set('key', 'value')\n      expect(dummy).toBe('value')\n      map.set('key', 'value2')\n      expect(dummy).toBe('value2')\n      map.delete('key')\n      expect(dummy).toBe(undefined)\n    })\n\n    it('should observe mutations with observed value as key', () => {\n      let dummy\n      const key = reactive({})\n      const value = reactive({})\n      const map = reactive(new Map())\n      effect(() => {\n        dummy = map.get(key)\n      })\n\n      expect(dummy).toBe(undefined)\n      map.set(key, value)\n      expect(dummy).toBe(value)\n      map.delete(key)\n      expect(dummy).toBe(undefined)\n    })\n\n    it('should observe size mutations', () => {\n      let dummy\n      const map = reactive(new Map())\n      effect(() => (dummy = map.size))\n\n      expect(dummy).toBe(0)\n      map.set('key1', 'value')\n      map.set('key2', 'value2')\n      expect(dummy).toBe(2)\n      map.delete('key1')\n      expect(dummy).toBe(1)\n      map.clear()\n      expect(dummy).toBe(0)\n    })\n\n    it('should observe for of iteration', () => {\n      let dummy\n      const map = reactive(new Map())\n      effect(() => {\n        dummy = 0\n        for (let [key, num] of map) {\n          key\n          dummy += num\n        }\n      })\n\n      expect(dummy).toBe(0)\n      map.set('key1', 3)\n      expect(dummy).toBe(3)\n      map.set('key2', 2)\n      expect(dummy).toBe(5)\n      // iteration should track mutation of existing entries (#709)\n      map.set('key1', 4)\n      expect(dummy).toBe(6)\n      map.delete('key1')\n      expect(dummy).toBe(2)\n      map.clear()\n      expect(dummy).toBe(0)\n    })\n\n    it('should observe forEach iteration', () => {\n      let dummy: any\n      const map = reactive(new Map())\n      effect(() => {\n        dummy = 0\n        map.forEach((num: any) => (dummy += num))\n      })\n\n      expect(dummy).toBe(0)\n      map.set('key1', 3)\n      expect(dummy).toBe(3)\n      map.set('key2', 2)\n      expect(dummy).toBe(5)\n      // iteration should track mutation of existing entries (#709)\n      map.set('key1', 4)\n      expect(dummy).toBe(6)\n      map.delete('key1')\n      expect(dummy).toBe(2)\n      map.clear()\n      expect(dummy).toBe(0)\n    })\n\n    it('should observe keys iteration', () => {\n      let dummy\n      const map = reactive(new Map())\n      effect(() => {\n        dummy = 0\n        for (let key of map.keys()) {\n          dummy += key\n        }\n      })\n\n      expect(dummy).toBe(0)\n      map.set(3, 3)\n      expect(dummy).toBe(3)\n      map.set(2, 2)\n      expect(dummy).toBe(5)\n      map.delete(3)\n      expect(dummy).toBe(2)\n      map.clear()\n      expect(dummy).toBe(0)\n    })\n\n    it('should observe values iteration', () => {\n      let dummy\n      const map = reactive(new Map())\n      effect(() => {\n        dummy = 0\n        for (let num of map.values()) {\n          dummy += num\n        }\n      })\n\n      expect(dummy).toBe(0)\n      map.set('key1', 3)\n      expect(dummy).toBe(3)\n      map.set('key2', 2)\n      expect(dummy).toBe(5)\n      // iteration should track mutation of existing entries (#709)\n      map.set('key1', 4)\n      expect(dummy).toBe(6)\n      map.delete('key1')\n      expect(dummy).toBe(2)\n      map.clear()\n      expect(dummy).toBe(0)\n    })\n\n    it('should observe entries iteration', () => {\n      let dummy\n      let dummy2\n      const map = reactive(new Map())\n      effect(() => {\n        dummy = ''\n        dummy2 = 0\n        for (let [key, num] of map.entries()) {\n          dummy += key\n          dummy2 += num\n        }\n      })\n\n      expect(dummy).toBe('')\n      expect(dummy2).toBe(0)\n      map.set('key1', 3)\n      expect(dummy).toBe('key1')\n      expect(dummy2).toBe(3)\n      map.set('key2', 2)\n      expect(dummy).toBe('key1key2')\n      expect(dummy2).toBe(5)\n      // iteration should track mutation of existing entries (#709)\n      map.set('key1', 4)\n      expect(dummy).toBe('key1key2')\n      expect(dummy2).toBe(6)\n      map.delete('key1')\n      expect(dummy).toBe('key2')\n      expect(dummy2).toBe(2)\n      map.clear()\n      expect(dummy).toBe('')\n      expect(dummy2).toBe(0)\n    })\n\n    it('should be triggered by clearing', () => {\n      let dummy\n      const map = reactive(new Map())\n      effect(() => (dummy = map.get('key')))\n\n      expect(dummy).toBe(undefined)\n      map.set('key', 3)\n      expect(dummy).toBe(3)\n      map.clear()\n      expect(dummy).toBe(undefined)\n    })\n\n    it('should not observe custom property mutations', () => {\n      let dummy\n      const map: any = reactive(new Map())\n      effect(() => (dummy = map.customProp))\n\n      expect(dummy).toBe(undefined)\n      map.customProp = 'Hello World'\n      expect(dummy).toBe(undefined)\n    })\n\n    it('should not observe non value changing mutations', () => {\n      let dummy\n      const map = reactive(new Map())\n      const mapSpy = vi.fn(() => (dummy = map.get('key')))\n      effect(mapSpy)\n\n      expect(dummy).toBe(undefined)\n      expect(mapSpy).toHaveBeenCalledTimes(1)\n      map.set('key', undefined)\n      expect(dummy).toBe(undefined)\n      expect(mapSpy).toHaveBeenCalledTimes(2)\n      map.set('key', 'value')\n      expect(dummy).toBe('value')\n      expect(mapSpy).toHaveBeenCalledTimes(3)\n      map.set('key', 'value')\n      expect(dummy).toBe('value')\n      expect(mapSpy).toHaveBeenCalledTimes(3)\n      map.delete('key')\n      expect(dummy).toBe(undefined)\n      expect(mapSpy).toHaveBeenCalledTimes(4)\n      map.delete('key')\n      expect(dummy).toBe(undefined)\n      expect(mapSpy).toHaveBeenCalledTimes(4)\n      map.clear()\n      expect(dummy).toBe(undefined)\n      expect(mapSpy).toHaveBeenCalledTimes(4)\n    })\n\n    it('should not observe raw data', () => {\n      let dummy\n      const map = reactive(new Map())\n      effect(() => (dummy = toRaw(map).get('key')))\n\n      expect(dummy).toBe(undefined)\n      map.set('key', 'Hello')\n      expect(dummy).toBe(undefined)\n      map.delete('key')\n      expect(dummy).toBe(undefined)\n    })\n\n    it('should not pollute original Map with Proxies', () => {\n      const map = new Map()\n      const observed = reactive(map)\n      const value = reactive({})\n      observed.set('key', value)\n      expect(map.get('key')).not.toBe(value)\n      expect(map.get('key')).toBe(toRaw(value))\n    })\n\n    it('should return observable versions of contained values', () => {\n      const observed = reactive(new Map())\n      const value = {}\n      observed.set('key', value)\n      const wrapped = observed.get('key')\n      expect(isReactive(wrapped)).toBe(true)\n      expect(toRaw(wrapped)).toBe(value)\n    })\n\n    it('should observed nested data', () => {\n      const observed = reactive(new Map())\n      observed.set('key', { a: 1 })\n      let dummy\n      effect(() => {\n        dummy = observed.get('key').a\n      })\n      observed.get('key').a = 2\n      expect(dummy).toBe(2)\n    })\n\n    it('should observe nested values in iterations (forEach)', () => {\n      const map = reactive(new Map([[1, { foo: 1 }]]))\n      let dummy: any\n      effect(() => {\n        dummy = 0\n        map.forEach(value => {\n          expect(isReactive(value)).toBe(true)\n          dummy += value.foo\n        })\n      })\n      expect(dummy).toBe(1)\n      map.get(1)!.foo++\n      expect(dummy).toBe(2)\n    })\n\n    it('should observe nested values in iterations (values)', () => {\n      const map = reactive(new Map([[1, { foo: 1 }]]))\n      let dummy: any\n      effect(() => {\n        dummy = 0\n        for (const value of map.values()) {\n          expect(isReactive(value)).toBe(true)\n          dummy += value.foo\n        }\n      })\n      expect(dummy).toBe(1)\n      map.get(1)!.foo++\n      expect(dummy).toBe(2)\n    })\n\n    it('should observe nested values in iterations (entries)', () => {\n      const key = {}\n      const map = reactive(new Map([[key, { foo: 1 }]]))\n      let dummy: any\n      effect(() => {\n        dummy = 0\n        for (const [key, value] of map.entries()) {\n          key\n          expect(isReactive(key)).toBe(true)\n          expect(isReactive(value)).toBe(true)\n          dummy += value.foo\n        }\n      })\n      expect(dummy).toBe(1)\n      map.get(key)!.foo++\n      expect(dummy).toBe(2)\n    })\n\n    it('should observe nested values in iterations (for...of)', () => {\n      const key = {}\n      const map = reactive(new Map([[key, { foo: 1 }]]))\n      let dummy: any\n      effect(() => {\n        dummy = 0\n        for (const [key, value] of map) {\n          key\n          expect(isReactive(key)).toBe(true)\n          expect(isReactive(value)).toBe(true)\n          dummy += value.foo\n        }\n      })\n      expect(dummy).toBe(1)\n      map.get(key)!.foo++\n      expect(dummy).toBe(2)\n    })\n\n    it('should not be trigger when the value and the old value both are NaN', () => {\n      const map = reactive(new Map([['foo', NaN]]))\n      const mapSpy = vi.fn(() => map.get('foo'))\n      effect(mapSpy)\n      map.set('foo', NaN)\n      expect(mapSpy).toHaveBeenCalledTimes(1)\n    })\n\n    it('should work with reactive keys in raw map', () => {\n      const raw = new Map()\n      const key = reactive({})\n      raw.set(key, 1)\n      const map = reactive(raw)\n\n      expect(map.has(key)).toBe(true)\n      expect(map.get(key)).toBe(1)\n\n      expect(map.delete(key)).toBe(true)\n      expect(map.has(key)).toBe(false)\n      expect(map.get(key)).toBeUndefined()\n    })\n\n    it('should track set of reactive keys in raw map', () => {\n      const raw = new Map()\n      const key = reactive({})\n      raw.set(key, 1)\n      const map = reactive(raw)\n\n      let dummy\n      effect(() => {\n        dummy = map.get(key)\n      })\n      expect(dummy).toBe(1)\n\n      map.set(key, 2)\n      expect(dummy).toBe(2)\n    })\n\n    it('should track deletion of reactive keys in raw map', () => {\n      const raw = new Map()\n      const key = reactive({})\n      raw.set(key, 1)\n      const map = reactive(raw)\n\n      let dummy\n      effect(() => {\n        dummy = map.has(key)\n      })\n      expect(dummy).toBe(true)\n\n      map.delete(key)\n      expect(dummy).toBe(false)\n    })\n\n    it('should warn when both raw and reactive versions of the same object is used as key', () => {\n      const raw = new Map()\n      const rawKey = {}\n      const key = reactive(rawKey)\n      raw.set(rawKey, 1)\n      raw.set(key, 1)\n      const map = reactive(raw)\n      map.set(key, 2)\n      expect(\n        `Reactive Map contains both the raw and reactive`,\n      ).toHaveBeenWarned()\n    })\n\n    // #877\n    it('should not trigger key iteration when setting existing keys', () => {\n      const map = reactive(new Map())\n      const spy = vi.fn()\n\n      effect(() => {\n        const keys = []\n        for (const key of map.keys()) {\n          keys.push(key)\n        }\n        spy(keys)\n      })\n\n      expect(spy).toHaveBeenCalledTimes(1)\n      expect(spy.mock.calls[0][0]).toMatchObject([])\n\n      map.set('a', 0)\n      expect(spy).toHaveBeenCalledTimes(2)\n      expect(spy.mock.calls[1][0]).toMatchObject(['a'])\n\n      map.set('b', 0)\n      expect(spy).toHaveBeenCalledTimes(3)\n      expect(spy.mock.calls[2][0]).toMatchObject(['a', 'b'])\n\n      // keys didn't change, should not trigger\n      map.set('b', 1)\n      expect(spy).toHaveBeenCalledTimes(3)\n    })\n\n    it('should trigger Map.has only once for non-reactive keys', () => {\n      const [proxy, spy] = coverCollectionFn(new Map(), 'has')\n      proxy.has('k')\n      expect(spy).toBeCalledTimes(1)\n    })\n\n    it('should trigger Map.set only once for non-reactive keys', () => {\n      const [proxy, spy] = coverCollectionFn(new Map(), 'set')\n      proxy.set('k', 'v')\n      expect(spy).toBeCalledTimes(1)\n    })\n\n    it('should trigger Map.delete only once for non-reactive keys', () => {\n      const [proxy, spy] = coverCollectionFn(new Map(), 'delete')\n      proxy.delete('foo')\n      expect(spy).toBeCalledTimes(1)\n    })\n\n    it('should trigger Map.clear only once for non-reactive keys', () => {\n      const [proxy, spy] = coverCollectionFn(new Map(), 'clear')\n      proxy.clear()\n      expect(spy).toBeCalledTimes(1)\n    })\n\n    it('should return proxy from Map.set call', () => {\n      const map = reactive(new Map())\n      const result = map.set('a', 'a')\n      expect(result).toBe(map)\n    })\n\n    it('should wrapped iterator inherit all iterator properties', () => {\n      const raw = new Map([['key', 'value']])\n      const map = reactive(raw)\n\n      const rawIterator = raw.entries()\n      const wrappedIterator = map.entries()\n\n      // Wrapped iterator should have the same properties as original iterator\n      expect(typeof wrappedIterator.next).toBe('function')\n      expect(typeof wrappedIterator[Symbol.iterator]).toBe('function')\n      expect(wrappedIterator[Symbol.iterator]()).toBe(wrappedIterator)\n\n      // Check inherited iterator helper methods if they exist on the original\n      for (const key of Object.getOwnPropertyNames(\n        Object.getPrototypeOf(rawIterator),\n      )) {\n        expect(key in wrappedIterator).toBe(true)\n      }\n      for (const key of Object.getOwnPropertySymbols(\n        Object.getPrototypeOf(rawIterator),\n      )) {\n        expect(key in wrappedIterator).toBe(true)\n      }\n    })\n  })\n})\n"
  },
  {
    "path": "packages/reactivity/__tests__/collections/Set.spec.ts",
    "content": "import {\n  effect,\n  isReactive,\n  reactive,\n  readonly,\n  shallowReactive,\n  toRaw,\n} from '../../src'\n\ndescribe('reactivity/collections', () => {\n  function coverCollectionFn(collection: Set<any>, fnName: string) {\n    const spy = vi.fn()\n    let proxy = reactive(collection)\n    ;(collection as any)[fnName] = spy\n    return [proxy as any, spy]\n  }\n\n  describe('Set', () => {\n    it('instanceof', () => {\n      const original = new Set()\n      const observed = reactive(original)\n      expect(isReactive(observed)).toBe(true)\n      expect(original).toBeInstanceOf(Set)\n      expect(observed).toBeInstanceOf(Set)\n    })\n\n    it('should observe mutations', () => {\n      let dummy\n      const set = reactive(new Set())\n      effect(() => (dummy = set.has('value')))\n\n      expect(dummy).toBe(false)\n      set.add('value')\n      expect(dummy).toBe(true)\n      set.delete('value')\n      expect(dummy).toBe(false)\n    })\n\n    it('should observe mutations with observed value', () => {\n      let dummy\n      const value = reactive({})\n      const set = reactive(new Set())\n      effect(() => (dummy = set.has(value)))\n\n      expect(dummy).toBe(false)\n      set.add(value)\n      expect(dummy).toBe(true)\n      set.delete(value)\n      expect(dummy).toBe(false)\n    })\n\n    it('should observe for of iteration', () => {\n      let dummy\n      const set = reactive(new Set() as Set<number>)\n      effect(() => {\n        dummy = 0\n        for (let num of set) {\n          dummy += num\n        }\n      })\n\n      expect(dummy).toBe(0)\n      set.add(2)\n      set.add(1)\n      expect(dummy).toBe(3)\n      set.delete(2)\n      expect(dummy).toBe(1)\n      set.clear()\n      expect(dummy).toBe(0)\n    })\n\n    it('should observe forEach iteration', () => {\n      let dummy: any\n      const set = reactive(new Set())\n      effect(() => {\n        dummy = 0\n        set.forEach(num => (dummy += num))\n      })\n\n      expect(dummy).toBe(0)\n      set.add(2)\n      set.add(1)\n      expect(dummy).toBe(3)\n      set.delete(2)\n      expect(dummy).toBe(1)\n      set.clear()\n      expect(dummy).toBe(0)\n    })\n\n    it('should observe values iteration', () => {\n      let dummy\n      const set = reactive(new Set() as Set<number>)\n      effect(() => {\n        dummy = 0\n        for (let num of set.values()) {\n          dummy += num\n        }\n      })\n\n      expect(dummy).toBe(0)\n      set.add(2)\n      set.add(1)\n      expect(dummy).toBe(3)\n      set.delete(2)\n      expect(dummy).toBe(1)\n      set.clear()\n      expect(dummy).toBe(0)\n    })\n\n    it('should observe keys iteration', () => {\n      let dummy\n      const set = reactive(new Set() as Set<number>)\n      effect(() => {\n        dummy = 0\n        for (let num of set.keys()) {\n          dummy += num\n        }\n      })\n\n      expect(dummy).toBe(0)\n      set.add(2)\n      set.add(1)\n      expect(dummy).toBe(3)\n      set.delete(2)\n      expect(dummy).toBe(1)\n      set.clear()\n      expect(dummy).toBe(0)\n    })\n\n    it('should observe entries iteration', () => {\n      let dummy\n      const set = reactive(new Set<number>())\n      effect(() => {\n        dummy = 0\n        for (let [key, num] of set.entries()) {\n          key\n          dummy += num\n        }\n      })\n\n      expect(dummy).toBe(0)\n      set.add(2)\n      set.add(1)\n      expect(dummy).toBe(3)\n      set.delete(2)\n      expect(dummy).toBe(1)\n      set.clear()\n      expect(dummy).toBe(0)\n    })\n\n    it('should be triggered by clearing', () => {\n      let dummy\n      const set = reactive(new Set())\n      effect(() => (dummy = set.has('key')))\n\n      expect(dummy).toBe(false)\n      set.add('key')\n      expect(dummy).toBe(true)\n      set.clear()\n      expect(dummy).toBe(false)\n    })\n\n    it('should not observe custom property mutations', () => {\n      let dummy\n      const set: any = reactive(new Set())\n      effect(() => (dummy = set.customProp))\n\n      expect(dummy).toBe(undefined)\n      set.customProp = 'Hello World'\n      expect(dummy).toBe(undefined)\n    })\n\n    it('should observe size mutations', () => {\n      let dummy\n      const set = reactive(new Set())\n      effect(() => (dummy = set.size))\n\n      expect(dummy).toBe(0)\n      set.add('value')\n      set.add('value2')\n      expect(dummy).toBe(2)\n      set.delete('value')\n      expect(dummy).toBe(1)\n      set.clear()\n      expect(dummy).toBe(0)\n    })\n\n    it('should not observe non value changing mutations', () => {\n      let dummy\n      const set = reactive(new Set())\n      const setSpy = vi.fn(() => (dummy = set.has('value')))\n      effect(setSpy)\n\n      expect(dummy).toBe(false)\n      expect(setSpy).toHaveBeenCalledTimes(1)\n      set.add('value')\n      expect(dummy).toBe(true)\n      expect(setSpy).toHaveBeenCalledTimes(2)\n      set.add('value')\n      expect(dummy).toBe(true)\n      expect(setSpy).toHaveBeenCalledTimes(2)\n      set.delete('value')\n      expect(dummy).toBe(false)\n      expect(setSpy).toHaveBeenCalledTimes(3)\n      set.delete('value')\n      expect(dummy).toBe(false)\n      expect(setSpy).toHaveBeenCalledTimes(3)\n      set.clear()\n      expect(dummy).toBe(false)\n      expect(setSpy).toHaveBeenCalledTimes(3)\n    })\n\n    it('should not observe raw data', () => {\n      let dummy\n      const set = reactive(new Set())\n      effect(() => (dummy = toRaw(set).has('value')))\n\n      expect(dummy).toBe(false)\n      set.add('value')\n      expect(dummy).toBe(false)\n    })\n\n    it('should not observe raw iterations', () => {\n      let dummy = 0\n      const set = reactive(new Set<number>())\n      effect(() => {\n        dummy = 0\n        for (let [num] of toRaw(set).entries()) {\n          dummy += num\n        }\n        for (let num of toRaw(set).keys()) {\n          dummy += num\n        }\n        for (let num of toRaw(set).values()) {\n          dummy += num\n        }\n        toRaw(set).forEach(num => {\n          dummy += num\n        })\n        for (let num of toRaw(set)) {\n          dummy += num\n        }\n      })\n\n      expect(dummy).toBe(0)\n      set.add(2)\n      set.add(3)\n      expect(dummy).toBe(0)\n      set.delete(2)\n      expect(dummy).toBe(0)\n    })\n\n    it('should not be triggered by raw mutations', () => {\n      let dummy\n      const set = reactive(new Set())\n      effect(() => (dummy = set.has('value')))\n\n      expect(dummy).toBe(false)\n      toRaw(set).add('value')\n      expect(dummy).toBe(false)\n      dummy = true\n      toRaw(set).delete('value')\n      expect(dummy).toBe(true)\n      toRaw(set).clear()\n      expect(dummy).toBe(true)\n    })\n\n    it('should not observe raw size mutations', () => {\n      let dummy\n      const set = reactive(new Set())\n      effect(() => (dummy = toRaw(set).size))\n\n      expect(dummy).toBe(0)\n      set.add('value')\n      expect(dummy).toBe(0)\n    })\n\n    it('should not be triggered by raw size mutations', () => {\n      let dummy\n      const set = reactive(new Set())\n      effect(() => (dummy = set.size))\n\n      expect(dummy).toBe(0)\n      toRaw(set).add('value')\n      expect(dummy).toBe(0)\n    })\n\n    it('should support objects as key', () => {\n      let dummy\n      const key = {}\n      const set = reactive(new Set())\n      const setSpy = vi.fn(() => (dummy = set.has(key)))\n      effect(setSpy)\n\n      expect(dummy).toBe(false)\n      expect(setSpy).toHaveBeenCalledTimes(1)\n\n      set.add({})\n      expect(dummy).toBe(false)\n      expect(setSpy).toHaveBeenCalledTimes(1)\n\n      set.add(key)\n      expect(dummy).toBe(true)\n      expect(setSpy).toHaveBeenCalledTimes(2)\n    })\n\n    it('should not pollute original Set with Proxies', () => {\n      const set = new Set()\n      const observed = reactive(set)\n      const value = reactive({})\n      observed.add(value)\n      expect(observed.has(value)).toBe(true)\n      expect(set.has(value)).toBe(false)\n    })\n\n    it('should observe nested values in iterations (forEach)', () => {\n      const set = reactive(new Set([{ foo: 1 }]))\n      let dummy: any\n      effect(() => {\n        dummy = 0\n        set.forEach(value => {\n          expect(isReactive(value)).toBe(true)\n          dummy += value.foo\n        })\n      })\n      expect(dummy).toBe(1)\n      set.forEach(value => {\n        value.foo++\n      })\n      expect(dummy).toBe(2)\n    })\n\n    it('should observe nested values in iterations (values)', () => {\n      const set = reactive(new Set([{ foo: 1 }]))\n      let dummy: any\n      effect(() => {\n        dummy = 0\n        for (const value of set.values()) {\n          expect(isReactive(value)).toBe(true)\n          dummy += value.foo\n        }\n      })\n      expect(dummy).toBe(1)\n      set.forEach(value => {\n        value.foo++\n      })\n      expect(dummy).toBe(2)\n    })\n\n    it('should observe nested values in iterations (entries)', () => {\n      const set = reactive(new Set([{ foo: 1 }]))\n      let dummy: any\n      effect(() => {\n        dummy = 0\n        for (const [key, value] of set.entries()) {\n          expect(isReactive(key)).toBe(true)\n          expect(isReactive(value)).toBe(true)\n          dummy += value.foo\n        }\n      })\n      expect(dummy).toBe(1)\n      set.forEach(value => {\n        value.foo++\n      })\n      expect(dummy).toBe(2)\n    })\n\n    it('should observe nested values in iterations (for...of)', () => {\n      const set = reactive(new Set([{ foo: 1 }]))\n      let dummy: any\n      effect(() => {\n        dummy = 0\n        for (const value of set) {\n          expect(isReactive(value)).toBe(true)\n          dummy += value.foo\n        }\n      })\n      expect(dummy).toBe(1)\n      set.forEach(value => {\n        value.foo++\n      })\n      expect(dummy).toBe(2)\n    })\n\n    it('should work with reactive entries in raw set', () => {\n      const raw = new Set()\n      const entry = reactive({})\n      raw.add(entry)\n      const set = reactive(raw)\n\n      expect(set.has(entry)).toBe(true)\n\n      expect(set.delete(entry)).toBe(true)\n      expect(set.has(entry)).toBe(false)\n    })\n\n    it('should track deletion of reactive entries in raw set', () => {\n      const raw = new Set()\n      const entry = reactive({})\n      raw.add(entry)\n      const set = reactive(raw)\n\n      let dummy\n      effect(() => {\n        dummy = set.has(entry)\n      })\n      expect(dummy).toBe(true)\n\n      set.delete(entry)\n      expect(dummy).toBe(false)\n    })\n\n    it('should not add readonly versions of existing raw values', () => {\n      const rawValue = {}\n      const wrappedValue = readonly(rawValue)\n      const set = reactive(new Set([rawValue]))\n\n      expect(set.has(wrappedValue)).toBe(true)\n\n      set.add(wrappedValue)\n\n      expect(set.size).toBe(1)\n      expect(toRaw(set).has(rawValue)).toBe(true)\n      expect(toRaw(set).has(wrappedValue)).toBe(false)\n    })\n\n    it('should not add proxy versions of existing raw values to shallow sets', () => {\n      const rawValue = {}\n      const wrappedValue = reactive(rawValue)\n      const set = shallowReactive(new Set([rawValue]))\n\n      expect(set.has(wrappedValue)).toBe(true)\n\n      set.add(wrappedValue)\n\n      expect(set.size).toBe(1)\n      expect(toRaw(set).has(rawValue)).toBe(true)\n      expect(toRaw(set).has(wrappedValue)).toBe(false)\n    })\n\n    it('should warn when set contains both raw and reactive versions of the same object', () => {\n      const raw = new Set()\n      const rawKey = {}\n      const key = reactive(rawKey)\n      raw.add(rawKey)\n      raw.add(key)\n      const set = reactive(raw)\n      set.delete(key)\n      expect(\n        `Reactive Set contains both the raw and reactive`,\n      ).toHaveBeenWarned()\n    })\n\n    it('thisArg', () => {\n      const raw = new Set(['value'])\n      const proxy = reactive(raw)\n      const thisArg = {}\n      let count = 0\n      proxy.forEach(function (this: {}, value, _, set) {\n        ++count\n        expect(this).toBe(thisArg)\n        expect(value).toBe('value')\n        expect(set).toBe(proxy)\n      }, thisArg)\n      expect(count).toBe(1)\n    })\n\n    it('should trigger Set.has only once for non-reactive keys', () => {\n      const [proxy, spy] = coverCollectionFn(new Set(), 'has')\n      proxy.has('foo')\n      expect(spy).toBeCalledTimes(1)\n    })\n\n    it('should trigger Set.add only once for non-reactive keys', () => {\n      const [proxy, spy] = coverCollectionFn(new Set(), 'add')\n      proxy.add('foo')\n      expect(spy).toBeCalledTimes(1)\n    })\n\n    it('should trigger Set.delete only once for non-reactive keys', () => {\n      const [proxy, spy] = coverCollectionFn(new Set(), 'delete')\n      proxy.delete('foo')\n      expect(spy).toBeCalledTimes(1)\n    })\n\n    it('should trigger Set.clear only once for non-reactive keys', () => {\n      const [proxy, spy] = coverCollectionFn(new Set(), 'clear')\n      proxy.clear()\n      expect(spy).toBeCalledTimes(1)\n    })\n\n    it('should return proxy from Set.add call', () => {\n      const set = reactive(new Set())\n      const result = set.add('a')\n      expect(result).toBe(set)\n    })\n  })\n})\n"
  },
  {
    "path": "packages/reactivity/__tests__/collections/WeakMap.spec.ts",
    "content": "import { effect, isReactive, reactive, toRaw } from '../../src'\n\ndescribe('reactivity/collections', () => {\n  describe('WeakMap', () => {\n    test('instanceof', () => {\n      const original = new WeakMap()\n      const observed = reactive(original)\n      expect(isReactive(observed)).toBe(true)\n      expect(original).toBeInstanceOf(WeakMap)\n      expect(observed).toBeInstanceOf(WeakMap)\n    })\n\n    it('should observe mutations', () => {\n      let dummy\n      const key = {}\n      const map = reactive(new WeakMap())\n      effect(() => {\n        dummy = map.get(key)\n      })\n\n      expect(dummy).toBe(undefined)\n      map.set(key, 'value')\n      expect(dummy).toBe('value')\n      map.set(key, 'value2')\n      expect(dummy).toBe('value2')\n      map.delete(key)\n      expect(dummy).toBe(undefined)\n    })\n\n    it('should observe mutations with observed value as key', () => {\n      let dummy\n      const key = reactive({})\n      const value = reactive({})\n      const map = reactive(new WeakMap())\n      effect(() => {\n        dummy = map.get(key)\n      })\n\n      expect(dummy).toBe(undefined)\n      map.set(key, value)\n      expect(dummy).toBe(value)\n      map.delete(key)\n      expect(dummy).toBe(undefined)\n    })\n\n    it('should not observe custom property mutations', () => {\n      let dummy\n      const map: any = reactive(new WeakMap())\n      effect(() => (dummy = map.customProp))\n\n      expect(dummy).toBe(undefined)\n      map.customProp = 'Hello World'\n      expect(dummy).toBe(undefined)\n    })\n\n    it('should not observe non value changing mutations', () => {\n      let dummy\n      const key = {}\n      const map = reactive(new WeakMap())\n      const mapSpy = vi.fn(() => (dummy = map.get(key)))\n      effect(mapSpy)\n\n      expect(dummy).toBe(undefined)\n      expect(mapSpy).toHaveBeenCalledTimes(1)\n      map.set(key, undefined)\n      expect(dummy).toBe(undefined)\n      expect(mapSpy).toHaveBeenCalledTimes(2)\n      map.set(key, 'value')\n      expect(dummy).toBe('value')\n      expect(mapSpy).toHaveBeenCalledTimes(3)\n      map.set(key, 'value')\n      expect(dummy).toBe('value')\n      expect(mapSpy).toHaveBeenCalledTimes(3)\n      map.delete(key)\n      expect(dummy).toBe(undefined)\n      expect(mapSpy).toHaveBeenCalledTimes(4)\n      map.delete(key)\n      expect(dummy).toBe(undefined)\n      expect(mapSpy).toHaveBeenCalledTimes(4)\n    })\n\n    it('should not observe raw data', () => {\n      let dummy\n      const key = {}\n      const map = reactive(new WeakMap())\n      effect(() => (dummy = toRaw(map).get(key)))\n\n      expect(dummy).toBe(undefined)\n      map.set(key, 'Hello')\n      expect(dummy).toBe(undefined)\n      map.delete(key)\n      expect(dummy).toBe(undefined)\n    })\n\n    it('should not pollute original Map with Proxies', () => {\n      const map = new WeakMap()\n      const observed = reactive(map)\n      const key = {}\n      const value = reactive({})\n      observed.set(key, value)\n      expect(map.get(key)).not.toBe(value)\n      expect(map.get(key)).toBe(toRaw(value))\n    })\n\n    it('should return observable versions of contained values', () => {\n      const observed = reactive(new WeakMap())\n      const key = {}\n      const value = {}\n      observed.set(key, value)\n      const wrapped = observed.get(key)\n      expect(isReactive(wrapped)).toBe(true)\n      expect(toRaw(wrapped)).toBe(value)\n    })\n\n    it('should observed nested data', () => {\n      const observed = reactive(new WeakMap())\n      const key = {}\n      observed.set(key, { a: 1 })\n      let dummy\n      effect(() => {\n        dummy = observed.get(key).a\n      })\n      observed.get(key).a = 2\n      expect(dummy).toBe(2)\n    })\n\n    it('should not be trigger when the value and the old value both are NaN', () => {\n      const map = new WeakMap()\n      const key = {}\n      map.set(key, NaN)\n      const mapSpy = vi.fn(() => map.get(key))\n      effect(mapSpy)\n      map.set(key, NaN)\n      expect(mapSpy).toHaveBeenCalledTimes(1)\n    })\n    it('should return proxy from WeakMap.set call', () => {\n      const map = reactive(new WeakMap())\n      const result = map.set({}, 'a')\n      expect(result).toBe(map)\n    })\n  })\n})\n"
  },
  {
    "path": "packages/reactivity/__tests__/collections/WeakSet.spec.ts",
    "content": "import { effect, isReactive, reactive, toRaw } from '../../src'\n\ndescribe('reactivity/collections', () => {\n  describe('WeakSet', () => {\n    it('instanceof', () => {\n      const original = new WeakSet()\n      const observed = reactive(original)\n      expect(isReactive(observed)).toBe(true)\n      expect(original).toBeInstanceOf(WeakSet)\n      expect(observed).toBeInstanceOf(WeakSet)\n    })\n\n    it('should observe mutations', () => {\n      let dummy\n      const value = {}\n      const set = reactive(new WeakSet())\n      effect(() => (dummy = set.has(value)))\n\n      expect(dummy).toBe(false)\n      set.add(value)\n      expect(dummy).toBe(true)\n      set.delete(value)\n      expect(dummy).toBe(false)\n    })\n\n    it('should observe mutations with observed value', () => {\n      let dummy\n      const value = reactive({})\n      const set = reactive(new WeakSet())\n      effect(() => (dummy = set.has(value)))\n\n      expect(dummy).toBe(false)\n      set.add(value)\n      expect(dummy).toBe(true)\n      set.delete(value)\n      expect(dummy).toBe(false)\n    })\n\n    it('should not observe custom property mutations', () => {\n      let dummy\n      const set: any = reactive(new WeakSet())\n      effect(() => (dummy = set.customProp))\n\n      expect(dummy).toBe(undefined)\n      set.customProp = 'Hello World'\n      expect(dummy).toBe(undefined)\n    })\n\n    it('should not observe non value changing mutations', () => {\n      let dummy\n      const value = {}\n      const set = reactive(new WeakSet())\n      const setSpy = vi.fn(() => (dummy = set.has(value)))\n      effect(setSpy)\n\n      expect(dummy).toBe(false)\n      expect(setSpy).toHaveBeenCalledTimes(1)\n      set.add(value)\n      expect(dummy).toBe(true)\n      expect(setSpy).toHaveBeenCalledTimes(2)\n      set.add(value)\n      expect(dummy).toBe(true)\n      expect(setSpy).toHaveBeenCalledTimes(2)\n      set.delete(value)\n      expect(dummy).toBe(false)\n      expect(setSpy).toHaveBeenCalledTimes(3)\n      set.delete(value)\n      expect(dummy).toBe(false)\n      expect(setSpy).toHaveBeenCalledTimes(3)\n    })\n\n    it('should not observe raw data', () => {\n      const value = {}\n      let dummy\n      const set = reactive(new WeakSet())\n      effect(() => (dummy = toRaw(set).has(value)))\n\n      expect(dummy).toBe(false)\n      set.add(value)\n      expect(dummy).toBe(false)\n    })\n\n    it('should not be triggered by raw mutations', () => {\n      const value = {}\n      let dummy\n      const set = reactive(new WeakSet())\n      effect(() => (dummy = set.has(value)))\n\n      expect(dummy).toBe(false)\n      toRaw(set).add(value)\n      expect(dummy).toBe(false)\n    })\n\n    it('should not pollute original Set with Proxies', () => {\n      const set = new WeakSet()\n      const observed = reactive(set)\n      const value = reactive({})\n      observed.add(value)\n      expect(observed.has(value)).toBe(true)\n      expect(set.has(value)).toBe(false)\n    })\n\n    it('should return proxy from WeakSet.add call', () => {\n      const set = reactive(new WeakSet())\n      const result = set.add({})\n      expect(result).toBe(set)\n    })\n  })\n})\n"
  },
  {
    "path": "packages/reactivity/__tests__/collections/shallowReadonly.spec.ts",
    "content": "import { isReactive, isReadonly, shallowReadonly } from '../../src'\n\ndescribe('reactivity/collections', () => {\n  describe('shallowReadonly/Map', () => {\n    ;[Map, WeakMap].forEach(Collection => {\n      test('should make the map/weak-map readonly', () => {\n        const key = {}\n        const val = { foo: 1 }\n        const original = new Collection([[key, val]])\n        const sroMap = shallowReadonly(original)\n        expect(isReadonly(sroMap)).toBe(true)\n        expect(isReactive(sroMap)).toBe(false)\n        expect(sroMap.get(key)).toBe(val)\n\n        sroMap.set(key, {} as any)\n        expect(\n          `Set operation on key \"[object Object]\" failed: target is readonly.`,\n        ).toHaveBeenWarned()\n      })\n\n      test('should not make nested values readonly', () => {\n        const key = {}\n        const val = { foo: 1 }\n        const original = new Collection([[key, val]])\n        const sroMap = shallowReadonly(original)\n        expect(isReadonly(sroMap.get(key))).toBe(false)\n        expect(isReactive(sroMap.get(key))).toBe(false)\n\n        sroMap.get(key)!.foo = 2\n        expect(\n          `Set operation on key \"foo\" failed: target is readonly.`,\n        ).not.toHaveBeenWarned()\n      })\n    })\n\n    test('should not make the value generated by the iterable method readonly', () => {\n      const key = {}\n      const val = { foo: 1 }\n      const original = new Map([[key, val]])\n      const sroMap = shallowReadonly(original)\n\n      const values1 = [...sroMap.values()]\n      const values2 = [...sroMap.entries()]\n\n      expect(isReadonly(values1[0])).toBe(false)\n      expect(isReactive(values1[0])).toBe(false)\n      expect(values1[0]).toBe(val)\n\n      values1[0].foo = 2\n      expect(\n        `Set operation on key \"foo\" failed: target is readonly.`,\n      ).not.toHaveBeenWarned()\n\n      expect(isReadonly(values2[0][1])).toBe(false)\n      expect(isReactive(values2[0][1])).toBe(false)\n      expect(values2[0][1]).toBe(val)\n\n      values2[0][1].foo = 2\n      expect(\n        `Set operation on key \"foo\" failed: target is readonly.`,\n      ).not.toHaveBeenWarned()\n    })\n\n    test('should not make the value generated by the forEach method readonly', () => {\n      const val = { foo: 1 }\n      const original = new Map([['key', val]])\n      const sroMap = shallowReadonly(original)\n\n      sroMap.forEach(val => {\n        expect(isReadonly(val)).toBe(false)\n        expect(isReactive(val)).toBe(false)\n        expect(val).toBe(val)\n\n        val.foo = 2\n        expect(\n          `Set operation on key \"foo\" failed: target is readonly.`,\n        ).not.toHaveBeenWarned()\n      })\n    })\n  })\n\n  describe('shallowReadonly/Set', () => {\n    test('should make the set/weak-set readonly', () => {\n      ;[Set, WeakSet].forEach(Collection => {\n        const obj = { foo: 1 }\n        const original = new Collection([obj])\n        const sroSet = shallowReadonly(original)\n        expect(isReadonly(sroSet)).toBe(true)\n        expect(isReactive(sroSet)).toBe(false)\n        expect(sroSet.has(obj)).toBe(true)\n\n        sroSet.add({} as any)\n        expect(\n          `Add operation on key \"[object Object]\" failed: target is readonly.`,\n        ).toHaveBeenWarned()\n      })\n    })\n\n    test('should not make nested values readonly', () => {\n      const obj = { foo: 1 }\n      const original = new Set([obj])\n      const sroSet = shallowReadonly(original)\n\n      const values = [...sroSet.values()]\n\n      expect(values[0]).toBe(obj)\n      expect(isReadonly(values[0])).toBe(false)\n      expect(isReactive(values[0])).toBe(false)\n\n      sroSet.add({} as any)\n      expect(\n        `Add operation on key \"[object Object]\" failed: target is readonly.`,\n      ).toHaveBeenWarned()\n\n      values[0].foo = 2\n      expect(\n        `Set operation on key \"foo\" failed: target is readonly.`,\n      ).not.toHaveBeenWarned()\n    })\n\n    test('should not make the value generated by the iterable method readonly', () => {\n      const val = { foo: 1 }\n      const original = new Set([val])\n      const sroSet = shallowReadonly(original)\n\n      const values1 = [...sroSet.values()]\n      const values2 = [...sroSet.entries()]\n\n      expect(isReadonly(values1[0])).toBe(false)\n      expect(isReactive(values1[0])).toBe(false)\n      expect(values1[0]).toBe(val)\n\n      values1[0].foo = 2\n      expect(\n        `Set operation on key \"foo\" failed: target is readonly.`,\n      ).not.toHaveBeenWarned()\n\n      expect(isReadonly(values2[0][1])).toBe(false)\n      expect(isReactive(values2[0][1])).toBe(false)\n      expect(values2[0][1]).toBe(val)\n\n      values2[0][1].foo = 2\n      expect(\n        `Set operation on key \"foo\" failed: target is readonly.`,\n      ).not.toHaveBeenWarned()\n    })\n\n    test('should not make the value generated by the forEach method readonly', () => {\n      const val = { foo: 1 }\n      const original = new Set([val])\n      const sroSet = shallowReadonly(original)\n\n      sroSet.forEach(val => {\n        expect(isReadonly(val)).toBe(false)\n        expect(isReactive(val)).toBe(false)\n        expect(val).toBe(val)\n\n        val.foo = 2\n        expect(\n          `Set operation on key \"foo\" failed: target is readonly.`,\n        ).not.toHaveBeenWarned()\n      })\n    })\n  })\n})\n"
  },
  {
    "path": "packages/reactivity/__tests__/computed.spec.ts",
    "content": "import {\n  type TestElement,\n  defineComponent,\n  h,\n  nextTick,\n  nodeOps,\n  onMounted,\n  onUnmounted,\n  render,\n  serializeInner,\n  triggerEvent,\n} from '@vue/runtime-test'\nimport {\n  type DebuggerEvent,\n  ITERATE_KEY,\n  TrackOpTypes,\n  TriggerOpTypes,\n  type WritableComputedRef,\n  computed,\n  effect,\n  isReadonly,\n  reactive,\n  ref,\n  shallowRef,\n  toRaw,\n  triggerRef,\n} from '../src'\nimport { EffectFlags, pauseTracking, resetTracking } from '../src/effect'\nimport type { ComputedRef, ComputedRefImpl } from '../src/computed'\n\ndescribe('reactivity/computed', () => {\n  it('should return updated value', () => {\n    const value = reactive<{ foo?: number }>({})\n    const cValue = computed(() => value.foo)\n    expect(cValue.value).toBe(undefined)\n    value.foo = 1\n    expect(cValue.value).toBe(1)\n  })\n\n  it('pass oldValue to computed getter', () => {\n    const count = ref(0)\n    const oldValue = ref()\n    const curValue = computed(pre => {\n      oldValue.value = pre\n      return count.value\n    })\n    expect(curValue.value).toBe(0)\n    expect(oldValue.value).toBe(undefined)\n    count.value++\n    expect(curValue.value).toBe(1)\n    expect(oldValue.value).toBe(0)\n  })\n\n  it('should compute lazily', () => {\n    const value = reactive<{ foo?: number }>({})\n    const getter = vi.fn(() => value.foo)\n    const cValue = computed(getter)\n\n    // lazy\n    expect(getter).not.toHaveBeenCalled()\n\n    expect(cValue.value).toBe(undefined)\n    expect(getter).toHaveBeenCalledTimes(1)\n\n    // should not compute again\n    cValue.value\n    expect(getter).toHaveBeenCalledTimes(1)\n\n    // should not compute until needed\n    value.foo = 1\n    expect(getter).toHaveBeenCalledTimes(1)\n\n    // now it should compute\n    expect(cValue.value).toBe(1)\n    expect(getter).toHaveBeenCalledTimes(2)\n\n    // should not compute again\n    cValue.value\n    expect(getter).toHaveBeenCalledTimes(2)\n  })\n\n  it('should trigger effect', () => {\n    const value = reactive<{ foo?: number }>({})\n    const cValue = computed(() => value.foo)\n    let dummy\n    effect(() => {\n      dummy = cValue.value\n    })\n    expect(dummy).toBe(undefined)\n    value.foo = 1\n    expect(dummy).toBe(1)\n  })\n\n  it('should work when chained', () => {\n    const value = reactive({ foo: 0 })\n    const c1 = computed(() => value.foo)\n    const c2 = computed(() => c1.value + 1)\n    expect(c2.value).toBe(1)\n    expect(c1.value).toBe(0)\n    value.foo++\n    expect(c2.value).toBe(2)\n    expect(c1.value).toBe(1)\n  })\n\n  it('should trigger effect when chained', () => {\n    const value = reactive({ foo: 0 })\n    const getter1 = vi.fn(() => value.foo)\n    const getter2 = vi.fn(() => {\n      return c1.value + 1\n    })\n    const c1 = computed(getter1)\n    const c2 = computed(getter2)\n\n    let dummy\n    effect(() => {\n      dummy = c2.value\n    })\n    expect(dummy).toBe(1)\n    expect(getter1).toHaveBeenCalledTimes(1)\n    expect(getter2).toHaveBeenCalledTimes(1)\n    value.foo++\n    expect(dummy).toBe(2)\n    // should not result in duplicate calls\n    expect(getter1).toHaveBeenCalledTimes(2)\n    expect(getter2).toHaveBeenCalledTimes(2)\n  })\n\n  it('should trigger effect when chained (mixed invocations)', () => {\n    const value = reactive({ foo: 0 })\n    const getter1 = vi.fn(() => value.foo)\n    const getter2 = vi.fn(() => {\n      return c1.value + 1\n    })\n    const c1 = computed(getter1)\n    const c2 = computed(getter2)\n\n    let dummy\n    effect(() => {\n      dummy = c1.value + c2.value\n    })\n    expect(dummy).toBe(1)\n\n    expect(getter1).toHaveBeenCalledTimes(1)\n    expect(getter2).toHaveBeenCalledTimes(1)\n    value.foo++\n    expect(dummy).toBe(3)\n    // should not result in duplicate calls\n    expect(getter1).toHaveBeenCalledTimes(2)\n    expect(getter2).toHaveBeenCalledTimes(2)\n  })\n\n  it('should support setter', () => {\n    const n = ref(1)\n    const plusOne = computed({\n      get: () => n.value + 1,\n      set: val => {\n        n.value = val - 1\n      },\n    })\n\n    expect(plusOne.value).toBe(2)\n    n.value++\n    expect(plusOne.value).toBe(3)\n\n    plusOne.value = 0\n    expect(n.value).toBe(-1)\n  })\n\n  it('should trigger effect w/ setter', () => {\n    const n = ref(1)\n    const plusOne = computed({\n      get: () => n.value + 1,\n      set: val => {\n        n.value = val - 1\n      },\n    })\n\n    let dummy\n    effect(() => {\n      dummy = n.value\n    })\n    expect(dummy).toBe(1)\n\n    plusOne.value = 0\n    expect(dummy).toBe(-1)\n  })\n\n  // #5720\n  it('should invalidate before non-computed effects', () => {\n    let plusOneValues: number[] = []\n    const n = ref(0)\n    const plusOne = computed(() => n.value + 1)\n    effect(() => {\n      n.value\n      plusOneValues.push(plusOne.value)\n    })\n    // access plusOne, causing it to be non-dirty\n    plusOne.value\n    // mutate n\n    n.value++\n    // on the 2nd run, plusOne.value should have already updated.\n    expect(plusOneValues).toMatchObject([1, 2])\n  })\n\n  it('should warn if trying to set a readonly computed', () => {\n    const n = ref(1)\n    const plusOne = computed(() => n.value + 1)\n    ;(plusOne as WritableComputedRef<number>).value++ // Type cast to prevent TS from preventing the error\n\n    expect(\n      'Write operation failed: computed value is readonly',\n    ).toHaveBeenWarnedLast()\n  })\n\n  it('should be readonly', () => {\n    let a = { a: 1 }\n    const x = computed(() => a)\n    expect(isReadonly(x)).toBe(true)\n    expect(isReadonly(x.value)).toBe(false)\n    expect(isReadonly(x.value.a)).toBe(false)\n    const z = computed<typeof a>({\n      get() {\n        return a\n      },\n      set(v) {\n        a = v\n      },\n    })\n    expect(isReadonly(z)).toBe(false)\n    expect(isReadonly(z.value.a)).toBe(false)\n  })\n\n  it('debug: onTrack', () => {\n    let events: DebuggerEvent[] = []\n    const onTrack = vi.fn((e: DebuggerEvent) => {\n      events.push(e)\n    })\n    const obj = reactive({ foo: 1, bar: 2 })\n    const c = computed(() => (obj.foo, 'bar' in obj, Object.keys(obj)), {\n      onTrack,\n    })\n    expect(c.value).toEqual(['foo', 'bar'])\n    expect(onTrack).toHaveBeenCalledTimes(3)\n    expect(events).toEqual([\n      {\n        effect: c,\n        target: toRaw(obj),\n        type: TrackOpTypes.GET,\n        key: 'foo',\n      },\n      {\n        effect: c,\n        target: toRaw(obj),\n        type: TrackOpTypes.HAS,\n        key: 'bar',\n      },\n      {\n        effect: c,\n        target: toRaw(obj),\n        type: TrackOpTypes.ITERATE,\n        key: ITERATE_KEY,\n      },\n    ])\n  })\n\n  it('debug: onTrigger (reactive)', () => {\n    let events: DebuggerEvent[] = []\n    const onTrigger = vi.fn((e: DebuggerEvent) => {\n      events.push(e)\n    })\n    const obj = reactive<{ foo?: number }>({ foo: 1 })\n    const c = computed(() => obj.foo, { onTrigger })\n\n    // computed won't track until it has a subscriber\n    effect(() => c.value)\n\n    obj.foo!++\n    expect(c.value).toBe(2)\n    expect(onTrigger).toHaveBeenCalledTimes(1)\n    expect(events[0]).toEqual({\n      effect: c,\n      target: toRaw(obj),\n      type: TriggerOpTypes.SET,\n      key: 'foo',\n      oldValue: 1,\n      newValue: 2,\n    })\n\n    delete obj.foo\n    expect(c.value).toBeUndefined()\n    expect(onTrigger).toHaveBeenCalledTimes(2)\n    expect(events[1]).toEqual({\n      effect: c,\n      target: toRaw(obj),\n      type: TriggerOpTypes.DELETE,\n      key: 'foo',\n      oldValue: 2,\n    })\n  })\n\n  // https://github.com/vuejs/core/pull/5912#issuecomment-1497596875\n  it('should query deps dirty sequentially', () => {\n    const cSpy = vi.fn()\n\n    const a = ref<null | { v: number }>({\n      v: 1,\n    })\n    const b = computed(() => {\n      return a.value\n    })\n    const c = computed(() => {\n      cSpy()\n      return b.value?.v\n    })\n    const d = computed(() => {\n      if (b.value) {\n        return c.value\n      }\n      return 0\n    })\n\n    d.value\n    a.value!.v = 2\n    a.value = null\n    d.value\n    expect(cSpy).toHaveBeenCalledTimes(1)\n  })\n\n  // https://github.com/vuejs/core/pull/5912#issuecomment-1738257692\n  it('chained computed dirty reallocation after querying dirty', () => {\n    let _msg: string | undefined\n\n    const items = ref<number[]>()\n    const isLoaded = computed(() => {\n      return !!items.value\n    })\n    const msg = computed(() => {\n      if (isLoaded.value) {\n        return 'The items are loaded'\n      } else {\n        return 'The items are not loaded'\n      }\n    })\n\n    effect(() => {\n      _msg = msg.value\n    })\n\n    items.value = [1, 2, 3]\n    items.value = [1, 2, 3]\n    items.value = undefined\n\n    expect(_msg).toBe('The items are not loaded')\n  })\n\n  it('chained computed dirty reallocation after trigger computed getter', () => {\n    let _msg: string | undefined\n\n    const items = ref<number[]>()\n    const isLoaded = computed(() => {\n      return !!items.value\n    })\n    const msg = computed(() => {\n      if (isLoaded.value) {\n        return 'The items are loaded'\n      } else {\n        return 'The items are not loaded'\n      }\n    })\n\n    _msg = msg.value\n    items.value = [1, 2, 3]\n    isLoaded.value // <- trigger computed getter\n    _msg = msg.value\n    items.value = undefined\n    _msg = msg.value\n\n    expect(_msg).toBe('The items are not loaded')\n  })\n\n  // https://github.com/vuejs/core/pull/5912#issuecomment-1739159832\n  it('deps order should be consistent with the last time get value', () => {\n    const cSpy = vi.fn()\n\n    const a = ref(0)\n    const b = computed(() => {\n      return a.value % 3 !== 0\n    }) as unknown as ComputedRefImpl\n    const c = computed(() => {\n      cSpy()\n      if (a.value % 3 === 2) {\n        return 'expensive'\n      }\n      return 'cheap'\n    }) as unknown as ComputedRefImpl\n    const d = computed(() => {\n      return a.value % 3 === 2\n    }) as unknown as ComputedRefImpl\n    const e = computed(() => {\n      if (b.value) {\n        if (d.value) {\n          return 'Avoiding expensive calculation'\n        }\n      }\n      return c.value\n    }) as unknown as ComputedRefImpl\n\n    e.value\n    a.value++\n    e.value\n\n    expect(e.deps!.dep).toBe(b.dep)\n    expect(e.deps!.nextDep!.dep).toBe(d.dep)\n    expect(e.deps!.nextDep!.nextDep!.dep).toBe(c.dep)\n    expect(cSpy).toHaveBeenCalledTimes(2)\n\n    a.value++\n    e.value\n\n    expect(cSpy).toHaveBeenCalledTimes(2)\n  })\n\n  it('should trigger by the second computed that maybe dirty', () => {\n    const cSpy = vi.fn()\n\n    const src1 = ref(0)\n    const src2 = ref(0)\n    const c1 = computed(() => src1.value)\n    const c2 = computed(() => (src1.value % 2) + src2.value)\n    const c3 = computed(() => {\n      cSpy()\n      c1.value\n      c2.value\n    })\n\n    c3.value\n    src1.value = 2\n    c3.value\n    expect(cSpy).toHaveBeenCalledTimes(2)\n    src2.value = 1\n    c3.value\n    expect(cSpy).toHaveBeenCalledTimes(3)\n  })\n\n  it('should trigger the second effect', () => {\n    const fnSpy = vi.fn()\n    const v = ref(1)\n    const c = computed(() => v.value)\n\n    effect(() => {\n      c.value\n    })\n    effect(() => {\n      c.value\n      fnSpy()\n    })\n\n    expect(fnSpy).toBeCalledTimes(1)\n    v.value = 2\n    expect(fnSpy).toBeCalledTimes(2)\n  })\n\n  it('should chained recursive effects clear dirty after trigger', () => {\n    const v = ref(1)\n    const c1 = computed(() => v.value) as unknown as ComputedRefImpl\n    const c2 = computed(() => c1.value) as unknown as ComputedRefImpl\n\n    c2.value\n    expect(c1.flags & EffectFlags.DIRTY).toBeFalsy()\n    expect(c2.flags & EffectFlags.DIRTY).toBeFalsy()\n  })\n\n  it('should chained computeds dirtyLevel update with first computed effect', () => {\n    const v = ref(0)\n    const c1 = computed(() => {\n      if (v.value === 0) {\n        v.value = 1\n      }\n      return v.value\n    })\n    const c2 = computed(() => c1.value)\n    const c3 = computed(() => c2.value)\n\n    c3.value\n    // expect(COMPUTED_SIDE_EFFECT_WARN).toHaveBeenWarned()\n  })\n\n  it('should work when chained(ref+computed)', () => {\n    const v = ref(0)\n    const c1 = computed(() => {\n      if (v.value === 0) {\n        v.value = 1\n      }\n      return 'foo'\n    })\n    const c2 = computed(() => v.value + c1.value)\n    expect(c2.value).toBe('0foo')\n    expect(c2.value).toBe('1foo')\n    // expect(COMPUTED_SIDE_EFFECT_WARN).toHaveBeenWarned()\n  })\n\n  it('should trigger effect even computed already dirty', () => {\n    const fnSpy = vi.fn()\n    const v = ref(0)\n    const c1 = computed(() => {\n      if (v.value === 0) {\n        v.value = 1\n      }\n      return 'foo'\n    })\n    const c2 = computed(() => v.value + c1.value)\n\n    effect(() => {\n      fnSpy(c2.value)\n    })\n    expect(fnSpy).toBeCalledTimes(1)\n    expect(fnSpy.mock.calls).toMatchObject([['0foo']])\n    expect(v.value).toBe(1)\n    v.value = 2\n    expect(fnSpy).toBeCalledTimes(2)\n    expect(fnSpy.mock.calls).toMatchObject([['0foo'], ['2foo']])\n    expect(v.value).toBe(2)\n    // expect(COMPUTED_SIDE_EFFECT_WARN).toHaveBeenWarned()\n  })\n\n  // #10185\n  it('should not override queried MaybeDirty result', () => {\n    class Item {\n      v = ref(0)\n    }\n    const v1 = shallowRef()\n    const v2 = ref(false)\n    const c1 = computed(() => {\n      let c = v1.value\n      if (!v1.value) {\n        c = new Item()\n        v1.value = c\n      }\n      return c.v.value\n    })\n    const c2 = computed(() => {\n      if (!v2.value) return 'no'\n      return c1.value ? 'yes' : 'no'\n    })\n    const c3 = computed(() => c2.value)\n\n    c3.value\n    v2.value = true\n\n    c3.value\n    v1.value.v.value = 999\n\n    expect(c3.value).toBe('yes')\n    // expect(COMPUTED_SIDE_EFFECT_WARN).toHaveBeenWarned()\n  })\n\n  it('should be not dirty after deps mutate (mutate deps in computed)', async () => {\n    const state = reactive<any>({})\n    const consumer = computed(() => {\n      if (!('a' in state)) state.a = 1\n      return state.a\n    })\n    const Comp = {\n      setup: () => {\n        nextTick().then(() => {\n          state.a = 2\n        })\n        return () => consumer.value\n      },\n    }\n    const root = nodeOps.createElement('div')\n    render(h(Comp), root)\n    await nextTick()\n    await nextTick()\n    expect(serializeInner(root)).toBe(`2`)\n    // expect(COMPUTED_SIDE_EFFECT_WARN).toHaveBeenWarned()\n  })\n\n  it('should not trigger effect scheduler by recursive computed effect', async () => {\n    const v = ref('Hello')\n    const c = computed(() => {\n      v.value += ' World'\n      return v.value\n    })\n    const Comp = {\n      setup: () => {\n        return () => c.value\n      },\n    }\n    const root = nodeOps.createElement('div')\n\n    render(h(Comp), root)\n    await nextTick()\n    expect(serializeInner(root)).toBe('Hello World')\n\n    v.value += ' World'\n    await nextTick()\n    expect(serializeInner(root)).toBe('Hello World World World World')\n    // expect(COMPUTED_SIDE_EFFECT_WARN).toHaveBeenWarned()\n  })\n\n  test('should not trigger if value did not change', () => {\n    const src = ref(0)\n    const c = computed(() => src.value % 2)\n    const spy = vi.fn()\n    effect(() => {\n      spy(c.value)\n    })\n    expect(spy).toHaveBeenCalledTimes(1)\n    src.value = 2\n\n    // should not trigger\n    expect(spy).toHaveBeenCalledTimes(1)\n\n    src.value = 3\n    src.value = 5\n    // should trigger because latest value changes\n    expect(spy).toHaveBeenCalledTimes(2)\n  })\n\n  test('chained computed trigger', () => {\n    const effectSpy = vi.fn()\n    const c1Spy = vi.fn()\n    const c2Spy = vi.fn()\n\n    const src = ref(0)\n    const c1 = computed(() => {\n      c1Spy()\n      return src.value % 2\n    })\n    const c2 = computed(() => {\n      c2Spy()\n      return c1.value + 1\n    })\n\n    effect(() => {\n      effectSpy(c2.value)\n    })\n\n    expect(c1Spy).toHaveBeenCalledTimes(1)\n    expect(c2Spy).toHaveBeenCalledTimes(1)\n    expect(effectSpy).toHaveBeenCalledTimes(1)\n\n    src.value = 1\n    expect(c1Spy).toHaveBeenCalledTimes(2)\n    expect(c2Spy).toHaveBeenCalledTimes(2)\n    expect(effectSpy).toHaveBeenCalledTimes(2)\n  })\n\n  test('chained computed avoid re-compute', () => {\n    const effectSpy = vi.fn()\n    const c1Spy = vi.fn()\n    const c2Spy = vi.fn()\n\n    const src = ref(0)\n    const c1 = computed(() => {\n      c1Spy()\n      return src.value % 2\n    })\n    const c2 = computed(() => {\n      c2Spy()\n      return c1.value + 1\n    })\n\n    effect(() => {\n      effectSpy(c2.value)\n    })\n\n    expect(effectSpy).toHaveBeenCalledTimes(1)\n    src.value = 2\n    src.value = 4\n    src.value = 6\n    expect(c1Spy).toHaveBeenCalledTimes(4)\n    // c2 should not have to re-compute because c1 did not change.\n    expect(c2Spy).toHaveBeenCalledTimes(1)\n    // effect should not trigger because c2 did not change.\n    expect(effectSpy).toHaveBeenCalledTimes(1)\n  })\n\n  test('chained computed value invalidation', () => {\n    const effectSpy = vi.fn()\n    const c1Spy = vi.fn()\n    const c2Spy = vi.fn()\n\n    const src = ref(0)\n    const c1 = computed(() => {\n      c1Spy()\n      return src.value % 2\n    })\n    const c2 = computed(() => {\n      c2Spy()\n      return c1.value + 1\n    })\n\n    effect(() => {\n      effectSpy(c2.value)\n    })\n\n    expect(effectSpy).toHaveBeenCalledTimes(1)\n    expect(effectSpy).toHaveBeenCalledWith(1)\n    expect(c2.value).toBe(1)\n\n    expect(c1Spy).toHaveBeenCalledTimes(1)\n    expect(c2Spy).toHaveBeenCalledTimes(1)\n\n    src.value = 1\n    // value should be available sync\n    expect(c2.value).toBe(2)\n    expect(c2Spy).toHaveBeenCalledTimes(2)\n  })\n\n  test('sync access of invalidated chained computed should not prevent final effect from running', () => {\n    const effectSpy = vi.fn()\n    const c1Spy = vi.fn()\n    const c2Spy = vi.fn()\n\n    const src = ref(0)\n    const c1 = computed(() => {\n      c1Spy()\n      return src.value % 2\n    })\n    const c2 = computed(() => {\n      c2Spy()\n      return c1.value + 1\n    })\n\n    effect(() => {\n      effectSpy(c2.value)\n    })\n    expect(effectSpy).toHaveBeenCalledTimes(1)\n\n    src.value = 1\n    // sync access c2\n    c2.value\n    expect(effectSpy).toHaveBeenCalledTimes(2)\n  })\n\n  it('computed should force track in untracked zone', () => {\n    const n = ref(0)\n    const spy1 = vi.fn()\n    const spy2 = vi.fn()\n\n    let c: ComputedRef\n    effect(() => {\n      spy1()\n      pauseTracking()\n      n.value\n      c = computed(() => n.value + 1)\n      // access computed now to force refresh\n      c.value\n      effect(() => spy2(c.value))\n      n.value\n      resetTracking()\n    })\n\n    expect(spy1).toHaveBeenCalledTimes(1)\n    expect(spy2).toHaveBeenCalledTimes(1)\n\n    n.value++\n    // outer effect should not trigger\n    expect(spy1).toHaveBeenCalledTimes(1)\n    // inner effect should trigger\n    expect(spy2).toHaveBeenCalledTimes(2)\n  })\n\n  // not recommended behavior, but needed for backwards compatibility\n  // used in VueUse asyncComputed\n  it('computed side effect should be able trigger', () => {\n    const a = ref(false)\n    const b = ref(false)\n    const c = computed(() => {\n      a.value = true\n      return b.value\n    })\n    effect(() => {\n      if (a.value) {\n        b.value = true\n      }\n    })\n    expect(b.value).toBe(false)\n    // accessing c triggers change\n    c.value\n    expect(b.value).toBe(true)\n    expect(c.value).toBe(true)\n  })\n\n  it('chained computed should work when accessed before having subs', () => {\n    const n = ref(0)\n    const c = computed(() => n.value)\n    const d = computed(() => c.value + 1)\n    const spy = vi.fn()\n\n    // access\n    d.value\n\n    let dummy\n    effect(() => {\n      spy()\n      dummy = d.value\n    })\n    expect(spy).toHaveBeenCalledTimes(1)\n    expect(dummy).toBe(1)\n\n    n.value++\n    expect(spy).toHaveBeenCalledTimes(2)\n    expect(dummy).toBe(2)\n  })\n\n  // #10236\n  it('chained computed should still refresh after owner component unmount', async () => {\n    const a = ref(0)\n    const spy = vi.fn()\n\n    const Child = {\n      setup() {\n        const b = computed(() => a.value + 1)\n        const c = computed(() => b.value + 1)\n        // access\n        c.value\n        onUnmounted(() => spy(c.value))\n        return () => {}\n      },\n    }\n\n    const show = ref(true)\n    const Parent = {\n      setup() {\n        return () => (show.value ? h(Child) : null)\n      },\n    }\n\n    render(h(Parent), nodeOps.createElement('div'))\n\n    a.value++\n    show.value = false\n\n    await nextTick()\n    expect(spy).toHaveBeenCalledWith(3)\n  })\n\n  // case: radix-vue `useForwardExpose` sets a template ref during mount,\n  // and checks for the element's closest form element in a computed.\n  // the computed is expected to only evaluate after mount.\n  it('computed deps should only be refreshed when the subscribing effect is run, not when scheduled', async () => {\n    const calls: string[] = []\n    const a = ref(0)\n    const b = computed(() => {\n      calls.push('b eval')\n      return a.value + 1\n    })\n\n    const App = {\n      setup() {\n        onMounted(() => {\n          calls.push('mounted')\n        })\n        return () =>\n          h(\n            'div',\n            {\n              ref: () => (a.value = 1),\n            },\n            b.value,\n          )\n      },\n    }\n\n    render(h(App), nodeOps.createElement('div'))\n\n    await nextTick()\n    expect(calls).toMatchObject(['b eval', 'mounted', 'b eval'])\n  })\n\n  it('should chained computeds keep reactivity when computed effect happens', async () => {\n    const v = ref('Hello')\n    const c = computed(() => {\n      v.value += ' World'\n      return v.value\n    })\n    const d = computed(() => c.value)\n    const e = computed(() => d.value)\n    const Comp = {\n      setup: () => {\n        return () => d.value + ' | ' + e.value\n      },\n    }\n    const root = nodeOps.createElement('div')\n\n    render(h(Comp), root)\n    await nextTick()\n    expect(serializeInner(root)).toBe('Hello World | Hello World')\n\n    v.value += ' World'\n    await nextTick()\n    expect(serializeInner(root)).toBe(\n      'Hello World World World World | Hello World World World World',\n    )\n  })\n\n  it('should keep dirty level when side effect computed value changed', () => {\n    const v = ref(0)\n    const c = computed(() => {\n      v.value += 1\n      return v.value\n    })\n    const d = computed(() => {\n      return { d: c.value }\n    })\n\n    const Comp = {\n      setup: () => {\n        return () => {\n          return [d.value.d, d.value.d]\n        }\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(Comp), root)\n\n    expect(d.value.d).toBe(1)\n    expect(serializeInner(root)).toBe('11')\n  })\n\n  it('should be recomputed without being affected by side effects', () => {\n    const v = ref(0)\n    const c1 = computed(() => {\n      v.value = 1\n      return 0\n    })\n    const c2 = computed(() => {\n      return v.value + ',' + c1.value\n    })\n\n    expect(c2.value).toBe('0,0')\n    v.value = 1\n    expect(c2.value).toBe('1,0')\n    // expect(COMPUTED_SIDE_EFFECT_WARN).toHaveBeenWarned()\n  })\n\n  it('debug: onTrigger (ref)', () => {\n    let events: DebuggerEvent[] = []\n    const onTrigger = vi.fn((e: DebuggerEvent) => {\n      events.push(e)\n    })\n    const obj = ref(1)\n    const c = computed(() => obj.value, { onTrigger })\n\n    // computed won't track until it has a subscriber\n    effect(() => c.value)\n\n    obj.value++\n\n    expect(c.value).toBe(2)\n    expect(onTrigger).toHaveBeenCalledTimes(1)\n    expect(events[0]).toEqual({\n      effect: c,\n      target: toRaw(obj),\n      type: TriggerOpTypes.SET,\n      key: 'value',\n      oldValue: 1,\n      newValue: 2,\n    })\n  })\n\n  // #11797\n  test('should prevent endless recursion in self-referencing computed getters', async () => {\n    const Comp = defineComponent({\n      data() {\n        return {\n          counter: 0,\n        }\n      },\n\n      computed: {\n        message(): string {\n          if (this.counter === 0) {\n            this.counter++\n            return this.message\n          } else {\n            return `Step ${this.counter}`\n          }\n        },\n      },\n\n      render() {\n        return [\n          h(\n            'button',\n            {\n              onClick: () => {\n                this.counter++\n              },\n            },\n            'Step',\n          ),\n          h('p', this.message),\n        ]\n      },\n    })\n    const root = nodeOps.createElement('div')\n    render(h(Comp), root)\n    expect(serializeInner(root)).toBe(`<button>Step</button><p>Step 1</p>`)\n    triggerEvent(root.children[1] as TestElement, 'click')\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<button>Step</button><p>Step 2</p>`)\n  })\n\n  test('manual trigger computed', () => {\n    const cValue = computed(() => 1)\n    triggerRef(cValue)\n    expect(cValue.value).toBe(1)\n  })\n\n  test('should not recompute if computed does not track reactive data', async () => {\n    const spy = vi.fn()\n    const c1 = computed(() => spy())\n\n    c1.value\n    ref(0).value++ // update globalVersion\n    c1.value\n\n    expect(spy).toBeCalledTimes(1)\n  })\n\n  test('computed should remain live after losing all subscribers', () => {\n    const state = reactive({ a: 1 })\n    const p = computed(() => state.a + 1)\n    const { effect: e } = effect(() => p.value)\n    e.stop()\n\n    expect(p.value).toBe(2)\n    state.a++\n    expect(p.value).toBe(3)\n  })\n\n  // #11995\n  test('computed dep cleanup should not cause property dep to be deleted', () => {\n    const toggle = ref(true)\n    const state = reactive({ a: 1 })\n    const p = computed(() => {\n      return toggle.value ? state.a : 111\n    })\n    const pp = computed(() => state.a)\n    effect(() => p.value)\n\n    expect(pp.value).toBe(1)\n    toggle.value = false\n    state.a++\n    expect(pp.value).toBe(2)\n  })\n\n  // #12020\n  test('computed value updates correctly after dep cleanup', () => {\n    const obj = reactive({ foo: 1, flag: 1 })\n    const c1 = computed(() => obj.foo)\n\n    let foo\n    effect(() => {\n      foo = obj.flag ? (obj.foo, c1.value) : 0\n    })\n    expect(foo).toBe(1)\n\n    obj.flag = 0\n    expect(foo).toBe(0)\n\n    obj.foo = 2\n    obj.flag = 1\n    expect(foo).toBe(2)\n  })\n\n  // #11928\n  test('should not lead to exponential perf cost with deeply chained computed', () => {\n    const start = {\n      prop1: shallowRef(1),\n      prop2: shallowRef(2),\n      prop3: shallowRef(3),\n      prop4: shallowRef(4),\n    }\n\n    let layer = start\n\n    const LAYERS = 1000\n\n    for (let i = LAYERS; i > 0; i--) {\n      const m = layer\n      const s = {\n        prop1: computed(() => m.prop2.value),\n        prop2: computed(() => m.prop1.value - m.prop3.value),\n        prop3: computed(() => m.prop2.value + m.prop4.value),\n        prop4: computed(() => m.prop3.value),\n      }\n      effect(() => s.prop1.value)\n      effect(() => s.prop2.value)\n      effect(() => s.prop3.value)\n      effect(() => s.prop4.value)\n\n      s.prop1.value\n      s.prop2.value\n      s.prop3.value\n      s.prop4.value\n\n      layer = s\n    }\n\n    const t = performance.now()\n    start.prop1.value = 4\n    start.prop2.value = 3\n    start.prop3.value = 2\n    start.prop4.value = 1\n    expect(performance.now() - t).toBeLessThan(process.env.CI ? 100 : 30)\n\n    const end = layer\n    expect([\n      end.prop1.value,\n      end.prop2.value,\n      end.prop3.value,\n      end.prop4.value,\n    ]).toMatchObject([-2, -4, 2, 3])\n  })\n\n  test('performance when removing dependencies from deeply nested computeds', () => {\n    const base = ref(1)\n    const trigger = ref(true)\n    const computeds: ComputedRef<number>[] = []\n\n    const LAYERS = 30\n\n    for (let i = 0; i < LAYERS; i++) {\n      const earlier = [...computeds]\n\n      computeds.push(\n        computed(() => {\n          return base.value + earlier.reduce((sum, c) => sum + c.value, 0)\n        }),\n      )\n    }\n\n    const tail = computed(() =>\n      trigger.value ? computeds[computeds.length - 1].value : 0,\n    )\n\n    const t0 = performance.now()\n    expect(tail.value).toBe(2 ** (LAYERS - 1))\n    const t1 = performance.now()\n    expect(t1 - t0).toBeLessThan(process.env.CI ? 100 : 30)\n\n    trigger.value = false\n    expect(tail.value).toBe(0)\n    const t2 = performance.now()\n    expect(t2 - t1).toBeLessThan(process.env.CI ? 100 : 30)\n  })\n})\n"
  },
  {
    "path": "packages/reactivity/__tests__/effect.spec.ts",
    "content": "import {\n  type DebuggerEvent,\n  type ReactiveEffectRunner,\n  TrackOpTypes,\n  TriggerOpTypes,\n  effect,\n  markRaw,\n  reactive,\n  readonly,\n  shallowReactive,\n  stop,\n  toRaw,\n} from '../src/index'\nimport { type Dep, ITERATE_KEY, getDepFromReactive } from '../src/dep'\nimport {\n  computed,\n  h,\n  nextTick,\n  nodeOps,\n  ref,\n  render,\n  serializeInner,\n} from '@vue/runtime-test'\nimport {\n  endBatch,\n  onEffectCleanup,\n  pauseTracking,\n  resetTracking,\n  startBatch,\n} from '../src/effect'\n\ndescribe('reactivity/effect', () => {\n  it('should run the passed function once (wrapped by a effect)', () => {\n    const fnSpy = vi.fn(() => {})\n    effect(fnSpy)\n    expect(fnSpy).toHaveBeenCalledTimes(1)\n  })\n\n  it('should observe basic properties', () => {\n    let dummy\n    const counter = reactive({ num: 0 })\n    effect(() => (dummy = counter.num))\n\n    expect(dummy).toBe(0)\n    counter.num = 7\n    expect(dummy).toBe(7)\n  })\n\n  it('should observe multiple properties', () => {\n    let dummy\n    const counter = reactive({ num1: 0, num2: 0 })\n    effect(() => (dummy = counter.num1 + counter.num1 + counter.num2))\n\n    expect(dummy).toBe(0)\n    counter.num1 = counter.num2 = 7\n    expect(dummy).toBe(21)\n  })\n\n  it('should handle multiple effects', () => {\n    let dummy1, dummy2\n    const counter = reactive({ num: 0 })\n    effect(() => (dummy1 = counter.num))\n    effect(() => (dummy2 = counter.num))\n\n    expect(dummy1).toBe(0)\n    expect(dummy2).toBe(0)\n    counter.num++\n    expect(dummy1).toBe(1)\n    expect(dummy2).toBe(1)\n  })\n\n  it('should observe nested properties', () => {\n    let dummy\n    const counter = reactive({ nested: { num: 0 } })\n    effect(() => (dummy = counter.nested.num))\n\n    expect(dummy).toBe(0)\n    counter.nested.num = 8\n    expect(dummy).toBe(8)\n  })\n\n  it('should observe delete operations', () => {\n    let dummy\n    const obj = reactive<{\n      prop?: string\n    }>({ prop: 'value' })\n    effect(() => (dummy = obj.prop))\n\n    expect(dummy).toBe('value')\n    delete obj.prop\n    expect(dummy).toBe(undefined)\n  })\n\n  it('should observe has operations', () => {\n    let dummy\n    const obj = reactive<{ prop?: string | number }>({ prop: 'value' })\n    effect(() => (dummy = 'prop' in obj))\n\n    expect(dummy).toBe(true)\n    delete obj.prop\n    expect(dummy).toBe(false)\n    obj.prop = 12\n    expect(dummy).toBe(true)\n  })\n\n  it('should observe properties on the prototype chain', () => {\n    let dummy\n    const counter = reactive<{ num?: number }>({ num: 0 })\n    const parentCounter = reactive({ num: 2 })\n    Object.setPrototypeOf(counter, parentCounter)\n    effect(() => (dummy = counter.num))\n\n    expect(dummy).toBe(0)\n    delete counter.num\n    expect(dummy).toBe(2)\n    parentCounter.num = 4\n    expect(dummy).toBe(4)\n    counter.num = 3\n    expect(dummy).toBe(3)\n  })\n\n  it('should observe has operations on the prototype chain', () => {\n    let dummy\n    const counter = reactive<{ num?: number }>({ num: 0 })\n    const parentCounter = reactive<{ num?: number }>({ num: 2 })\n    Object.setPrototypeOf(counter, parentCounter)\n    effect(() => (dummy = 'num' in counter))\n\n    expect(dummy).toBe(true)\n    delete counter.num\n    expect(dummy).toBe(true)\n    delete parentCounter.num\n    expect(dummy).toBe(false)\n    counter.num = 3\n    expect(dummy).toBe(true)\n  })\n\n  it('should observe inherited property accessors', () => {\n    let dummy, parentDummy, hiddenValue: any\n    const obj = reactive<{ prop?: number }>({})\n    const parent = reactive({\n      set prop(value) {\n        hiddenValue = value\n      },\n      get prop() {\n        return hiddenValue\n      },\n    })\n    Object.setPrototypeOf(obj, parent)\n    effect(() => (dummy = obj.prop))\n    effect(() => (parentDummy = parent.prop))\n\n    expect(dummy).toBe(undefined)\n    expect(parentDummy).toBe(undefined)\n    obj.prop = 4\n    expect(dummy).toBe(4)\n    // this doesn't work, should it?\n    // expect(parentDummy).toBe(4)\n    parent.prop = 2\n    expect(dummy).toBe(2)\n    expect(parentDummy).toBe(2)\n  })\n\n  it('should observe function call chains', () => {\n    let dummy\n    const counter = reactive({ num: 0 })\n    effect(() => (dummy = getNum()))\n\n    function getNum() {\n      return counter.num\n    }\n\n    expect(dummy).toBe(0)\n    counter.num = 2\n    expect(dummy).toBe(2)\n  })\n\n  it('should observe iteration', () => {\n    let dummy\n    const list = reactive(['Hello'])\n    effect(() => (dummy = list.join(' ')))\n\n    expect(dummy).toBe('Hello')\n    list.push('World!')\n    expect(dummy).toBe('Hello World!')\n    list.shift()\n    expect(dummy).toBe('World!')\n  })\n\n  it('should observe implicit array length changes', () => {\n    let dummy\n    const list = reactive(['Hello'])\n    effect(() => (dummy = list.join(' ')))\n\n    expect(dummy).toBe('Hello')\n    list[1] = 'World!'\n    expect(dummy).toBe('Hello World!')\n    list[3] = 'Hello!'\n    expect(dummy).toBe('Hello World!  Hello!')\n  })\n\n  it('should observe sparse array mutations', () => {\n    let dummy\n    const list = reactive<string[]>([])\n    list[1] = 'World!'\n    effect(() => (dummy = list.join(' ')))\n\n    expect(dummy).toBe(' World!')\n    list[0] = 'Hello'\n    expect(dummy).toBe('Hello World!')\n    list.pop()\n    expect(dummy).toBe('Hello')\n  })\n\n  it('should observe enumeration', () => {\n    let dummy = 0\n    const numbers = reactive<Record<string, number>>({ num1: 3 })\n    effect(() => {\n      dummy = 0\n      for (let key in numbers) {\n        dummy += numbers[key]\n      }\n    })\n\n    expect(dummy).toBe(3)\n    numbers.num2 = 4\n    expect(dummy).toBe(7)\n    delete numbers.num1\n    expect(dummy).toBe(4)\n  })\n\n  it('should observe symbol keyed properties', () => {\n    const key = Symbol('symbol keyed prop')\n    let dummy, hasDummy\n    const obj = reactive<{ [key]?: string }>({ [key]: 'value' })\n    effect(() => (dummy = obj[key]))\n    effect(() => (hasDummy = key in obj))\n\n    expect(dummy).toBe('value')\n    expect(hasDummy).toBe(true)\n    obj[key] = 'newValue'\n    expect(dummy).toBe('newValue')\n    delete obj[key]\n    expect(dummy).toBe(undefined)\n    expect(hasDummy).toBe(false)\n  })\n\n  it('should not observe well-known symbol keyed properties', () => {\n    const key = Symbol.isConcatSpreadable\n    let dummy\n    const array: any = reactive([])\n    effect(() => (dummy = array[key]))\n\n    expect(array[key]).toBe(undefined)\n    expect(dummy).toBe(undefined)\n    array[key] = true\n    expect(array[key]).toBe(true)\n    expect(dummy).toBe(undefined)\n  })\n\n  it('should not observe well-known symbol keyed properties in has operation', () => {\n    const key = Symbol.isConcatSpreadable\n    const obj = reactive({\n      [key]: true,\n    }) as any\n\n    const spy = vi.fn(() => {\n      key in obj\n    })\n    effect(spy)\n    expect(spy).toHaveBeenCalledTimes(1)\n\n    obj[key] = false\n    expect(spy).toHaveBeenCalledTimes(1)\n  })\n\n  it('should support manipulating an array while observing symbol keyed properties', () => {\n    const key = Symbol()\n    let dummy\n    const array: any = reactive([1, 2, 3])\n    effect(() => (dummy = array[key]))\n\n    expect(dummy).toBe(undefined)\n    array.pop()\n    array.shift()\n    array.splice(0, 1)\n    expect(dummy).toBe(undefined)\n    array[key] = 'value'\n    array.length = 0\n    expect(dummy).toBe('value')\n  })\n\n  it('should observe function valued properties', () => {\n    const oldFunc = () => {}\n    const newFunc = () => {}\n\n    let dummy\n    const obj = reactive({ func: oldFunc })\n    effect(() => (dummy = obj.func))\n\n    expect(dummy).toBe(oldFunc)\n    obj.func = newFunc\n    expect(dummy).toBe(newFunc)\n  })\n\n  it('should observe chained getters relying on this', () => {\n    const obj = reactive({\n      a: 1,\n      get b() {\n        return this.a\n      },\n    })\n\n    let dummy\n    effect(() => (dummy = obj.b))\n    expect(dummy).toBe(1)\n    obj.a++\n    expect(dummy).toBe(2)\n  })\n\n  it('should observe methods relying on this', () => {\n    const obj = reactive({\n      a: 1,\n      b() {\n        return this.a\n      },\n    })\n\n    let dummy\n    effect(() => (dummy = obj.b()))\n    expect(dummy).toBe(1)\n    obj.a++\n    expect(dummy).toBe(2)\n  })\n\n  it('should not observe set operations without a value change', () => {\n    let hasDummy, getDummy\n    const obj = reactive({ prop: 'value' })\n\n    const getSpy = vi.fn(() => (getDummy = obj.prop))\n    const hasSpy = vi.fn(() => (hasDummy = 'prop' in obj))\n    effect(getSpy)\n    effect(hasSpy)\n\n    expect(getDummy).toBe('value')\n    expect(hasDummy).toBe(true)\n    obj.prop = 'value'\n    expect(getSpy).toHaveBeenCalledTimes(1)\n    expect(hasSpy).toHaveBeenCalledTimes(1)\n    expect(getDummy).toBe('value')\n    expect(hasDummy).toBe(true)\n  })\n\n  it('should not observe raw mutations', () => {\n    let dummy\n    const obj = reactive<{ prop?: string }>({})\n    effect(() => (dummy = toRaw(obj).prop))\n\n    expect(dummy).toBe(undefined)\n    obj.prop = 'value'\n    expect(dummy).toBe(undefined)\n  })\n\n  it('should not be triggered by raw mutations', () => {\n    let dummy\n    const obj = reactive<{ prop?: string }>({})\n    effect(() => (dummy = obj.prop))\n\n    expect(dummy).toBe(undefined)\n    toRaw(obj).prop = 'value'\n    expect(dummy).toBe(undefined)\n  })\n\n  it('should not be triggered by inherited raw setters', () => {\n    let dummy, parentDummy, hiddenValue: any\n    const obj = reactive<{ prop?: number }>({})\n    const parent = reactive({\n      set prop(value) {\n        hiddenValue = value\n      },\n      get prop() {\n        return hiddenValue\n      },\n    })\n    Object.setPrototypeOf(obj, parent)\n    effect(() => (dummy = obj.prop))\n    effect(() => (parentDummy = parent.prop))\n\n    expect(dummy).toBe(undefined)\n    expect(parentDummy).toBe(undefined)\n    toRaw(obj).prop = 4\n    expect(dummy).toBe(undefined)\n    expect(parentDummy).toBe(undefined)\n  })\n\n  it('should avoid implicit infinite recursive loops with itself', () => {\n    const counter = reactive({ num: 0 })\n\n    const counterSpy = vi.fn(() => counter.num++)\n    effect(counterSpy)\n    expect(counter.num).toBe(1)\n    expect(counterSpy).toHaveBeenCalledTimes(1)\n    counter.num = 4\n    expect(counter.num).toBe(5)\n    expect(counterSpy).toHaveBeenCalledTimes(2)\n  })\n\n  it('should avoid infinite recursive loops when use Array.prototype.push/unshift/pop/shift', () => {\n    ;(['push', 'unshift'] as const).forEach(key => {\n      const arr = reactive<number[]>([])\n      const counterSpy1 = vi.fn(() => (arr[key] as any)(1))\n      const counterSpy2 = vi.fn(() => (arr[key] as any)(2))\n      effect(counterSpy1)\n      effect(counterSpy2)\n      expect(arr.length).toBe(2)\n      expect(counterSpy1).toHaveBeenCalledTimes(1)\n      expect(counterSpy2).toHaveBeenCalledTimes(1)\n    })\n    ;(['pop', 'shift'] as const).forEach(key => {\n      const arr = reactive<number[]>([1, 2, 3, 4])\n      const counterSpy1 = vi.fn(() => (arr[key] as any)())\n      const counterSpy2 = vi.fn(() => (arr[key] as any)())\n      effect(counterSpy1)\n      effect(counterSpy2)\n      expect(arr.length).toBe(2)\n      expect(counterSpy1).toHaveBeenCalledTimes(1)\n      expect(counterSpy2).toHaveBeenCalledTimes(1)\n    })\n  })\n\n  it('should allow explicitly recursive raw function loops', () => {\n    const counter = reactive({ num: 0 })\n    const numSpy = vi.fn(() => {\n      counter.num++\n      if (counter.num < 10) {\n        numSpy()\n      }\n    })\n    effect(numSpy)\n    expect(counter.num).toEqual(10)\n    expect(numSpy).toHaveBeenCalledTimes(10)\n  })\n\n  it('should avoid infinite loops with other effects', () => {\n    const nums = reactive({ num1: 0, num2: 1 })\n\n    const spy1 = vi.fn(() => (nums.num1 = nums.num2))\n    const spy2 = vi.fn(() => (nums.num2 = nums.num1))\n    effect(spy1)\n    effect(spy2)\n    expect(nums.num1).toBe(1)\n    expect(nums.num2).toBe(1)\n    expect(spy1).toHaveBeenCalledTimes(1)\n    expect(spy2).toHaveBeenCalledTimes(1)\n    nums.num2 = 4\n    expect(nums.num1).toBe(4)\n    expect(nums.num2).toBe(4)\n    expect(spy1).toHaveBeenCalledTimes(2)\n    expect(spy2).toHaveBeenCalledTimes(2)\n    nums.num1 = 10\n    expect(nums.num1).toBe(10)\n    expect(nums.num2).toBe(10)\n    expect(spy1).toHaveBeenCalledTimes(3)\n    expect(spy2).toHaveBeenCalledTimes(3)\n  })\n\n  it('should return a new reactive version of the function', () => {\n    function greet() {\n      return 'Hello World'\n    }\n    const effect1 = effect(greet)\n    const effect2 = effect(greet)\n    expect(typeof effect1).toBe('function')\n    expect(typeof effect2).toBe('function')\n    expect(effect1).not.toBe(greet)\n    expect(effect1).not.toBe(effect2)\n  })\n\n  it('should discover new branches while running automatically', () => {\n    let dummy\n    const obj = reactive({ prop: 'value', run: false })\n\n    const conditionalSpy = vi.fn(() => {\n      dummy = obj.run ? obj.prop : 'other'\n    })\n    effect(conditionalSpy)\n\n    expect(dummy).toBe('other')\n    expect(conditionalSpy).toHaveBeenCalledTimes(1)\n    obj.prop = 'Hi'\n    expect(dummy).toBe('other')\n    expect(conditionalSpy).toHaveBeenCalledTimes(1)\n    obj.run = true\n    expect(dummy).toBe('Hi')\n    expect(conditionalSpy).toHaveBeenCalledTimes(2)\n    obj.prop = 'World'\n    expect(dummy).toBe('World')\n    expect(conditionalSpy).toHaveBeenCalledTimes(3)\n  })\n\n  it('should discover new branches when running manually', () => {\n    let dummy\n    let run = false\n    const obj = reactive({ prop: 'value' })\n    const runner = effect(() => {\n      dummy = run ? obj.prop : 'other'\n    })\n\n    expect(dummy).toBe('other')\n    runner()\n    expect(dummy).toBe('other')\n    run = true\n    runner()\n    expect(dummy).toBe('value')\n    obj.prop = 'World'\n    expect(dummy).toBe('World')\n  })\n\n  it('should not be triggered by mutating a property, which is used in an inactive branch', () => {\n    let dummy\n    const obj = reactive({ prop: 'value', run: true })\n\n    const conditionalSpy = vi.fn(() => {\n      dummy = obj.run ? obj.prop : 'other'\n    })\n    effect(conditionalSpy)\n\n    expect(dummy).toBe('value')\n    expect(conditionalSpy).toHaveBeenCalledTimes(1)\n    obj.run = false\n    expect(dummy).toBe('other')\n    expect(conditionalSpy).toHaveBeenCalledTimes(2)\n    obj.prop = 'value2'\n    expect(dummy).toBe('other')\n    expect(conditionalSpy).toHaveBeenCalledTimes(2)\n  })\n\n  it('should handle deep effect recursion using cleanup fallback', () => {\n    const results = reactive([0])\n    const effects: { fx: ReactiveEffectRunner; index: number }[] = []\n    for (let i = 1; i < 40; i++) {\n      ;(index => {\n        const fx = effect(() => {\n          results[index] = results[index - 1] * 2\n        })\n        effects.push({ fx, index })\n      })(i)\n    }\n\n    expect(results[39]).toBe(0)\n    results[0] = 1\n    expect(results[39]).toBe(Math.pow(2, 39))\n  })\n\n  it('should register deps independently during effect recursion', () => {\n    const input = reactive({ a: 1, b: 2, c: 0 })\n    const output = reactive({ fx1: 0, fx2: 0 })\n\n    const fx1Spy = vi.fn(() => {\n      let result = 0\n      if (input.c < 2) result += input.a\n      if (input.c > 1) result += input.b\n      output.fx1 = result\n    })\n\n    const fx1 = effect(fx1Spy)\n\n    const fx2Spy = vi.fn(() => {\n      let result = 0\n      if (input.c > 1) result += input.a\n      if (input.c < 3) result += input.b\n      output.fx2 = result + output.fx1\n    })\n\n    const fx2 = effect(fx2Spy)\n\n    expect(fx1).not.toBeNull()\n    expect(fx2).not.toBeNull()\n\n    expect(output.fx1).toBe(1)\n    expect(output.fx2).toBe(2 + 1)\n    expect(fx1Spy).toHaveBeenCalledTimes(1)\n    expect(fx2Spy).toHaveBeenCalledTimes(1)\n\n    fx1Spy.mockClear()\n    fx2Spy.mockClear()\n    input.b = 3\n    expect(output.fx1).toBe(1)\n    expect(output.fx2).toBe(3 + 1)\n    expect(fx1Spy).toHaveBeenCalledTimes(0)\n    expect(fx2Spy).toHaveBeenCalledTimes(1)\n\n    fx1Spy.mockClear()\n    fx2Spy.mockClear()\n    input.c = 1\n    expect(output.fx1).toBe(1)\n    expect(output.fx2).toBe(3 + 1)\n    expect(fx1Spy).toHaveBeenCalledTimes(1)\n    expect(fx2Spy).toHaveBeenCalledTimes(1)\n\n    fx1Spy.mockClear()\n    fx2Spy.mockClear()\n    input.c = 2\n    expect(output.fx1).toBe(3)\n    expect(output.fx2).toBe(1 + 3 + 3)\n    expect(fx1Spy).toHaveBeenCalledTimes(1)\n\n    // Invoked due to change of fx1.\n    expect(fx2Spy).toHaveBeenCalledTimes(1)\n\n    fx1Spy.mockClear()\n    fx2Spy.mockClear()\n    input.c = 3\n    expect(output.fx1).toBe(3)\n    expect(output.fx2).toBe(1 + 3)\n    expect(fx1Spy).toHaveBeenCalledTimes(1)\n    expect(fx2Spy).toHaveBeenCalledTimes(1)\n\n    fx1Spy.mockClear()\n    fx2Spy.mockClear()\n    input.a = 10\n    expect(output.fx1).toBe(3)\n    expect(output.fx2).toBe(10 + 3)\n    expect(fx1Spy).toHaveBeenCalledTimes(0)\n    expect(fx2Spy).toHaveBeenCalledTimes(1)\n  })\n\n  it('should not double wrap if the passed function is a effect', () => {\n    const runner = effect(() => {})\n    const otherRunner = effect(runner)\n    expect(runner).not.toBe(otherRunner)\n    expect(runner.effect.fn).toBe(otherRunner.effect.fn)\n  })\n\n  it('should wrap if the passed function is a fake effect', () => {\n    const fakeRunner = () => {}\n    fakeRunner.effect = {}\n    const runner = effect(fakeRunner)\n    expect(fakeRunner).not.toBe(runner)\n    expect(runner.effect.fn).toBe(fakeRunner)\n  })\n\n  it('should not run multiple times for a single mutation', () => {\n    let dummy\n    const obj = reactive<Record<string, number>>({})\n    const fnSpy = vi.fn(() => {\n      for (const key in obj) {\n        dummy = obj[key]\n      }\n      dummy = obj.prop\n    })\n    effect(fnSpy)\n\n    expect(fnSpy).toHaveBeenCalledTimes(1)\n    obj.prop = 16\n    expect(dummy).toBe(16)\n    expect(fnSpy).toHaveBeenCalledTimes(2)\n  })\n\n  it('should allow nested effects', () => {\n    const nums = reactive({ num1: 0, num2: 1, num3: 2 })\n    const dummy: any = {}\n\n    const childSpy = vi.fn(() => (dummy.num1 = nums.num1))\n    const childeffect = effect(childSpy)\n    const parentSpy = vi.fn(() => {\n      dummy.num2 = nums.num2\n      childeffect()\n      dummy.num3 = nums.num3\n    })\n    effect(parentSpy)\n\n    expect(dummy).toEqual({ num1: 0, num2: 1, num3: 2 })\n    expect(parentSpy).toHaveBeenCalledTimes(1)\n    expect(childSpy).toHaveBeenCalledTimes(2)\n    // this should only call the childeffect\n    nums.num1 = 4\n    expect(dummy).toEqual({ num1: 4, num2: 1, num3: 2 })\n    expect(parentSpy).toHaveBeenCalledTimes(1)\n    expect(childSpy).toHaveBeenCalledTimes(3)\n    // this calls the parenteffect, which calls the childeffect once\n    nums.num2 = 10\n    expect(dummy).toEqual({ num1: 4, num2: 10, num3: 2 })\n    expect(parentSpy).toHaveBeenCalledTimes(2)\n    expect(childSpy).toHaveBeenCalledTimes(4)\n    // this calls the parenteffect, which calls the childeffect once\n    nums.num3 = 7\n    expect(dummy).toEqual({ num1: 4, num2: 10, num3: 7 })\n    expect(parentSpy).toHaveBeenCalledTimes(3)\n    expect(childSpy).toHaveBeenCalledTimes(5)\n  })\n\n  it('should observe json methods', () => {\n    let dummy = <Record<string, number>>{}\n    const obj = reactive<Record<string, number>>({})\n    effect(() => {\n      dummy = JSON.parse(JSON.stringify(obj))\n    })\n    obj.a = 1\n    expect(dummy.a).toBe(1)\n  })\n\n  it('should observe class method invocations', () => {\n    class Model {\n      count: number\n      constructor() {\n        this.count = 0\n      }\n      inc() {\n        this.count++\n      }\n    }\n    const model = reactive(new Model())\n    let dummy\n    effect(() => {\n      dummy = model.count\n    })\n    expect(dummy).toBe(0)\n    model.inc()\n    expect(dummy).toBe(1)\n  })\n\n  it('scheduler', () => {\n    let dummy\n    let run: any\n    const scheduler = vi.fn(() => {\n      run = runner\n    })\n    const obj = reactive({ foo: 1 })\n    const runner = effect(\n      () => {\n        dummy = obj.foo\n      },\n      { scheduler },\n    )\n    expect(scheduler).not.toHaveBeenCalled()\n    expect(dummy).toBe(1)\n    // should be called on first trigger\n    obj.foo++\n    expect(scheduler).toHaveBeenCalledTimes(1)\n    // should not run yet\n    expect(dummy).toBe(1)\n    // manually run\n    run()\n    // should have run\n    expect(dummy).toBe(2)\n  })\n\n  it('events: onTrack', () => {\n    let events: DebuggerEvent[] = []\n    let dummy\n    const onTrack = vi.fn((e: DebuggerEvent) => {\n      events.push(e)\n    })\n    const obj = reactive({ foo: 1, bar: 2 })\n    const runner = effect(\n      () => {\n        dummy = obj.foo\n        dummy = 'bar' in obj\n        dummy = Object.keys(obj)\n      },\n      { onTrack },\n    )\n    expect(dummy).toEqual(['foo', 'bar'])\n    expect(onTrack).toHaveBeenCalledTimes(3)\n    expect(events).toEqual([\n      {\n        effect: runner.effect,\n        target: toRaw(obj),\n        type: TrackOpTypes.GET,\n        key: 'foo',\n      },\n      {\n        effect: runner.effect,\n        target: toRaw(obj),\n        type: TrackOpTypes.HAS,\n        key: 'bar',\n      },\n      {\n        effect: runner.effect,\n        target: toRaw(obj),\n        type: TrackOpTypes.ITERATE,\n        key: ITERATE_KEY,\n      },\n    ])\n  })\n\n  it('debug: the call sequence of onTrack', () => {\n    const seq: number[] = []\n    const s = ref(0)\n\n    const track1 = () => seq.push(1)\n    const track2 = () => seq.push(2)\n\n    effect(\n      () => {\n        s.value\n      },\n      {\n        onTrack: track1,\n      },\n    )\n    effect(\n      () => {\n        s.value\n      },\n      {\n        onTrack: track2,\n      },\n    )\n    expect(seq.toString()).toBe('1,2')\n  })\n\n  it('events: onTrigger', () => {\n    let events: DebuggerEvent[] = []\n    let dummy\n    const onTrigger = vi.fn((e: DebuggerEvent) => {\n      events.push(e)\n    })\n    const obj = reactive<{ foo?: number }>({ foo: 1 })\n    const runner = effect(\n      () => {\n        dummy = obj.foo\n      },\n      { onTrigger },\n    )\n\n    obj.foo!++\n    expect(dummy).toBe(2)\n    expect(onTrigger).toHaveBeenCalledTimes(1)\n    expect(events[0]).toEqual({\n      effect: runner.effect,\n      target: toRaw(obj),\n      type: TriggerOpTypes.SET,\n      key: 'foo',\n      oldValue: 1,\n      newValue: 2,\n    })\n\n    delete obj.foo\n    expect(dummy).toBeUndefined()\n    expect(onTrigger).toHaveBeenCalledTimes(2)\n    expect(events[1]).toEqual({\n      effect: runner.effect,\n      target: toRaw(obj),\n      type: TriggerOpTypes.DELETE,\n      key: 'foo',\n      oldValue: 2,\n    })\n  })\n\n  it('debug: the call sequence of onTrigger', () => {\n    const seq: number[] = []\n    const s = ref(0)\n\n    const trigger1 = () => seq.push(1)\n    const trigger2 = () => seq.push(2)\n    const trigger3 = () => seq.push(3)\n    const trigger4 = () => seq.push(4)\n\n    effect(\n      () => {\n        s.value\n      },\n      {\n        onTrigger: trigger1,\n      },\n    )\n    effect(\n      () => {\n        s.value\n        effect(\n          () => {\n            s.value\n            effect(\n              () => {\n                s.value\n              },\n              {\n                onTrigger: trigger4,\n              },\n            )\n          },\n          {\n            onTrigger: trigger3,\n          },\n        )\n      },\n      {\n        onTrigger: trigger2,\n      },\n    )\n    s.value++\n    expect(seq.toString()).toBe('1,2,3,4')\n  })\n\n  it('stop', () => {\n    let dummy\n    const obj = reactive({ prop: 1 })\n    const runner = effect(() => {\n      dummy = obj.prop\n    })\n    obj.prop = 2\n    expect(dummy).toBe(2)\n    stop(runner)\n    obj.prop = 3\n    expect(dummy).toBe(2)\n\n    // stopped effect should still be manually callable\n    runner()\n    expect(dummy).toBe(3)\n  })\n\n  it('stop with multiple dependencies', () => {\n    let dummy1, dummy2\n    const obj1 = reactive({ prop: 1 })\n    const obj2 = reactive({ prop: 1 })\n    const runner = effect(() => {\n      dummy1 = obj1.prop\n      dummy2 = obj2.prop\n    })\n\n    obj1.prop = 2\n    expect(dummy1).toBe(2)\n\n    obj2.prop = 3\n    expect(dummy2).toBe(3)\n\n    stop(runner)\n\n    obj1.prop = 4\n    obj2.prop = 5\n\n    // Check that both dependencies have been cleared\n    expect(dummy1).toBe(2)\n    expect(dummy2).toBe(3)\n  })\n\n  it('events: onStop', () => {\n    const onStop = vi.fn()\n    const runner = effect(() => {}, {\n      onStop,\n    })\n\n    stop(runner)\n    expect(onStop).toHaveBeenCalled()\n  })\n\n  it('stop: a stopped effect is nested in a normal effect', () => {\n    let dummy\n    const obj = reactive({ prop: 1 })\n    const runner = effect(() => {\n      dummy = obj.prop\n    })\n    stop(runner)\n    obj.prop = 2\n    expect(dummy).toBe(1)\n\n    // observed value in inner stopped effect\n    // will track outer effect as an dependency\n    effect(() => {\n      runner()\n    })\n    expect(dummy).toBe(2)\n\n    // notify outer effect to run\n    obj.prop = 3\n    expect(dummy).toBe(3)\n  })\n\n  it('markRaw', () => {\n    const obj = reactive({\n      foo: markRaw({\n        prop: 0,\n      }),\n    })\n    let dummy\n    effect(() => {\n      dummy = obj.foo.prop\n    })\n    expect(dummy).toBe(0)\n    obj.foo.prop++\n    expect(dummy).toBe(0)\n    obj.foo = { prop: 1 }\n    expect(dummy).toBe(1)\n  })\n\n  it('should not be triggered when the value and the old value both are NaN', () => {\n    const obj = reactive({\n      foo: NaN,\n    })\n    const fnSpy = vi.fn(() => obj.foo)\n    effect(fnSpy)\n    obj.foo = NaN\n    expect(fnSpy).toHaveBeenCalledTimes(1)\n  })\n\n  it('should trigger all effects when array length is set to 0', () => {\n    const observed: any = reactive([1])\n    let dummy, record\n    effect(() => {\n      dummy = observed.length\n    })\n    effect(() => {\n      record = observed[0]\n    })\n    expect(dummy).toBe(1)\n    expect(record).toBe(1)\n\n    observed[1] = 2\n    expect(observed[1]).toBe(2)\n\n    observed.unshift(3)\n    expect(dummy).toBe(3)\n    expect(record).toBe(3)\n\n    observed.length = 0\n    expect(dummy).toBe(0)\n    expect(record).toBeUndefined()\n  })\n\n  it('should not be triggered when set with the same proxy', () => {\n    const obj = reactive({ foo: 1 })\n    const observed: any = reactive({ obj })\n    const fnSpy = vi.fn(() => observed.obj)\n\n    effect(fnSpy)\n\n    expect(fnSpy).toHaveBeenCalledTimes(1)\n    observed.obj = obj\n    expect(fnSpy).toHaveBeenCalledTimes(1)\n\n    const obj2 = reactive({ foo: 1 })\n    const observed2: any = shallowReactive({ obj2 })\n    const fnSpy2 = vi.fn(() => observed2.obj2)\n\n    effect(fnSpy2)\n\n    expect(fnSpy2).toHaveBeenCalledTimes(1)\n    observed2.obj2 = obj2\n    expect(fnSpy2).toHaveBeenCalledTimes(1)\n  })\n\n  it('should be triggered when set length with string', () => {\n    let ret1 = 'idle'\n    let ret2 = 'idle'\n    const arr1 = reactive(new Array(11).fill(0))\n    const arr2 = reactive(new Array(11).fill(0))\n    effect(() => {\n      ret1 = arr1[10] === undefined ? 'arr[10] is set to empty' : 'idle'\n    })\n    effect(() => {\n      ret2 = arr2[10] === undefined ? 'arr[10] is set to empty' : 'idle'\n    })\n    arr1.length = 2\n    arr2.length = '2' as any\n    expect(ret1).toBe(ret2)\n  })\n\n  describe('readonly + reactive for Map', () => {\n    test('should work with readonly(reactive(Map))', () => {\n      const m = reactive(new Map())\n      const roM = readonly(m)\n      const fnSpy = vi.fn(() => roM.get(1))\n\n      effect(fnSpy)\n      expect(fnSpy).toHaveBeenCalledTimes(1)\n      m.set(1, 1)\n      expect(fnSpy).toHaveBeenCalledTimes(2)\n    })\n\n    test('should work with observed value as key', () => {\n      const key = reactive({})\n      const m = reactive(new Map())\n      m.set(key, 1)\n      const roM = readonly(m)\n      const fnSpy = vi.fn(() => roM.get(key))\n\n      effect(fnSpy)\n      expect(fnSpy).toHaveBeenCalledTimes(1)\n      m.set(key, 1)\n      expect(fnSpy).toHaveBeenCalledTimes(1)\n      m.set(key, 2)\n      expect(fnSpy).toHaveBeenCalledTimes(2)\n    })\n\n    test('should track hasOwnProperty', () => {\n      const obj: any = reactive({})\n      let has = false\n      const fnSpy = vi.fn()\n\n      effect(() => {\n        fnSpy()\n        has = obj.hasOwnProperty('foo')\n      })\n      expect(fnSpy).toHaveBeenCalledTimes(1)\n      expect(has).toBe(false)\n\n      obj.foo = 1\n      expect(fnSpy).toHaveBeenCalledTimes(2)\n      expect(has).toBe(true)\n\n      delete obj.foo\n      expect(fnSpy).toHaveBeenCalledTimes(3)\n      expect(has).toBe(false)\n\n      // should not trigger on unrelated key\n      obj.bar = 2\n      expect(fnSpy).toHaveBeenCalledTimes(3)\n      expect(has).toBe(false)\n    })\n  })\n\n  it('should be triggered once with batching', () => {\n    const counter = reactive({ num: 0 })\n\n    const counterSpy = vi.fn(() => counter.num)\n    effect(counterSpy)\n\n    counterSpy.mockClear()\n\n    startBatch()\n    counter.num++\n    counter.num++\n    endBatch()\n    expect(counterSpy).toHaveBeenCalledTimes(1)\n  })\n\n  // #10082\n  it('should set dirtyLevel when effect is allowRecurse and is running', async () => {\n    const s = ref(0)\n    const n = computed(() => s.value + 1)\n\n    const Child = {\n      setup() {\n        s.value++\n        return () => n.value\n      },\n    }\n\n    const renderSpy = vi.fn()\n    const Parent = {\n      setup() {\n        return () => {\n          renderSpy()\n          return [n.value, h(Child)]\n        }\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(Parent), root)\n    await nextTick()\n    expect(serializeInner(root)).toBe('22')\n    expect(renderSpy).toHaveBeenCalledTimes(2)\n  })\n\n  it('nested effect should force track in untracked zone', () => {\n    const n = ref(0)\n    const spy1 = vi.fn()\n    const spy2 = vi.fn()\n\n    effect(() => {\n      spy1()\n      pauseTracking()\n      n.value\n      effect(() => {\n        n.value\n        spy2()\n      })\n      n.value\n      resetTracking()\n    })\n\n    expect(spy1).toHaveBeenCalledTimes(1)\n    expect(spy2).toHaveBeenCalledTimes(1)\n\n    n.value++\n    // outer effect should not trigger\n    expect(spy1).toHaveBeenCalledTimes(1)\n    // inner effect should trigger\n    expect(spy2).toHaveBeenCalledTimes(2)\n  })\n\n  describe('dep unsubscribe', () => {\n    function getSubCount(dep: Dep | undefined) {\n      let count = 0\n      let sub = dep!.subs\n      while (sub) {\n        count++\n        sub = sub.prevSub\n      }\n      return count\n    }\n\n    it('should remove the dep when the effect is stopped', () => {\n      const obj = reactive({ prop: 1 })\n      const runner = effect(() => obj.prop)\n      const dep = getDepFromReactive(toRaw(obj), 'prop')\n      expect(getSubCount(dep)).toBe(1)\n      obj.prop = 2\n      expect(getSubCount(dep)).toBe(1)\n      stop(runner)\n      expect(getSubCount(dep)).toBe(0)\n      obj.prop = 3\n      runner()\n      expect(getSubCount(dep)).toBe(0)\n    })\n\n    it('should only remove the dep when the last effect is stopped', () => {\n      const obj = reactive({ prop: 1 })\n      const runner1 = effect(() => obj.prop)\n      const dep = getDepFromReactive(toRaw(obj), 'prop')\n      expect(getSubCount(dep)).toBe(1)\n      const runner2 = effect(() => obj.prop)\n      expect(getSubCount(dep)).toBe(2)\n      obj.prop = 2\n      expect(getSubCount(dep)).toBe(2)\n      stop(runner1)\n      expect(getSubCount(dep)).toBe(1)\n      obj.prop = 3\n      expect(getSubCount(dep)).toBe(1)\n      stop(runner2)\n      obj.prop = 4\n      runner1()\n      runner2()\n      expect(getSubCount(dep)).toBe(0)\n    })\n\n    it('should remove the dep when it is no longer used by the effect', () => {\n      const obj = reactive<{ a: number; b: number; c: 'a' | 'b' }>({\n        a: 1,\n        b: 2,\n        c: 'a',\n      })\n      effect(() => obj[obj.c])\n      const depC = getDepFromReactive(toRaw(obj), 'c')\n      expect(getSubCount(getDepFromReactive(toRaw(obj), 'a'))).toBe(1)\n      expect(getSubCount(depC)).toBe(1)\n      obj.c = 'b'\n      obj.a = 4\n      expect(getSubCount(getDepFromReactive(toRaw(obj), 'b'))).toBe(1)\n      expect(getDepFromReactive(toRaw(obj), 'c')).toBe(depC)\n      expect(getSubCount(depC)).toBe(1)\n    })\n  })\n\n  describe('onEffectCleanup', () => {\n    it('should get called correctly', async () => {\n      const count = ref(0)\n      const cleanupEffect = vi.fn()\n\n      const e = effect(() => {\n        onEffectCleanup(cleanupEffect)\n        count.value\n      })\n\n      count.value++\n      await nextTick()\n      expect(cleanupEffect).toHaveBeenCalledTimes(1)\n\n      count.value++\n      await nextTick()\n      expect(cleanupEffect).toHaveBeenCalledTimes(2)\n\n      // call it on stop\n      e.effect.stop()\n      expect(cleanupEffect).toHaveBeenCalledTimes(3)\n    })\n\n    it('should warn if called without active effect', () => {\n      onEffectCleanup(() => {})\n      expect(\n        `onEffectCleanup() was called when there was no active effect`,\n      ).toHaveBeenWarned()\n    })\n\n    it('should not warn without active effect when failSilently argument is passed', () => {\n      onEffectCleanup(() => {}, true)\n      expect(\n        `onEffectCleanup() was called when there was no active effect`,\n      ).not.toHaveBeenWarned()\n    })\n  })\n\n  test('should pause/resume effect', () => {\n    const obj = reactive({ foo: 1 })\n    const fnSpy = vi.fn(() => obj.foo)\n    const runner = effect(fnSpy)\n\n    expect(fnSpy).toHaveBeenCalledTimes(1)\n    expect(obj.foo).toBe(1)\n\n    runner.effect.pause()\n    obj.foo++\n    expect(fnSpy).toHaveBeenCalledTimes(1)\n    expect(obj.foo).toBe(2)\n\n    runner.effect.resume()\n    expect(fnSpy).toHaveBeenCalledTimes(2)\n    expect(obj.foo).toBe(2)\n\n    obj.foo++\n    expect(fnSpy).toHaveBeenCalledTimes(3)\n    expect(obj.foo).toBe(3)\n  })\n\n  test('should be executed once immediately when resume is called', () => {\n    const obj = reactive({ foo: 1 })\n    const fnSpy = vi.fn(() => obj.foo)\n    const runner = effect(fnSpy)\n\n    expect(fnSpy).toHaveBeenCalledTimes(1)\n    expect(obj.foo).toBe(1)\n\n    runner.effect.pause()\n    obj.foo++\n    expect(fnSpy).toHaveBeenCalledTimes(1)\n    expect(obj.foo).toBe(2)\n\n    obj.foo++\n    expect(fnSpy).toHaveBeenCalledTimes(1)\n    expect(obj.foo).toBe(3)\n\n    runner.effect.resume()\n    expect(fnSpy).toHaveBeenCalledTimes(2)\n    expect(obj.foo).toBe(3)\n  })\n})\n"
  },
  {
    "path": "packages/reactivity/__tests__/effectScope.spec.ts",
    "content": "import { nextTick, watch, watchEffect } from '@vue/runtime-core'\nimport {\n  type ComputedRef,\n  EffectScope,\n  computed,\n  effect,\n  effectScope,\n  getCurrentScope,\n  onScopeDispose,\n  reactive,\n  ref,\n} from '../src'\n\ndescribe('reactivity/effect/scope', () => {\n  it('should run', () => {\n    const fnSpy = vi.fn(() => {})\n    effectScope().run(fnSpy)\n    expect(fnSpy).toHaveBeenCalledTimes(1)\n  })\n\n  it('should accept zero argument', () => {\n    const scope = effectScope()\n    expect(scope.effects.length).toBe(0)\n  })\n\n  it('should return run value', () => {\n    expect(effectScope().run(() => 1)).toBe(1)\n  })\n\n  it('should work w/ active property', () => {\n    const scope = effectScope()\n    scope.run(() => 1)\n    expect(scope.active).toBe(true)\n    scope.stop()\n    expect(scope.active).toBe(false)\n  })\n\n  it('should collect the effects', () => {\n    const scope = effectScope()\n    scope.run(() => {\n      let dummy\n      const counter = reactive({ num: 0 })\n      effect(() => (dummy = counter.num))\n\n      expect(dummy).toBe(0)\n      counter.num = 7\n      expect(dummy).toBe(7)\n    })\n\n    expect(scope.effects.length).toBe(1)\n  })\n\n  it('stop', () => {\n    let dummy, doubled\n    const counter = reactive({ num: 0 })\n\n    const scope = effectScope()\n    scope.run(() => {\n      effect(() => (dummy = counter.num))\n      effect(() => (doubled = counter.num * 2))\n    })\n\n    expect(scope.effects.length).toBe(2)\n\n    expect(dummy).toBe(0)\n    counter.num = 7\n    expect(dummy).toBe(7)\n    expect(doubled).toBe(14)\n\n    scope.stop()\n\n    counter.num = 6\n    expect(dummy).toBe(7)\n    expect(doubled).toBe(14)\n  })\n\n  it('should collect nested scope', () => {\n    let dummy, doubled\n    const counter = reactive({ num: 0 })\n\n    const scope = effectScope()\n    scope.run(() => {\n      effect(() => (dummy = counter.num))\n      // nested scope\n      effectScope().run(() => {\n        effect(() => (doubled = counter.num * 2))\n      })\n    })\n\n    expect(scope.effects.length).toBe(1)\n    expect(scope.scopes!.length).toBe(1)\n    expect(scope.scopes![0]).toBeInstanceOf(EffectScope)\n\n    expect(dummy).toBe(0)\n    counter.num = 7\n    expect(dummy).toBe(7)\n    expect(doubled).toBe(14)\n\n    // stop the nested scope as well\n    scope.stop()\n\n    counter.num = 6\n    expect(dummy).toBe(7)\n    expect(doubled).toBe(14)\n  })\n\n  it('nested scope can be escaped', () => {\n    let dummy, doubled\n    const counter = reactive({ num: 0 })\n\n    const scope = effectScope()\n    scope.run(() => {\n      effect(() => (dummy = counter.num))\n      // nested scope\n      effectScope(true).run(() => {\n        effect(() => (doubled = counter.num * 2))\n      })\n    })\n\n    expect(scope.effects.length).toBe(1)\n\n    expect(dummy).toBe(0)\n    counter.num = 7\n    expect(dummy).toBe(7)\n    expect(doubled).toBe(14)\n\n    scope.stop()\n\n    counter.num = 6\n    expect(dummy).toBe(7)\n\n    // nested scope should not be stopped\n    expect(doubled).toBe(12)\n  })\n\n  it('able to run the scope', () => {\n    let dummy, doubled\n    const counter = reactive({ num: 0 })\n\n    const scope = effectScope()\n    scope.run(() => {\n      effect(() => (dummy = counter.num))\n    })\n\n    expect(scope.effects.length).toBe(1)\n\n    scope.run(() => {\n      effect(() => (doubled = counter.num * 2))\n    })\n\n    expect(scope.effects.length).toBe(2)\n\n    counter.num = 7\n    expect(dummy).toBe(7)\n    expect(doubled).toBe(14)\n\n    scope.stop()\n  })\n\n  it('can not run an inactive scope', () => {\n    let dummy, doubled\n    const counter = reactive({ num: 0 })\n\n    const scope = effectScope()\n    scope.run(() => {\n      effect(() => (dummy = counter.num))\n    })\n\n    expect(scope.effects.length).toBe(1)\n\n    scope.stop()\n\n    scope.run(() => {\n      effect(() => (doubled = counter.num * 2))\n    })\n\n    expect('[Vue warn] cannot run an inactive effect scope.').toHaveBeenWarned()\n\n    expect(scope.effects.length).toBe(0)\n\n    counter.num = 7\n    expect(dummy).toBe(0)\n    expect(doubled).toBe(undefined)\n  })\n\n  it('should fire onScopeDispose hook', () => {\n    let dummy = 0\n\n    const scope = effectScope()\n    scope.run(() => {\n      onScopeDispose(() => (dummy += 1))\n      onScopeDispose(() => (dummy += 2))\n    })\n\n    scope.run(() => {\n      onScopeDispose(() => (dummy += 4))\n    })\n\n    expect(dummy).toBe(0)\n\n    scope.stop()\n    expect(dummy).toBe(7)\n  })\n\n  it('should warn onScopeDispose() is called when there is no active effect scope', () => {\n    const spy = vi.fn()\n    const scope = effectScope()\n    scope.run(() => {\n      onScopeDispose(spy)\n    })\n\n    expect(spy).toHaveBeenCalledTimes(0)\n\n    onScopeDispose(spy)\n\n    expect(\n      '[Vue warn] onScopeDispose() is called when there is no active effect scope to be associated with.',\n    ).toHaveBeenWarned()\n\n    scope.stop()\n    expect(spy).toHaveBeenCalledTimes(1)\n  })\n\n  it('should dereference child scope from parent scope after stopping child scope (no memleaks)', () => {\n    const parent = effectScope()\n    const child = parent.run(() => effectScope())!\n    expect(parent.scopes!.includes(child)).toBe(true)\n    child.stop()\n    expect(parent.scopes!.includes(child)).toBe(false)\n  })\n\n  it('test with higher level APIs', async () => {\n    const r = ref(1)\n\n    const computedSpy = vi.fn()\n    const watchSpy = vi.fn()\n    const watchEffectSpy = vi.fn()\n\n    let c: ComputedRef\n    const scope = effectScope()\n    scope.run(() => {\n      c = computed(() => {\n        computedSpy()\n        return r.value + 1\n      })\n\n      watch(r, watchSpy)\n      watchEffect(() => {\n        watchEffectSpy()\n        r.value\n        c.value\n      })\n    })\n\n    expect(computedSpy).toHaveBeenCalledTimes(1)\n    expect(watchSpy).toHaveBeenCalledTimes(0)\n    expect(watchEffectSpy).toHaveBeenCalledTimes(1)\n\n    r.value++\n    await nextTick()\n    expect(computedSpy).toHaveBeenCalledTimes(2)\n    expect(watchSpy).toHaveBeenCalledTimes(1)\n    expect(watchEffectSpy).toHaveBeenCalledTimes(2)\n\n    scope.stop()\n\n    r.value++\n    await nextTick()\n    // should not trigger anymore\n    expect(computedSpy).toHaveBeenCalledTimes(2)\n    expect(watchSpy).toHaveBeenCalledTimes(1)\n    expect(watchEffectSpy).toHaveBeenCalledTimes(2)\n  })\n\n  it('getCurrentScope() stays valid when running a detached nested EffectScope', () => {\n    const parentScope = effectScope()\n\n    parentScope.run(() => {\n      const currentScope = getCurrentScope()\n      expect(currentScope).toBeDefined()\n      const detachedScope = effectScope(true)\n      detachedScope.run(() => {})\n\n      expect(getCurrentScope()).toBe(currentScope)\n    })\n  })\n\n  it('calling .off() of a detached scope inside an active scope should not break currentScope', () => {\n    const parentScope = effectScope()\n\n    parentScope.run(() => {\n      const childScope = effectScope(true)\n      childScope.on()\n      childScope.off()\n      expect(getCurrentScope()).toBe(parentScope)\n    })\n  })\n\n  it('should pause/resume EffectScope', async () => {\n    const counter = reactive({ num: 0 })\n    const fnSpy = vi.fn(() => counter.num)\n    const scope = new EffectScope()\n    scope.run(() => {\n      effect(fnSpy)\n    })\n\n    expect(fnSpy).toHaveBeenCalledTimes(1)\n\n    counter.num++\n    await nextTick()\n    expect(fnSpy).toHaveBeenCalledTimes(2)\n\n    scope.pause()\n    counter.num++\n    await nextTick()\n    expect(fnSpy).toHaveBeenCalledTimes(2)\n\n    counter.num++\n    await nextTick()\n    expect(fnSpy).toHaveBeenCalledTimes(2)\n\n    scope.resume()\n    expect(fnSpy).toHaveBeenCalledTimes(3)\n  })\n\n  test('removing a watcher while stopping its effectScope', async () => {\n    const count = ref(0)\n    const scope = effectScope()\n    let watcherCalls = 0\n    let cleanupCalls = 0\n\n    scope.run(() => {\n      const stop1 = watch(count, () => {\n        watcherCalls++\n      })\n      watch(count, (val, old, onCleanup) => {\n        watcherCalls++\n        onCleanup(() => {\n          cleanupCalls++\n          stop1()\n        })\n      })\n      watch(count, () => {\n        watcherCalls++\n      })\n    })\n\n    expect(watcherCalls).toBe(0)\n    expect(cleanupCalls).toBe(0)\n\n    count.value++\n    await nextTick()\n    expect(watcherCalls).toBe(3)\n    expect(cleanupCalls).toBe(0)\n\n    scope.stop()\n    count.value++\n    await nextTick()\n    expect(watcherCalls).toBe(3)\n    expect(cleanupCalls).toBe(1)\n\n    expect(scope.effects.length).toBe(0)\n    expect(scope.cleanups.length).toBe(0)\n  })\n\n  it('should still trigger updates after stopping scope stored in reactive object', () => {\n    const rs = ref({\n      stage: 0,\n      scope: null as any,\n    })\n\n    let renderCount = 0\n    effect(() => {\n      renderCount++\n      return rs.value.stage\n    })\n\n    const handleBegin = () => {\n      const status = rs.value\n      status.stage = 1\n      status.scope = effectScope()\n      status.scope.run(() => {\n        watch([() => status.stage], () => {})\n      })\n    }\n\n    const handleExit = () => {\n      const status = rs.value\n      status.stage = 0\n      const watchScope = status.scope\n      status.scope = null\n      if (watchScope) {\n        watchScope.stop()\n      }\n    }\n\n    expect(rs.value.stage).toBe(0)\n    expect(renderCount).toBe(1)\n\n    // 1. Click begin\n    handleBegin()\n    expect(rs.value.stage).toBe(1)\n    expect(renderCount).toBe(2)\n\n    // 2. Click add\n    rs.value.stage++\n    expect(rs.value.stage).toBe(2)\n    expect(renderCount).toBe(3)\n\n    // 3. Click end\n    handleExit()\n    expect(rs.value.stage).toBe(0)\n    expect(renderCount).toBe(4)\n\n    handleBegin()\n    expect(rs.value.stage).toBe(1)\n    expect(renderCount).toBe(5)\n  })\n})\n"
  },
  {
    "path": "packages/reactivity/__tests__/gc.spec.ts",
    "content": "import {\n  type ComputedRef,\n  computed,\n  effect,\n  reactive,\n  shallowRef as ref,\n  toRaw,\n} from '../src/index'\nimport { getDepFromReactive } from '../src/dep'\n\ndescribe.skipIf(!global.gc)('reactivity/gc', () => {\n  const gc = () => {\n    return new Promise<void>(resolve => {\n      setTimeout(() => {\n        global.gc!()\n        resolve()\n      })\n    })\n  }\n\n  // #9233\n  it('should release computed cache', async () => {\n    const src = ref<{} | undefined>({})\n    // @ts-expect-error ES2021 API\n    const srcRef = new WeakRef(src.value!)\n\n    let c: ComputedRef | undefined = computed(() => src.value)\n\n    c.value // cache src value\n    src.value = undefined // release value\n    c = undefined // release computed\n\n    await gc()\n    expect(srcRef.deref()).toBeUndefined()\n  })\n\n  it('should release reactive property dep', async () => {\n    const src = reactive({ foo: 1 })\n\n    let c: ComputedRef | undefined = computed(() => src.foo)\n\n    c.value\n    expect(getDepFromReactive(toRaw(src), 'foo')).not.toBeUndefined()\n\n    c = undefined\n    await gc()\n    await gc()\n    expect(getDepFromReactive(toRaw(src), 'foo')).toBeUndefined()\n  })\n\n  it('should not release effect for ref', async () => {\n    const spy = vi.fn()\n    const src = ref(0)\n\n    effect(() => {\n      spy()\n      src.value\n    })\n\n    expect(spy).toHaveBeenCalledTimes(1)\n\n    await gc()\n    src.value++\n    expect(spy).toHaveBeenCalledTimes(2)\n  })\n\n  it('should not release effect for reactive', async () => {\n    const spy = vi.fn()\n    const src = reactive({ foo: 1 })\n\n    effect(() => {\n      spy()\n      src.foo\n    })\n\n    expect(spy).toHaveBeenCalledTimes(1)\n\n    await gc()\n    src.foo++\n    expect(spy).toHaveBeenCalledTimes(2)\n  })\n})\n"
  },
  {
    "path": "packages/reactivity/__tests__/reactive.spec.ts",
    "content": "import { isRef, ref, shallowRef } from '../src/ref'\nimport {\n  isProxy,\n  isReactive,\n  isReadonly,\n  isShallow,\n  markRaw,\n  reactive,\n  readonly,\n  shallowReactive,\n  shallowReadonly,\n  toRaw,\n} from '../src/reactive'\nimport { computed } from '../src/computed'\nimport { effect } from '../src/effect'\nimport { targetMap } from '../src/dep'\n\ndescribe('reactivity/reactive', () => {\n  test('Object', () => {\n    const original = { foo: 1 }\n    const observed = reactive(original)\n    expect(observed).not.toBe(original)\n    expect(isReactive(observed)).toBe(true)\n    expect(isReactive(original)).toBe(false)\n    // get\n    expect(observed.foo).toBe(1)\n    // has\n    expect('foo' in observed).toBe(true)\n    // ownKeys\n    expect(Object.keys(observed)).toEqual(['foo'])\n  })\n\n  test('proto', () => {\n    const obj = {}\n    const reactiveObj = reactive(obj)\n    expect(isReactive(reactiveObj)).toBe(true)\n    // read prop of reactiveObject will cause reactiveObj[prop] to be reactive\n    // @ts-expect-error\n    const prototype = reactiveObj['__proto__']\n    const otherObj = { data: ['a'] }\n    expect(isReactive(otherObj)).toBe(false)\n    const reactiveOther = reactive(otherObj)\n    expect(isReactive(reactiveOther)).toBe(true)\n    expect(reactiveOther.data[0]).toBe('a')\n  })\n\n  test('nested reactives', () => {\n    const original = {\n      nested: {\n        foo: 1,\n      },\n      array: [{ bar: 2 }],\n    }\n    const observed = reactive(original)\n    expect(isReactive(observed.nested)).toBe(true)\n    expect(isReactive(observed.array)).toBe(true)\n    expect(isReactive(observed.array[0])).toBe(true)\n  })\n\n  test('observing subtypes of IterableCollections(Map, Set)', () => {\n    // subtypes of Map\n    class CustomMap extends Map {}\n    const cmap = reactive(new CustomMap())\n\n    expect(cmap).toBeInstanceOf(Map)\n    expect(isReactive(cmap)).toBe(true)\n\n    cmap.set('key', {})\n    expect(isReactive(cmap.get('key'))).toBe(true)\n\n    // subtypes of Set\n    class CustomSet extends Set {}\n    const cset = reactive(new CustomSet())\n\n    expect(cset).toBeInstanceOf(Set)\n    expect(isReactive(cset)).toBe(true)\n\n    let dummy\n    effect(() => (dummy = cset.has('value')))\n    expect(dummy).toBe(false)\n    cset.add('value')\n    expect(dummy).toBe(true)\n    cset.delete('value')\n    expect(dummy).toBe(false)\n  })\n\n  test('observing subtypes of WeakCollections(WeakMap, WeakSet)', () => {\n    // subtypes of WeakMap\n    class CustomMap extends WeakMap {}\n    const cmap = reactive(new CustomMap())\n\n    expect(cmap).toBeInstanceOf(WeakMap)\n    expect(isReactive(cmap)).toBe(true)\n\n    const key = {}\n    cmap.set(key, {})\n    expect(isReactive(cmap.get(key))).toBe(true)\n\n    // subtypes of WeakSet\n    class CustomSet extends WeakSet {}\n    const cset = reactive(new CustomSet())\n\n    expect(cset).toBeInstanceOf(WeakSet)\n    expect(isReactive(cset)).toBe(true)\n\n    let dummy\n    effect(() => (dummy = cset.has(key)))\n    expect(dummy).toBe(false)\n    cset.add(key)\n    expect(dummy).toBe(true)\n    cset.delete(key)\n    expect(dummy).toBe(false)\n  })\n\n  // #8647\n  test('observing Set with reactive initial value', () => {\n    const observed = reactive({})\n    const observedSet = reactive(new Set([observed]))\n\n    expect(observedSet.has(observed)).toBe(true)\n    expect(observedSet.size).toBe(1)\n\n    // expect nothing happens\n    observedSet.add(observed)\n    expect(observedSet.size).toBe(1)\n  })\n\n  test('observed value should proxy mutations to original (Object)', () => {\n    const original: any = { foo: 1 }\n    const observed = reactive(original)\n    // set\n    observed.bar = 1\n    expect(observed.bar).toBe(1)\n    expect(original.bar).toBe(1)\n    // delete\n    delete observed.foo\n    expect('foo' in observed).toBe(false)\n    expect('foo' in original).toBe(false)\n  })\n\n  test('original value change should reflect in observed value (Object)', () => {\n    const original: any = { foo: 1 }\n    const observed = reactive(original)\n    // set\n    original.bar = 1\n    expect(original.bar).toBe(1)\n    expect(observed.bar).toBe(1)\n    // delete\n    delete original.foo\n    expect('foo' in original).toBe(false)\n    expect('foo' in observed).toBe(false)\n  })\n\n  test('setting a property with an unobserved value should wrap with reactive', () => {\n    const observed = reactive<{ foo?: object }>({})\n    const raw = {}\n    observed.foo = raw\n    expect(observed.foo).not.toBe(raw)\n    expect(isReactive(observed.foo)).toBe(true)\n  })\n\n  test('observing already observed value should return same Proxy', () => {\n    const original = { foo: 1 }\n    const observed = reactive(original)\n    const observed2 = reactive(observed)\n    expect(observed2).toBe(observed)\n  })\n\n  test('observing the same value multiple times should return same Proxy', () => {\n    const original = { foo: 1 }\n    const observed = reactive(original)\n    const observed2 = reactive(original)\n    expect(observed2).toBe(observed)\n  })\n\n  test('should not pollute original object with Proxies', () => {\n    const original: any = { foo: 1 }\n    const original2 = { bar: 2 }\n    const observed = reactive(original)\n    const observed2 = reactive(original2)\n    observed.bar = observed2\n    expect(observed.bar).toBe(observed2)\n    expect(original.bar).toBe(original2)\n  })\n\n  // #1246\n  test('mutation on objects using reactive as prototype should not trigger', () => {\n    const observed = reactive({ foo: 1 })\n    const original = Object.create(observed)\n    let dummy\n    effect(() => (dummy = original.foo))\n    expect(dummy).toBe(1)\n    observed.foo = 2\n    expect(dummy).toBe(2)\n    original.foo = 3\n    expect(dummy).toBe(2)\n    original.foo = 4\n    expect(dummy).toBe(2)\n  })\n\n  test('toRaw', () => {\n    const original = { foo: 1 }\n    const observed = reactive(original)\n    expect(toRaw(observed)).toBe(original)\n    expect(toRaw(original)).toBe(original)\n  })\n\n  test('toRaw on object using reactive as prototype', () => {\n    const original = { foo: 1 }\n    const observed = reactive(original)\n    const inherited = Object.create(observed)\n    expect(toRaw(inherited)).toBe(inherited)\n  })\n\n  test('toRaw on user Proxy wrapping reactive', () => {\n    const original = {}\n    const re = reactive(original)\n    const obj = new Proxy(re, {})\n    const raw = toRaw(obj)\n    expect(raw).toBe(original)\n  })\n\n  test('should not unwrap Ref<T>', () => {\n    const observedNumberRef = reactive(ref(1))\n    const observedObjectRef = reactive(ref({ foo: 1 }))\n\n    expect(isRef(observedNumberRef)).toBe(true)\n    expect(isRef(observedObjectRef)).toBe(true)\n  })\n\n  test('should unwrap computed refs', () => {\n    // readonly\n    const a = computed(() => 1)\n    // writable\n    const b = computed({\n      get: () => 1,\n      set: () => {},\n    })\n    const obj = reactive({ a, b })\n    // check type\n    obj.a + 1\n    obj.b + 1\n    expect(typeof obj.a).toBe(`number`)\n    expect(typeof obj.b).toBe(`number`)\n  })\n\n  test('should allow setting property from a ref to another ref', () => {\n    const foo = ref(0)\n    const bar = ref(1)\n    const observed = reactive({ a: foo })\n    const dummy = computed(() => observed.a)\n    expect(dummy.value).toBe(0)\n\n    // @ts-expect-error\n    observed.a = bar\n    expect(dummy.value).toBe(1)\n\n    bar.value++\n    expect(dummy.value).toBe(2)\n  })\n\n  test('non-observable values', () => {\n    const assertValue = (value: any) => {\n      reactive(value)\n      expect(\n        `value cannot be made reactive: ${String(value)}`,\n      ).toHaveBeenWarnedLast()\n    }\n\n    // number\n    assertValue(1)\n    // string\n    assertValue('foo')\n    // boolean\n    assertValue(false)\n    // null\n    assertValue(null)\n    // undefined\n    assertValue(undefined)\n    // symbol\n    const s = Symbol()\n    assertValue(s)\n    // bigint\n    const bn = BigInt('9007199254740991')\n    assertValue(bn)\n\n    // built-ins should work and return same value\n    const p = Promise.resolve()\n    expect(reactive(p)).toBe(p)\n    const r = new RegExp('')\n    expect(reactive(r)).toBe(r)\n    const d = new Date()\n    expect(reactive(d)).toBe(d)\n  })\n\n  test('markRaw', () => {\n    const obj = reactive({\n      foo: { a: 1 },\n      bar: markRaw({ b: 2 }),\n    })\n    expect(isReactive(obj.foo)).toBe(true)\n    expect(isReactive(obj.bar)).toBe(false)\n  })\n\n  test('markRaw should skip non-extensible objects', () => {\n    const obj = Object.seal({ foo: 1 })\n    expect(() => markRaw(obj)).not.toThrowError()\n  })\n\n  test('markRaw should not redefine on an marked object', () => {\n    const obj = markRaw({ foo: 1 })\n    const raw = markRaw(obj)\n    expect(raw).toBe(obj)\n    expect(() => markRaw(obj)).not.toThrowError()\n  })\n\n  test('should not markRaw object as reactive', () => {\n    const a = reactive({ a: 1 })\n    const b = reactive({ b: 2 }) as any\n    b.a = markRaw(toRaw(a))\n    expect(b.a === a).toBe(false)\n  })\n\n  test('should not observe non-extensible objects', () => {\n    const obj = reactive({\n      foo: Object.preventExtensions({ a: 1 }),\n      // sealed or frozen objects are considered non-extensible as well\n      bar: Object.freeze({ a: 1 }),\n      baz: Object.seal({ a: 1 }),\n    })\n    expect(isReactive(obj.foo)).toBe(false)\n    expect(isReactive(obj.bar)).toBe(false)\n    expect(isReactive(obj.baz)).toBe(false)\n  })\n\n  test('should not observe objects with __v_skip', () => {\n    const original = {\n      foo: 1,\n      __v_skip: true,\n    }\n    const observed = reactive(original)\n    expect(isReactive(observed)).toBe(false)\n  })\n\n  test('hasOwnProperty edge case: Symbol values', () => {\n    const key = Symbol()\n    const obj = reactive({ [key]: 1 }) as { [key]?: 1 }\n    let dummy\n    effect(() => {\n      dummy = obj.hasOwnProperty(key)\n    })\n    expect(dummy).toBe(true)\n\n    delete obj[key]\n    expect(dummy).toBe(false)\n  })\n\n  test('hasOwnProperty edge case: non-string values', () => {\n    const key = {}\n    const obj = reactive({ '[object Object]': 1 }) as { '[object Object]'?: 1 }\n    let dummy\n    effect(() => {\n      // @ts-expect-error\n      dummy = obj.hasOwnProperty(key)\n    })\n    expect(dummy).toBe(true)\n\n    // @ts-expect-error\n    delete obj[key]\n    expect(dummy).toBe(false)\n  })\n\n  test('isProxy', () => {\n    const foo = {}\n    expect(isProxy(foo)).toBe(false)\n\n    const fooRe = reactive(foo)\n    expect(isProxy(fooRe)).toBe(true)\n\n    const fooSRe = shallowReactive(foo)\n    expect(isProxy(fooSRe)).toBe(true)\n\n    const barRl = readonly(foo)\n    expect(isProxy(barRl)).toBe(true)\n\n    const barSRl = shallowReadonly(foo)\n    expect(isProxy(barSRl)).toBe(true)\n\n    const c = computed(() => {})\n    expect(isProxy(c)).toBe(false)\n  })\n\n  test('The results of the shallow and readonly assignments are the same (Map)', () => {\n    const map = reactive(new Map())\n    map.set('foo', shallowReactive({ a: 2 }))\n    expect(isShallow(map.get('foo'))).toBe(true)\n\n    map.set('bar', readonly({ b: 2 }))\n    expect(isReadonly(map.get('bar'))).toBe(true)\n  })\n\n  test('The results of the shallow and readonly assignments are the same (Set)', () => {\n    const set = reactive(new Set())\n    set.add(shallowReactive({ a: 2 }))\n    set.add(readonly({ b: 2 }))\n    let count = 0\n    for (const i of set) {\n      if (count === 0) expect(isShallow(i)).toBe(true)\n      else expect(isReadonly(i)).toBe(true)\n      count++\n    }\n  })\n\n  // #11696\n  test('should use correct receiver on set handler for refs', () => {\n    const a = reactive(ref(1))\n    effect(() => a.value)\n    expect(() => {\n      a.value++\n    }).not.toThrow()\n  })\n\n  // #11979\n  test('should release property Dep instance if it no longer has subscribers', () => {\n    let obj = { x: 1 }\n    let a = reactive(obj)\n    const e = effect(() => a.x)\n    expect(targetMap.get(obj)?.get('x')).toBeTruthy()\n    e.effect.stop()\n    expect(targetMap.get(obj)?.get('x')).toBeFalsy()\n  })\n\n  test('should trigger reactivity when Map key is undefined', () => {\n    const map = reactive(new Map())\n    const c = computed(() => map.get(void 0))\n\n    expect(c.value).toBe(void 0)\n\n    map.set(void 0, 1)\n    expect(c.value).toBe(1)\n  })\n\n  test('should return true for reactive objects', () => {\n    expect(isReactive(reactive({}))).toBe(true)\n    expect(isReactive(readonly(reactive({})))).toBe(true)\n    expect(isReactive(ref({}).value)).toBe(true)\n    expect(isReactive(readonly(ref({})).value)).toBe(true)\n    expect(isReactive(shallowReactive({}))).toBe(true)\n  })\n\n  test('should return false for non-reactive objects', () => {\n    expect(isReactive(ref(true))).toBe(false)\n    expect(isReactive(shallowRef({}).value)).toBe(false)\n  })\n})\n"
  },
  {
    "path": "packages/reactivity/__tests__/reactiveArray.spec.ts",
    "content": "import { type ComputedRef, computed } from '../src/computed'\nimport { isReactive, reactive, shallowReactive, toRaw } from '../src/reactive'\nimport { isRef, ref } from '../src/ref'\nimport { effect } from '../src/effect'\n\ndescribe('reactivity/reactive/Array', () => {\n  test('should make Array reactive', () => {\n    const original = [{ foo: 1 }]\n    const observed = reactive(original)\n    expect(observed).not.toBe(original)\n    expect(isReactive(observed)).toBe(true)\n    expect(isReactive(original)).toBe(false)\n    expect(isReactive(observed[0])).toBe(true)\n    // get\n    expect(observed[0].foo).toBe(1)\n    // has\n    expect(0 in observed).toBe(true)\n    // ownKeys\n    expect(Object.keys(observed)).toEqual(['0'])\n  })\n\n  test('cloned reactive Array should point to observed values', () => {\n    const original = [{ foo: 1 }]\n    const observed = reactive(original)\n    const clone = observed.slice()\n    expect(isReactive(clone[0])).toBe(true)\n    expect(clone[0]).not.toBe(original[0])\n    expect(clone[0]).toBe(observed[0])\n  })\n\n  test('observed value should proxy mutations to original (Array)', () => {\n    const original: any[] = [{ foo: 1 }, { bar: 2 }]\n    const observed = reactive(original)\n    // set\n    const value = { baz: 3 }\n    const reactiveValue = reactive(value)\n    observed[0] = value\n    expect(observed[0]).toBe(reactiveValue)\n    expect(original[0]).toBe(value)\n    // delete\n    delete observed[0]\n    expect(observed[0]).toBeUndefined()\n    expect(original[0]).toBeUndefined()\n    // mutating methods\n    observed.push(value)\n    expect(observed[2]).toBe(reactiveValue)\n    expect(original[2]).toBe(value)\n  })\n\n  test('Array identity methods should work with raw values', () => {\n    const raw = {}\n    const arr = reactive([{}, {}])\n    arr.push(raw)\n\n    expect(arr.indexOf(raw)).toBe(2)\n    expect(arr.indexOf(raw, 3)).toBe(-1)\n    expect(arr.includes(raw)).toBe(true)\n    expect(arr.includes(raw, 3)).toBe(false)\n    expect(arr.lastIndexOf(raw)).toBe(2)\n    expect(arr.lastIndexOf(raw, 1)).toBe(-1)\n\n    // should work also for the observed version\n    const observed = arr[2]\n    expect(arr.indexOf(observed)).toBe(2)\n    expect(arr.indexOf(observed, 3)).toBe(-1)\n    expect(arr.includes(observed)).toBe(true)\n    expect(arr.includes(observed, 3)).toBe(false)\n    expect(arr.lastIndexOf(observed)).toBe(2)\n    expect(arr.lastIndexOf(observed, 1)).toBe(-1)\n  })\n\n  test('Array identity methods should work if raw value contains reactive objects', () => {\n    const raw = []\n    const obj = reactive({})\n    raw.push(obj)\n    const arr = reactive(raw)\n    expect(arr.includes(obj)).toBe(true)\n  })\n\n  test('Array identity methods should be reactive', () => {\n    const obj = {}\n    const arr = reactive([obj, {}])\n\n    let index: number = -1\n    effect(() => {\n      index = arr.indexOf(obj)\n    })\n    expect(index).toBe(0)\n    arr.reverse()\n    expect(index).toBe(1)\n  })\n\n  // only non-existent reactive will try to search by using its raw value\n  describe('Array identity methods should not be called more than necessary', () => {\n    const identityMethods = ['includes', 'indexOf', 'lastIndexOf'] as const\n\n    function instrumentArr(rawTarget: any[]) {\n      const mutableTarget = rawTarget as Record<\n        (typeof identityMethods)[number],\n        any\n      >\n      identityMethods.forEach(key => {\n        const spy = vi.fn(rawTarget[key] as any)\n        mutableTarget[key] = spy\n      })\n    }\n\n    function searchValue(target: any[], ...args: unknown[]) {\n      return identityMethods.map(key => (target[key] as any)(...args))\n    }\n\n    function unInstrumentArr(rawTarget: any[]) {\n      identityMethods.forEach(key => {\n        ;(rawTarget[key] as any).mockClear()\n        // relink to prototype method\n        rawTarget[key] = Array.prototype[key] as any\n      })\n    }\n\n    function expectHaveBeenCalledTimes(rawTarget: any[], times: number) {\n      identityMethods.forEach(key => {\n        expect(rawTarget[key]).toHaveBeenCalledTimes(times)\n      })\n    }\n\n    test('should be called once with a non-existent raw value', () => {\n      const reactiveArr = reactive([])\n      instrumentArr(toRaw(reactiveArr))\n      const searchResult = searchValue(reactiveArr, {})\n\n      expectHaveBeenCalledTimes(toRaw(reactiveArr), 1)\n      expect(searchResult).toStrictEqual([false, -1, -1])\n\n      unInstrumentArr(toRaw(reactiveArr))\n    })\n\n    test('should be called once with an existent reactive value', () => {\n      const existReactiveValue = reactive({})\n      const reactiveArr = reactive([existReactiveValue, existReactiveValue])\n\n      instrumentArr(toRaw(reactiveArr))\n      const searchResult = searchValue(reactiveArr, existReactiveValue)\n\n      expectHaveBeenCalledTimes(toRaw(reactiveArr), 1)\n      expect(searchResult).toStrictEqual([true, 0, 1])\n\n      unInstrumentArr(toRaw(reactiveArr))\n    })\n\n    test('should be called twice with a non-existent reactive value', () => {\n      const reactiveArr = reactive([])\n      instrumentArr(toRaw(reactiveArr))\n      const searchResult = searchValue(reactiveArr, reactive({}))\n\n      expectHaveBeenCalledTimes(toRaw(reactiveArr), 2)\n      expect(searchResult).toStrictEqual([false, -1, -1])\n\n      unInstrumentArr(toRaw(reactiveArr))\n    })\n\n    test('should be called twice with a non-existent reactive value, but the raw value exists', () => {\n      const existRaw = {}\n      const reactiveArr = reactive([existRaw, existRaw])\n\n      instrumentArr(toRaw(reactiveArr))\n      const searchResult = searchValue(reactiveArr, reactive(existRaw))\n\n      expectHaveBeenCalledTimes(toRaw(reactiveArr), 2)\n      expect(searchResult).toStrictEqual([true, 0, 1])\n\n      unInstrumentArr(toRaw(reactiveArr))\n    })\n  })\n\n  test('delete on Array should not trigger length dependency', () => {\n    const arr = reactive([1, 2, 3])\n    const fn = vi.fn()\n    effect(() => {\n      fn(arr.length)\n    })\n    expect(fn).toHaveBeenCalledTimes(1)\n    delete arr[1]\n    expect(fn).toHaveBeenCalledTimes(1)\n  })\n\n  test('should track hasOwnProperty call with index', () => {\n    const original = [1, 2, 3]\n    const observed = reactive(original)\n\n    let dummy\n    effect(() => {\n      dummy = observed.hasOwnProperty(0)\n    })\n\n    expect(dummy).toBe(true)\n\n    delete observed[0]\n    expect(dummy).toBe(false)\n  })\n\n  test('shift on Array should trigger dependency once', () => {\n    const arr = reactive([1, 2, 3])\n    const fn = vi.fn()\n    effect(() => {\n      for (let i = 0; i < arr.length; i++) {\n        arr[i]\n      }\n      fn()\n    })\n    expect(fn).toHaveBeenCalledTimes(1)\n    arr.shift()\n    expect(fn).toHaveBeenCalledTimes(2)\n  })\n\n  //#6018\n  test('edge case: avoid trigger effect in deleteProperty when array length-decrease mutation methods called', () => {\n    const arr = ref([1])\n    const fn1 = vi.fn()\n    const fn2 = vi.fn()\n    effect(() => {\n      fn1()\n      if (arr.value.length > 0) {\n        arr.value.slice()\n        fn2()\n      }\n    })\n    expect(fn1).toHaveBeenCalledTimes(1)\n    expect(fn2).toHaveBeenCalledTimes(1)\n    arr.value.splice(0)\n    expect(fn1).toHaveBeenCalledTimes(2)\n    expect(fn2).toHaveBeenCalledTimes(1)\n  })\n\n  test('add existing index on Array should not trigger length dependency', () => {\n    const array = new Array(3)\n    const observed = reactive(array)\n    const fn = vi.fn()\n    effect(() => {\n      fn(observed.length)\n    })\n    expect(fn).toHaveBeenCalledTimes(1)\n    observed[1] = 1\n    expect(fn).toHaveBeenCalledTimes(1)\n  })\n\n  test('add non-integer prop on Array should not trigger length dependency', () => {\n    const array: any[] & { x?: string } = new Array(3)\n    const observed = reactive(array)\n    const fn = vi.fn()\n    effect(() => {\n      fn(observed.length)\n    })\n    expect(fn).toHaveBeenCalledTimes(1)\n    observed.x = 'x'\n    expect(fn).toHaveBeenCalledTimes(1)\n    observed[-1] = 'x'\n    expect(fn).toHaveBeenCalledTimes(1)\n    observed[NaN] = 'x'\n    expect(fn).toHaveBeenCalledTimes(1)\n  })\n\n  // #2427\n  test('track length on for ... in iteration', () => {\n    const array = reactive([1])\n    let length = ''\n    effect(() => {\n      length = ''\n      for (const key in array) {\n        length += key\n      }\n    })\n    expect(length).toBe('0')\n    array.push(1)\n    expect(length).toBe('01')\n  })\n\n  // #9742\n  test('mutation on user proxy of reactive Array', () => {\n    const array = reactive<number[]>([])\n    const proxy = new Proxy(array, {})\n    proxy.push(1)\n    expect(array).toHaveLength(1)\n    expect(proxy).toHaveLength(1)\n  })\n\n  describe('Array methods w/ refs', () => {\n    let original: any[]\n    beforeEach(() => {\n      original = reactive([1, ref(2)])\n    })\n\n    // read + copy\n    test('read only copy methods', () => {\n      const raw = original.concat([3, ref(4)])\n      expect(isRef(raw[1])).toBe(true)\n      expect(isRef(raw[3])).toBe(true)\n    })\n\n    // read + write\n    test('read + write mutating methods', () => {\n      const res = original.copyWithin(0, 1, 2)\n      const raw = toRaw(res)\n      expect(isRef(raw[0])).toBe(true)\n      expect(isRef(raw[1])).toBe(true)\n    })\n\n    test('read + identity', () => {\n      const ref = original[1]\n      expect(ref).toBe(toRaw(original)[1])\n      expect(original.indexOf(ref)).toBe(1)\n    })\n  })\n\n  describe('Array subclasses', () => {\n    class SubArray<T> extends Array<T> {\n      lastPushed: undefined | T\n      lastSearched: undefined | T\n\n      push(item: T) {\n        this.lastPushed = item\n        return super.push(item)\n      }\n\n      indexOf(searchElement: T, fromIndex?: number | undefined): number {\n        this.lastSearched = searchElement\n        return super.indexOf(searchElement, fromIndex)\n      }\n    }\n\n    test('calls correct mutation method on Array subclass', () => {\n      const subArray = new SubArray(4, 5, 6)\n      const observed = reactive(subArray)\n\n      subArray.push(7)\n      expect(subArray.lastPushed).toBe(7)\n      observed.push(9)\n      expect(observed.lastPushed).toBe(9)\n    })\n\n    test('calls correct identity-sensitive method on Array subclass', () => {\n      const subArray = new SubArray(4, 5, 6)\n      const observed = reactive(subArray)\n      let index\n\n      index = subArray.indexOf(4)\n      expect(index).toBe(0)\n      expect(subArray.lastSearched).toBe(4)\n\n      index = observed.indexOf(6)\n      expect(index).toBe(2)\n      expect(observed.lastSearched).toBe(6)\n    })\n  })\n\n  describe('Optimized array methods:', () => {\n    test('iterator', () => {\n      const shallow = shallowReactive([1, 2, 3, 4])\n      let result = computed(() => {\n        let sum = 0\n        for (let x of shallow) {\n          sum += x ** 2\n        }\n        return sum\n      })\n      expect(result.value).toBe(30)\n\n      shallow[2] = 0\n      expect(result.value).toBe(21)\n\n      const deep = reactive([{ val: 1 }, { val: 2 }])\n      result = computed(() => {\n        let sum = 0\n        for (let x of deep) {\n          sum += x.val ** 2\n        }\n        return sum\n      })\n      expect(result.value).toBe(5)\n\n      deep[1].val = 3\n      expect(result.value).toBe(10)\n    })\n\n    test('concat', () => {\n      const a1 = shallowReactive([1, { val: 2 }])\n      const a2 = reactive([{ val: 3 }])\n      const a3 = [4, 5]\n\n      let result = computed(() => a1.concat(a2, a3, 6, { val: 7 }))\n      expect(result.value).toStrictEqual([\n        1,\n        { val: 2 },\n        { val: 3 },\n        4,\n        5,\n        6,\n        { val: 7 },\n      ])\n      expect(isReactive(result.value[1])).toBe(false)\n      expect(isReactive(result.value[2])).toBe(true)\n      expect(isReactive(result.value[6])).toBe(false)\n\n      a1.shift()\n      expect(result.value).toStrictEqual([\n        { val: 2 },\n        { val: 3 },\n        4,\n        5,\n        6,\n        { val: 7 },\n      ])\n\n      a2.pop()\n      expect(result.value).toStrictEqual([{ val: 2 }, 4, 5, 6, { val: 7 }])\n\n      a3.pop()\n      expect(result.value).toStrictEqual([{ val: 2 }, 4, 5, 6, { val: 7 }])\n    })\n\n    test('entries', () => {\n      const shallow = shallowReactive([0, 1])\n      const result1 = computed(() => Array.from(shallow.entries()))\n      expect(result1.value).toStrictEqual([\n        [0, 0],\n        [1, 1],\n      ])\n\n      shallow[1] = 10\n      expect(result1.value).toStrictEqual([\n        [0, 0],\n        [1, 10],\n      ])\n\n      const deep = reactive([{ val: 0 }, { val: 1 }])\n      const result2 = computed(() => Array.from(deep.entries()))\n      expect(result2.value).toStrictEqual([\n        [0, { val: 0 }],\n        [1, { val: 1 }],\n      ])\n      expect(isReactive(result2.value[0][1])).toBe(true)\n\n      deep.pop()\n      expect(Array.from(result2.value)).toStrictEqual([[0, { val: 0 }]])\n    })\n\n    test('every', () => {\n      const shallow = shallowReactive([1, 2, 5])\n      let result = computed(() => shallow.every(x => x < 5))\n      expect(result.value).toBe(false)\n\n      shallow.pop()\n      expect(result.value).toBe(true)\n\n      const deep = reactive([{ val: 1 }, { val: 5 }])\n      result = computed(() => deep.every(x => x.val < 5))\n      expect(result.value).toBe(false)\n\n      deep[1].val = 2\n      expect(result.value).toBe(true)\n    })\n\n    test('filter', () => {\n      const shallow = shallowReactive([1, 2, 3, 4])\n      const result1 = computed(() => shallow.filter(x => x < 3))\n      expect(result1.value).toStrictEqual([1, 2])\n\n      shallow[2] = 0\n      expect(result1.value).toStrictEqual([1, 2, 0])\n\n      const deep = reactive([{ val: 1 }, { val: 2 }])\n      const result2 = computed(() => deep.filter(x => x.val < 2))\n      expect(result2.value).toStrictEqual([{ val: 1 }])\n      expect(isReactive(result2.value[0])).toBe(true)\n\n      deep[1].val = 0\n      expect(result2.value).toStrictEqual([{ val: 1 }, { val: 0 }])\n    })\n\n    test('find and co.', () => {\n      const shallow = shallowReactive([{ val: 1 }, { val: 2 }])\n      let find = computed(() => shallow.find(x => x.val === 2))\n      // @ts-expect-error tests are not limited to es2016\n      let findLast = computed(() => shallow.findLast(x => x.val === 2))\n      let findIndex = computed(() => shallow.findIndex(x => x.val === 2))\n      let findLastIndex = computed(() =>\n        // @ts-expect-error tests are not limited to es2016\n        shallow.findLastIndex(x => x.val === 2),\n      )\n\n      expect(find.value).toBe(shallow[1])\n      expect(isReactive(find.value)).toBe(false)\n      expect(findLast.value).toBe(shallow[1])\n      expect(isReactive(findLast.value)).toBe(false)\n      expect(findIndex.value).toBe(1)\n      expect(findLastIndex.value).toBe(1)\n\n      shallow[1].val = 0\n\n      expect(find.value).toBe(shallow[1])\n      expect(findLast.value).toBe(shallow[1])\n      expect(findIndex.value).toBe(1)\n      expect(findLastIndex.value).toBe(1)\n\n      shallow.pop()\n\n      expect(find.value).toBe(undefined)\n      expect(findLast.value).toBe(undefined)\n      expect(findIndex.value).toBe(-1)\n      expect(findLastIndex.value).toBe(-1)\n\n      const deep = reactive([{ val: 1 }, { val: 2 }])\n      find = computed(() => deep.find(x => x.val === 2))\n      // @ts-expect-error tests are not limited to es2016\n      findLast = computed(() => deep.findLast(x => x.val === 2))\n      findIndex = computed(() => deep.findIndex(x => x.val === 2))\n      // @ts-expect-error tests are not limited to es2016\n      findLastIndex = computed(() => deep.findLastIndex(x => x.val === 2))\n\n      expect(find.value).toBe(deep[1])\n      expect(isReactive(find.value)).toBe(true)\n      expect(findLast.value).toBe(deep[1])\n      expect(isReactive(findLast.value)).toBe(true)\n      expect(findIndex.value).toBe(1)\n      expect(findLastIndex.value).toBe(1)\n\n      deep[1].val = 0\n\n      expect(find.value).toBe(undefined)\n      expect(findLast.value).toBe(undefined)\n      expect(findIndex.value).toBe(-1)\n      expect(findLastIndex.value).toBe(-1)\n    })\n\n    test('forEach', () => {\n      const shallow = shallowReactive([1, 2, 3, 4])\n      let result = computed(() => {\n        let sum = 0\n        shallow.forEach(x => (sum += x ** 2))\n        return sum\n      })\n      expect(result.value).toBe(30)\n\n      shallow[2] = 0\n      expect(result.value).toBe(21)\n\n      const deep = reactive([{ val: 1 }, { val: 2 }])\n      result = computed(() => {\n        let sum = 0\n        deep.forEach(x => (sum += x.val ** 2))\n        return sum\n      })\n      expect(result.value).toBe(5)\n\n      deep[1].val = 3\n      expect(result.value).toBe(10)\n    })\n\n    test('join', () => {\n      function toString(this: { val: number }) {\n        return this.val\n      }\n      const shallow = shallowReactive([\n        { val: 1, toString },\n        { val: 2, toString },\n      ])\n      let result = computed(() => shallow.join('+'))\n      expect(result.value).toBe('1+2')\n\n      shallow[1].val = 23\n      expect(result.value).toBe('1+2')\n\n      shallow.pop()\n      expect(result.value).toBe('1')\n\n      const deep = reactive([\n        { val: 1, toString },\n        { val: 2, toString },\n      ])\n      result = computed(() => deep.join())\n      expect(result.value).toBe('1,2')\n\n      deep[1].val = 23\n      expect(result.value).toBe('1,23')\n    })\n\n    test('map', () => {\n      const shallow = shallowReactive([1, 2, 3, 4])\n      let result = computed(() => shallow.map(x => x ** 2))\n      expect(result.value).toStrictEqual([1, 4, 9, 16])\n\n      shallow[2] = 0\n      expect(result.value).toStrictEqual([1, 4, 0, 16])\n\n      const deep = reactive([{ val: 1 }, { val: 2 }])\n      result = computed(() => deep.map(x => x.val ** 2))\n      expect(result.value).toStrictEqual([1, 4])\n\n      deep[1].val = 3\n      expect(result.value).toStrictEqual([1, 9])\n    })\n\n    test('reduce left and right', () => {\n      function toString(this: any) {\n        return this.val + '-'\n      }\n      const shallow = shallowReactive([\n        { val: 1, toString },\n        { val: 2, toString },\n      ] as any[])\n\n      expect(shallow.reduce((acc, x) => acc + '' + x.val, undefined)).toBe(\n        'undefined12',\n      )\n\n      let left = computed(() => shallow.reduce((acc, x) => acc + '' + x.val))\n      let right = computed(() =>\n        shallow.reduceRight((acc, x) => acc + '' + x.val),\n      )\n      expect(left.value).toBe('1-2')\n      expect(right.value).toBe('2-1')\n\n      shallow[1].val = 23\n      expect(left.value).toBe('1-2')\n      expect(right.value).toBe('2-1')\n\n      shallow.pop()\n      expect(left.value).toBe(shallow[0])\n      expect(right.value).toBe(shallow[0])\n\n      let deep = reactive([{ val: 1 }, { val: 2 }])\n      left = computed(() => deep.reduce((acc, x) => acc + x.val, '0'))\n      right = computed(() => deep.reduceRight((acc, x) => acc + x.val, '3'))\n      expect(left.value).toBe('012')\n      expect(right.value).toBe('321')\n\n      deep[1].val = 23\n      expect(left.value).toBe('0123')\n      expect(right.value).toBe('3231')\n\n      deep = reactive([{ val: 1 }, { val: 2 }])\n      const maxBy = (prev: any, cur: any) => {\n        expect(isReactive(prev)).toBe(true)\n        expect(isReactive(cur)).toBe(true)\n        return prev.val > cur.val ? prev : cur\n      }\n      left = computed(() => deep.reduce(maxBy))\n      right = computed(() => deep.reduceRight(maxBy))\n      expect(left.value).toMatchObject({ val: 2 })\n      expect(right.value).toMatchObject({ val: 2 })\n\n      deep[0].val = 23\n      expect(left.value).toMatchObject({ val: 23 })\n      expect(right.value).toMatchObject({ val: 23 })\n\n      deep[1].val = 24\n      expect(left.value).toMatchObject({ val: 24 })\n      expect(right.value).toMatchObject({ val: 24 })\n    })\n\n    test('reduce left and right with single deep reactive element and no initial value', () => {\n      const deep = reactive([{ val: 1 }])\n      const left = computed(() => deep.reduce(prev => prev))\n      const right = computed(() => deep.reduceRight(prev => prev))\n\n      expect(isReactive(left.value)).toBe(true)\n      expect(isReactive(right.value)).toBe(true)\n      expect(left.value).toMatchObject({ val: 1 })\n      expect(right.value).toMatchObject({ val: 1 })\n\n      deep[0].val = 2\n      expect(left.value).toMatchObject({ val: 2 })\n      expect(right.value).toMatchObject({ val: 2 })\n    })\n\n    test('some', () => {\n      const shallow = shallowReactive([1, 2, 5])\n      let result = computed(() => shallow.some(x => x > 4))\n      expect(result.value).toBe(true)\n\n      shallow.pop()\n      expect(result.value).toBe(false)\n\n      const deep = reactive([{ val: 1 }, { val: 5 }])\n      result = computed(() => deep.some(x => x.val > 4))\n      expect(result.value).toBe(true)\n\n      deep[1].val = 2\n      expect(result.value).toBe(false)\n    })\n\n    // Node 20+\n    // @ts-expect-error tests are not limited to es2016\n    test.skipIf(!Array.prototype.toReversed)('toReversed', () => {\n      const array = reactive([1, { val: 2 }])\n      const result = computed(() => (array as any).toReversed())\n      expect(result.value).toStrictEqual([{ val: 2 }, 1])\n      expect(isReactive(result.value[0])).toBe(true)\n\n      array.splice(1, 1, 2)\n      expect(result.value).toStrictEqual([2, 1])\n    })\n\n    // Node 20+\n    // @ts-expect-error tests are not limited to es2016\n    test.skipIf(!Array.prototype.toSorted)('toSorted', () => {\n      // No comparer\n      // @ts-expect-error\n      expect(shallowReactive([2, 1, 3]).toSorted()).toStrictEqual([1, 2, 3])\n\n      const shallow = shallowReactive([{ val: 2 }, { val: 1 }, { val: 3 }])\n      let result: ComputedRef<{ val: number }[]>\n      // @ts-expect-error\n      result = computed(() => shallow.toSorted((a, b) => a.val - b.val))\n      expect(result.value.map(x => x.val)).toStrictEqual([1, 2, 3])\n      expect(isReactive(result.value[0])).toBe(false)\n\n      shallow[0].val = 4\n      expect(result.value.map(x => x.val)).toStrictEqual([1, 4, 3])\n\n      shallow.pop()\n      expect(result.value.map(x => x.val)).toStrictEqual([1, 4])\n\n      const deep = reactive([{ val: 2 }, { val: 1 }, { val: 3 }])\n      // @ts-expect-error\n      result = computed(() => deep.toSorted((a, b) => a.val - b.val))\n      expect(result.value.map(x => x.val)).toStrictEqual([1, 2, 3])\n      expect(isReactive(result.value[0])).toBe(true)\n\n      deep[0].val = 4\n      expect(result.value.map(x => x.val)).toStrictEqual([1, 3, 4])\n    })\n\n    // Node 20+\n    // @ts-expect-error tests are not limited to es2016\n    test.skipIf(!Array.prototype.toSpliced)('toSpliced', () => {\n      const array = reactive([1, 2, 3])\n      // @ts-expect-error\n      const result = computed(() => array.toSpliced(1, 1, -2))\n      expect(result.value).toStrictEqual([1, -2, 3])\n\n      array[0] = 0\n      expect(result.value).toStrictEqual([0, -2, 3])\n    })\n\n    test('values', () => {\n      const shallow = shallowReactive([{ val: 1 }, { val: 2 }])\n      const result = computed(() => Array.from(shallow.values()))\n      expect(result.value).toStrictEqual([{ val: 1 }, { val: 2 }])\n      expect(isReactive(result.value[0])).toBe(false)\n\n      shallow.pop()\n      expect(result.value).toStrictEqual([{ val: 1 }])\n\n      const deep = reactive([{ val: 1 }, { val: 2 }])\n      const firstItem = Array.from(deep.values())[0]\n      expect(isReactive(firstItem)).toBe(true)\n    })\n\n    test('extend methods', () => {\n      class Collection extends Array {\n        // @ts-expect-error\n        every(foo: any, bar: any, baz: any) {\n          expect(foo).toBe('foo')\n          expect(bar).toBe('bar')\n          expect(baz).toBe('baz')\n          return super.every(obj => obj.id === foo)\n        }\n\n        // @ts-expect-error\n        filter(foo: any, bar: any, baz: any) {\n          expect(foo).toBe('foo')\n          expect(bar).toBe('bar')\n          expect(baz).toBe('baz')\n          return super.filter(obj => obj.id === foo)\n        }\n\n        // @ts-expect-error\n        find(foo: any, bar: any, baz: any) {\n          expect(foo).toBe('foo')\n          expect(bar).toBe('bar')\n          expect(baz).toBe('baz')\n          return super.find(obj => obj.id === foo)\n        }\n\n        // @ts-expect-error\n        findIndex(foo: any, bar: any, baz: any) {\n          expect(foo).toBe('foo')\n          expect(bar).toBe('bar')\n          expect(baz).toBe('baz')\n          return super.findIndex(obj => obj.id === bar)\n        }\n\n        findLast(foo: any, bar: any, baz: any) {\n          expect(foo).toBe('foo')\n          expect(bar).toBe('bar')\n          expect(baz).toBe('baz')\n          // @ts-expect-error our code is limited to es2016 but user code is not\n          return super.findLast(obj => obj.id === bar)\n        }\n\n        findLastIndex(foo: any, bar: any, baz: any) {\n          expect(foo).toBe('foo')\n          expect(bar).toBe('bar')\n          expect(baz).toBe('baz')\n          return super.findIndex(obj => obj.id === bar)\n        }\n\n        // @ts-expect-error\n        forEach(foo: any, bar: any, baz: any) {\n          expect(foo).toBe('foo')\n          expect(bar).toBe('bar')\n          expect(baz).toBe('baz')\n        }\n\n        // @ts-expect-error\n        map(foo: any, bar: any, baz: any) {\n          expect(foo).toBe('foo')\n          expect(bar).toBe('bar')\n          expect(baz).toBe('baz')\n          return super.map(obj => obj.value)\n        }\n\n        // @ts-expect-error\n        some(foo: any, bar: any, baz: any) {\n          expect(foo).toBe('foo')\n          expect(bar).toBe('bar')\n          expect(baz).toBe('baz')\n          return super.some(obj => obj.id === baz)\n        }\n      }\n\n      const state = reactive({\n        things: new Collection(),\n      })\n\n      const foo = { id: 'foo', value: '1' }\n      const bar = { id: 'bar', value: '2' }\n      const baz = { id: 'baz', value: '3' }\n      state.things.push(foo)\n      state.things.push(bar)\n      state.things.push(baz)\n\n      expect(state.things.every('foo', 'bar', 'baz')).toBe(false)\n      expect(state.things.filter('foo', 'bar', 'baz')).toEqual([foo])\n\n      const _foo = state.things.find('foo', 'bar', 'baz')\n      expect(isReactive(_foo)).toBe(true)\n      expect(foo).toStrictEqual(_foo)\n\n      expect(state.things.findIndex('foo', 'bar', 'baz')).toBe(1)\n\n      const _bar = state.things.findLast('foo', 'bar', 'baz')\n      expect(isReactive(_bar)).toBe(true)\n      expect(bar).toStrictEqual(_bar)\n\n      expect(state.things.findLastIndex('foo', 'bar', 'baz')).toBe(1)\n      expect(state.things.forEach('foo', 'bar', 'baz')).toBeUndefined()\n      expect(state.things.map('foo', 'bar', 'baz')).toEqual(['1', '2', '3'])\n      expect(state.things.some('foo', 'bar', 'baz')).toBe(true)\n\n      {\n        class Collection extends Array {\n          find(matcher: any) {\n            return super.find(matcher)\n          }\n        }\n\n        const state = reactive({\n          // @ts-expect-error\n          things: new Collection({ foo: '' }),\n        })\n\n        const bar = computed(() => {\n          return state.things.find((obj: any) => obj.foo === 'bar')\n        })\n        bar.value\n        state.things[0].foo = 'bar'\n\n        expect(bar.value).toEqual({ foo: 'bar' })\n      }\n    })\n  })\n})\n"
  },
  {
    "path": "packages/reactivity/__tests__/readonly.spec.ts",
    "content": "import {\n  computed,\n  effect,\n  isProxy,\n  isReactive,\n  isReadonly,\n  markRaw,\n  reactive,\n  readonly,\n  ref,\n  shallowRef,\n  toRaw,\n  triggerRef,\n} from '../src'\n\n/**\n * @see https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html\n */\ntype Writable<T> = { -readonly [P in keyof T]: T[P] }\n\ndescribe('reactivity/readonly', () => {\n  describe('Object', () => {\n    it('should make nested values readonly', () => {\n      const original = { foo: 1, bar: { baz: 2 } }\n      const wrapped = readonly(original)\n      expect(wrapped).not.toBe(original)\n      expect(isProxy(wrapped)).toBe(true)\n      expect(isReactive(wrapped)).toBe(false)\n      expect(isReadonly(wrapped)).toBe(true)\n      expect(isReactive(original)).toBe(false)\n      expect(isReadonly(original)).toBe(false)\n      expect(isReactive(wrapped.bar)).toBe(false)\n      expect(isReadonly(wrapped.bar)).toBe(true)\n      expect(isReactive(original.bar)).toBe(false)\n      expect(isReadonly(original.bar)).toBe(false)\n      // get\n      expect(wrapped.foo).toBe(1)\n      // has\n      expect('foo' in wrapped).toBe(true)\n      // ownKeys\n      expect(Object.keys(wrapped)).toEqual(['foo', 'bar'])\n    })\n\n    it('should not allow mutation', () => {\n      const qux = Symbol('qux')\n      const original = {\n        foo: 1,\n        bar: {\n          baz: 2,\n        },\n        [qux]: 3,\n      }\n      const wrapped: Writable<typeof original> = readonly(original)\n\n      wrapped.foo = 2\n      expect(wrapped.foo).toBe(1)\n      expect(\n        `Set operation on key \"foo\" failed: target is readonly.`,\n      ).toHaveBeenWarnedLast()\n\n      wrapped.bar.baz = 3\n      expect(wrapped.bar.baz).toBe(2)\n      expect(\n        `Set operation on key \"baz\" failed: target is readonly.`,\n      ).toHaveBeenWarnedLast()\n\n      wrapped[qux] = 4\n      expect(wrapped[qux]).toBe(3)\n      expect(\n        `Set operation on key \"Symbol(qux)\" failed: target is readonly.`,\n      ).toHaveBeenWarnedLast()\n\n      // @ts-expect-error\n      delete wrapped.foo\n      expect(wrapped.foo).toBe(1)\n      expect(\n        `Delete operation on key \"foo\" failed: target is readonly.`,\n      ).toHaveBeenWarnedLast()\n\n      // @ts-expect-error\n      delete wrapped.bar.baz\n      expect(wrapped.bar.baz).toBe(2)\n      expect(\n        `Delete operation on key \"baz\" failed: target is readonly.`,\n      ).toHaveBeenWarnedLast()\n\n      // @ts-expect-error\n      delete wrapped[qux]\n      expect(wrapped[qux]).toBe(3)\n      expect(\n        `Delete operation on key \"Symbol(qux)\" failed: target is readonly.`,\n      ).toHaveBeenWarnedLast()\n    })\n\n    it('should not trigger effects', () => {\n      const wrapped: any = readonly({ a: 1 })\n      let dummy\n      effect(() => {\n        dummy = wrapped.a\n      })\n      expect(dummy).toBe(1)\n      wrapped.a = 2\n      expect(wrapped.a).toBe(1)\n      expect(dummy).toBe(1)\n      expect(`target is readonly`).toHaveBeenWarned()\n    })\n  })\n\n  describe('Array', () => {\n    it('should make nested values readonly', () => {\n      const original = [{ foo: 1 }]\n      const wrapped = readonly(original)\n      expect(wrapped).not.toBe(original)\n      expect(isProxy(wrapped)).toBe(true)\n      expect(isReactive(wrapped)).toBe(false)\n      expect(isReadonly(wrapped)).toBe(true)\n      expect(isReactive(original)).toBe(false)\n      expect(isReadonly(original)).toBe(false)\n      expect(isReactive(wrapped[0])).toBe(false)\n      expect(isReadonly(wrapped[0])).toBe(true)\n      expect(isReactive(original[0])).toBe(false)\n      expect(isReadonly(original[0])).toBe(false)\n      // get\n      expect(wrapped[0].foo).toBe(1)\n      // has\n      expect(0 in wrapped).toBe(true)\n      // ownKeys\n      expect(Object.keys(wrapped)).toEqual(['0'])\n    })\n\n    it('should not allow mutation', () => {\n      const wrapped: any = readonly([{ foo: 1 }])\n      wrapped[0] = 1\n      expect(wrapped[0]).not.toBe(1)\n      expect(\n        `Set operation on key \"0\" failed: target is readonly.`,\n      ).toHaveBeenWarned()\n      wrapped[0].foo = 2\n      expect(wrapped[0].foo).toBe(1)\n      expect(\n        `Set operation on key \"foo\" failed: target is readonly.`,\n      ).toHaveBeenWarned()\n\n      // should block length mutation\n      wrapped.length = 0\n      expect(wrapped.length).toBe(1)\n      expect(wrapped[0].foo).toBe(1)\n      expect(\n        `Set operation on key \"length\" failed: target is readonly.`,\n      ).toHaveBeenWarned()\n\n      // mutation methods invoke set/length internally and thus are blocked as well\n      wrapped.push(2)\n      expect(wrapped.length).toBe(1)\n      // push triggers two warnings on [1] and .length\n      expect(`target is readonly.`).toHaveBeenWarnedTimes(5)\n    })\n\n    it('should not trigger effects', () => {\n      const wrapped: any = readonly([{ a: 1 }])\n      let dummy\n      effect(() => {\n        dummy = wrapped[0].a\n      })\n      expect(dummy).toBe(1)\n      wrapped[0].a = 2\n      expect(wrapped[0].a).toBe(1)\n      expect(dummy).toBe(1)\n      expect(`target is readonly`).toHaveBeenWarnedTimes(1)\n      wrapped[0] = { a: 2 }\n      expect(wrapped[0].a).toBe(1)\n      expect(dummy).toBe(1)\n      expect(`target is readonly`).toHaveBeenWarnedTimes(2)\n    })\n\n    it('should maintain identity when iterating readonly ref array', () => {\n      const list = readonly(ref([{}, {}, {}]))\n      const computedList = computed(() => {\n        const newList: any[] = []\n        list.value.forEach(x => newList.push(x))\n        return newList\n      })\n\n      expect(list.value[0]).toBe(computedList.value[0])\n      expect(isReadonly(computedList.value[0])).toBe(true)\n      expect(isReactive(computedList.value[0])).toBe(true)\n    })\n  })\n\n  const maps = [Map, WeakMap]\n  maps.forEach((Collection: any) => {\n    describe(Collection.name, () => {\n      test('should make nested values readonly', () => {\n        const key1 = {}\n        const key2 = {}\n        const original = new Collection([\n          [key1, {}],\n          [key2, {}],\n        ])\n        const wrapped = readonly(original)\n        expect(wrapped).not.toBe(original)\n        expect(isProxy(wrapped)).toBe(true)\n        expect(isReactive(wrapped)).toBe(false)\n        expect(isReadonly(wrapped)).toBe(true)\n        expect(isReactive(original)).toBe(false)\n        expect(isReadonly(original)).toBe(false)\n        expect(isReactive(wrapped.get(key1))).toBe(false)\n        expect(isReadonly(wrapped.get(key1))).toBe(true)\n        expect(isReactive(original.get(key1))).toBe(false)\n        expect(isReadonly(original.get(key1))).toBe(false)\n      })\n\n      test('should not allow mutation & not trigger effect', () => {\n        const map = readonly(new Collection())\n        const key = {}\n        let dummy\n        effect(() => {\n          dummy = map.get(key)\n        })\n        expect(dummy).toBeUndefined()\n        map.set(key, 1)\n        expect(dummy).toBeUndefined()\n        expect(map.has(key)).toBe(false)\n        expect(\n          `Set operation on key \"${key}\" failed: target is readonly.`,\n        ).toHaveBeenWarned()\n      })\n\n      // #1772\n      test('readonly + reactive should make get() value also readonly + reactive', () => {\n        const map = reactive(new Collection())\n        const roMap = readonly(map)\n        const key = {}\n        map.set(key, {})\n\n        const item = map.get(key)\n        expect(isReactive(item)).toBe(true)\n        expect(isReadonly(item)).toBe(false)\n\n        const roItem = roMap.get(key)\n        expect(isReactive(roItem)).toBe(true)\n        expect(isReadonly(roItem)).toBe(true)\n      })\n\n      if (Collection === Map) {\n        test('should retrieve readonly values on iteration', () => {\n          const key1 = {}\n          const key2 = {}\n          const original = new Map([\n            [key1, {}],\n            [key2, {}],\n          ])\n          const wrapped: any = readonly(original)\n          expect(wrapped.size).toBe(2)\n          for (const [key, value] of wrapped) {\n            expect(isReadonly(key)).toBe(true)\n            expect(isReadonly(value)).toBe(true)\n          }\n          wrapped.forEach((value: any) => {\n            expect(isReadonly(value)).toBe(true)\n          })\n          for (const value of wrapped.values()) {\n            expect(isReadonly(value)).toBe(true)\n          }\n        })\n\n        test('should retrieve reactive + readonly values on iteration', () => {\n          const key1 = {}\n          const key2 = {}\n          const original = reactive(\n            new Map([\n              [key1, {}],\n              [key2, {}],\n            ]),\n          )\n          const wrapped: any = readonly(original)\n          expect(wrapped.size).toBe(2)\n          for (const [key, value] of wrapped) {\n            expect(isReadonly(key)).toBe(true)\n            expect(isReadonly(value)).toBe(true)\n            expect(isReactive(key)).toBe(true)\n            expect(isReactive(value)).toBe(true)\n          }\n          wrapped.forEach((value: any) => {\n            expect(isReadonly(value)).toBe(true)\n            expect(isReactive(value)).toBe(true)\n          })\n          for (const value of wrapped.values()) {\n            expect(isReadonly(value)).toBe(true)\n            expect(isReactive(value)).toBe(true)\n          }\n        })\n\n        test('should return undefined from Map.clear() call', () => {\n          const wrapped = readonly(new Collection())\n          expect(wrapped.clear()).toBeUndefined()\n          expect(\n            `Clear operation failed: target is readonly.`,\n          ).toHaveBeenWarned()\n        })\n      }\n    })\n  })\n\n  const sets = [Set, WeakSet]\n  sets.forEach((Collection: any) => {\n    describe(Collection.name, () => {\n      test('should make nested values readonly', () => {\n        const key1 = {}\n        const key2 = {}\n        const original = new Collection([key1, key2])\n        const wrapped = readonly(original)\n        expect(wrapped).not.toBe(original)\n        expect(isProxy(wrapped)).toBe(true)\n        expect(isReactive(wrapped)).toBe(false)\n        expect(isReadonly(wrapped)).toBe(true)\n        expect(isReactive(original)).toBe(false)\n        expect(isReadonly(original)).toBe(false)\n        expect(wrapped.has(reactive(key1))).toBe(true)\n        expect(original.has(reactive(key1))).toBe(false)\n      })\n\n      test('should not allow mutation & not trigger effect', () => {\n        const set = readonly(new Collection())\n        const key = {}\n        let dummy\n        effect(() => {\n          dummy = set.has(key)\n        })\n        expect(dummy).toBe(false)\n        set.add(key)\n        expect(dummy).toBe(false)\n        expect(set.has(key)).toBe(false)\n        expect(\n          `Add operation on key \"${key}\" failed: target is readonly.`,\n        ).toHaveBeenWarned()\n      })\n\n      if (Collection === Set) {\n        test('should retrieve readonly values on iteration', () => {\n          const original = new Collection([{}, {}])\n          const wrapped: any = readonly(original)\n          expect(wrapped.size).toBe(2)\n          for (const value of wrapped) {\n            expect(isReadonly(value)).toBe(true)\n          }\n          wrapped.forEach((value: any) => {\n            expect(isReadonly(value)).toBe(true)\n          })\n          for (const value of wrapped.values()) {\n            expect(isReadonly(value)).toBe(true)\n          }\n          for (const [v1, v2] of wrapped.entries()) {\n            expect(isReadonly(v1)).toBe(true)\n            expect(isReadonly(v2)).toBe(true)\n          }\n        })\n\n        test('should return undefined from Set.clear() call', () => {\n          const wrapped = readonly(new Collection())\n          expect(wrapped.clear()).toBeUndefined()\n          expect(\n            `Clear operation failed: target is readonly.`,\n          ).toHaveBeenWarned()\n        })\n      }\n    })\n  })\n\n  test('calling reactive on an readonly should return readonly', () => {\n    const a = readonly({})\n    const b = reactive(a)\n    expect(isReadonly(b)).toBe(true)\n    // should point to same original\n    expect(toRaw(a)).toBe(toRaw(b))\n  })\n\n  test('calling readonly on a reactive object should return readonly', () => {\n    const a = reactive({})\n    const b = readonly(a)\n    expect(isReadonly(b)).toBe(true)\n    // should point to same original\n    expect(toRaw(a)).toBe(toRaw(b))\n  })\n\n  test('readonly should track and trigger if wrapping reactive original', () => {\n    const a = reactive({ n: 1 })\n    const b = readonly(a)\n    // should return true since it's wrapping a reactive source\n    expect(isReactive(b)).toBe(true)\n\n    let dummy\n    effect(() => {\n      dummy = b.n\n    })\n    expect(dummy).toBe(1)\n    a.n++\n    expect(b.n).toBe(2)\n    expect(dummy).toBe(2)\n  })\n\n  test('readonly collection should not track', () => {\n    const map = new Map()\n    map.set('foo', 1)\n\n    const reMap = reactive(map)\n    const roMap = readonly(map)\n\n    let dummy\n    effect(() => {\n      dummy = roMap.get('foo')\n    })\n    expect(dummy).toBe(1)\n    reMap.set('foo', 2)\n    expect(roMap.get('foo')).toBe(2)\n    // should not trigger\n    expect(dummy).toBe(1)\n  })\n\n  test('readonly array should not track', () => {\n    const arr = [1]\n    const roArr = readonly(arr)\n\n    const eff = effect(() => {\n      roArr.includes(2)\n    })\n    expect(eff.effect.deps).toBeUndefined()\n  })\n\n  test('readonly should track and trigger if wrapping reactive original (collection)', () => {\n    const a = reactive(new Map())\n    const b = readonly(a)\n    // should return true since it's wrapping a reactive source\n    expect(isReactive(b)).toBe(true)\n\n    a.set('foo', 1)\n\n    let dummy\n    effect(() => {\n      dummy = b.get('foo')\n    })\n    expect(dummy).toBe(1)\n    a.set('foo', 2)\n    expect(b.get('foo')).toBe(2)\n    expect(dummy).toBe(2)\n  })\n\n  test('wrapping already wrapped value should return same Proxy', () => {\n    const original = { foo: 1 }\n    const wrapped = readonly(original)\n    const wrapped2 = readonly(wrapped)\n    expect(wrapped2).toBe(wrapped)\n  })\n\n  test('wrapping the same value multiple times should return same Proxy', () => {\n    const original = { foo: 1 }\n    const wrapped = readonly(original)\n    const wrapped2 = readonly(original)\n    expect(wrapped2).toBe(wrapped)\n  })\n\n  test('markRaw', () => {\n    const obj = readonly({\n      foo: { a: 1 },\n      bar: markRaw({ b: 2 }),\n    })\n    expect(isReadonly(obj.foo)).toBe(true)\n    expect(isReadonly(obj.bar)).toBe(false)\n  })\n\n  test('should make ref readonly', () => {\n    const n = readonly(ref(1))\n    // @ts-expect-error\n    n.value = 2\n    expect(n.value).toBe(1)\n    expect(\n      `Set operation on key \"value\" failed: target is readonly.`,\n    ).toHaveBeenWarned()\n  })\n\n  // https://github.com/vuejs/core/issues/3376\n  test('calling readonly on computed should allow computed to set its private properties', () => {\n    const r = ref<boolean>(false)\n    const c = computed(() => r.value)\n    const rC = readonly(c)\n\n    r.value = true\n\n    expect(rC.value).toBe(true)\n    expect(\n      'Set operation on key \"_dirty\" failed: target is readonly.',\n    ).not.toHaveBeenWarned()\n    // @ts-expect-error - non-existent property\n    rC.randomProperty = true\n\n    expect(\n      'Set operation on key \"randomProperty\" failed: target is readonly.',\n    ).toHaveBeenWarned()\n  })\n\n  // #4986\n  test('setting a readonly object as a property of a reactive object should retain readonly proxy', () => {\n    const r = readonly({})\n    const rr = reactive({}) as any\n    rr.foo = r\n    expect(rr.foo).toBe(r)\n    expect(isReadonly(rr.foo)).toBe(true)\n  })\n\n  test('attempting to write plain value to a readonly ref nested in a reactive object should fail', () => {\n    const r = ref(false)\n    const ror = readonly(r)\n    const obj = reactive({ ror })\n    obj.ror = true\n    expect(\n      `Set operation on key \"ror\" failed: target is readonly.`,\n    ).toHaveBeenWarned()\n    expect(obj.ror).toBe(false)\n  })\n\n  test('replacing a readonly ref nested in a reactive object with a new ref', () => {\n    const r = ref(false)\n    const ror = readonly(r)\n    const obj = reactive({ ror })\n    obj.ror = ref(true) as unknown as boolean\n    expect(obj.ror).toBe(true)\n    expect(toRaw(obj).ror).not.toBe(ror) // ref successfully replaced\n  })\n\n  test('setting readonly object to writable nested ref', () => {\n    const r = ref<any>()\n    const obj = reactive({ r })\n    const ro = readonly({})\n    obj.r = ro\n    expect(obj.r).toBe(ro)\n    expect(r.value).toBe(ro)\n  })\n\n  test('should keep nested ref readonly', () => {\n    const items = ref(['one', 'two', 'three'])\n    const obj = {\n      o: readonly({\n        items,\n      }),\n    }\n    expect(isReadonly(obj.o.items)).toBe(true)\n  })\n})\n\ntest('should be able to trigger with triggerRef', () => {\n  const r = shallowRef({ a: 1 })\n  const ror = readonly(r)\n  let dummy\n  effect(() => {\n    dummy = ror.value.a\n  })\n  r.value.a = 2\n  expect(dummy).toBe(1)\n  triggerRef(ror)\n  expect(dummy).toBe(2)\n})\n"
  },
  {
    "path": "packages/reactivity/__tests__/ref.spec.ts",
    "content": "import {\n  type Ref,\n  effect,\n  isReactive,\n  isRef,\n  reactive,\n  ref,\n  toRef,\n  toRefs,\n  toValue,\n} from '../src/index'\nimport { computed } from '@vue/runtime-dom'\nimport { customRef, shallowRef, triggerRef, unref } from '../src/ref'\nimport {\n  isReadonly,\n  isShallow,\n  readonly,\n  shallowReactive,\n  shallowReadonly,\n} from '../src/reactive'\n\ndescribe('reactivity/ref', () => {\n  it('should hold a value', () => {\n    const a = ref(1)\n    expect(a.value).toBe(1)\n    a.value = 2\n    expect(a.value).toBe(2)\n  })\n\n  it('should be reactive', () => {\n    const a = ref(1)\n    let dummy\n    const fn = vi.fn(() => {\n      dummy = a.value\n    })\n    effect(fn)\n    expect(fn).toHaveBeenCalledTimes(1)\n    expect(dummy).toBe(1)\n    a.value = 2\n    expect(fn).toHaveBeenCalledTimes(2)\n    expect(dummy).toBe(2)\n    // same value should not trigger\n    a.value = 2\n    expect(fn).toHaveBeenCalledTimes(2)\n  })\n\n  it('ref wrapped in reactive should not track internal _value access', () => {\n    const a = ref(1)\n    const b = reactive(a)\n    let dummy\n    const fn = vi.fn(() => {\n      dummy = b.value // this will observe both b.value and a.value access\n    })\n    effect(fn)\n    expect(fn).toHaveBeenCalledTimes(1)\n    expect(dummy).toBe(1)\n\n    // mutating a.value should only trigger effect once\n    a.value = 3\n    expect(fn).toHaveBeenCalledTimes(2)\n    expect(dummy).toBe(3)\n\n    // mutating b.value should trigger the effect twice. (once for a.value change and once for b.value change)\n    b.value = 5\n    expect(fn).toHaveBeenCalledTimes(4)\n    expect(dummy).toBe(5)\n  })\n\n  it('should make nested properties reactive', () => {\n    const a = ref({\n      count: 1,\n    })\n    let dummy\n    effect(() => {\n      dummy = a.value.count\n    })\n    expect(dummy).toBe(1)\n    a.value.count = 2\n    expect(dummy).toBe(2)\n  })\n\n  it('should work without initial value', () => {\n    const a = ref()\n    let dummy\n    effect(() => {\n      dummy = a.value\n    })\n    expect(dummy).toBe(undefined)\n    a.value = 2\n    expect(dummy).toBe(2)\n  })\n\n  it('should work like a normal property when nested in a reactive object', () => {\n    const a = ref(1)\n    const obj = reactive({\n      a,\n      b: {\n        c: a,\n      },\n    })\n\n    let dummy1: number\n    let dummy2: number\n\n    effect(() => {\n      dummy1 = obj.a\n      dummy2 = obj.b.c\n    })\n\n    const assertDummiesEqualTo = (val: number) =>\n      [dummy1, dummy2].forEach(dummy => expect(dummy).toBe(val))\n\n    assertDummiesEqualTo(1)\n    a.value++\n    assertDummiesEqualTo(2)\n    obj.a++\n    assertDummiesEqualTo(3)\n    obj.b.c++\n    assertDummiesEqualTo(4)\n  })\n\n  it('should unwrap nested ref in types', () => {\n    const a = ref(0)\n    const b = ref(a)\n\n    expect(typeof (b.value + 1)).toBe('number')\n  })\n\n  it('should unwrap nested values in types', () => {\n    const a = {\n      b: ref(0),\n    }\n\n    const c = ref(a)\n\n    expect(typeof (c.value.b + 1)).toBe('number')\n  })\n\n  it('should NOT unwrap ref types nested inside arrays', () => {\n    const arr = ref([1, ref(3)]).value\n    expect(isRef(arr[0])).toBe(false)\n    expect(isRef(arr[1])).toBe(true)\n    expect((arr[1] as Ref).value).toBe(3)\n  })\n\n  it('should unwrap ref types as props of arrays', () => {\n    const arr = [ref(0)]\n    const symbolKey = Symbol('')\n    arr['' as any] = ref(1)\n    arr[symbolKey as any] = ref(2)\n    const arrRef = ref(arr).value\n    expect(isRef(arrRef[0])).toBe(true)\n    expect(isRef(arrRef['' as any])).toBe(false)\n    expect(isRef(arrRef[symbolKey as any])).toBe(false)\n    expect(arrRef['' as any]).toBe(1)\n    expect(arrRef[symbolKey as any]).toBe(2)\n  })\n\n  it('should keep tuple types', () => {\n    const tuple: [number, string, { a: number }, () => number, Ref<number>] = [\n      0,\n      '1',\n      { a: 1 },\n      () => 0,\n      ref(0),\n    ]\n    const tupleRef = ref(tuple)\n\n    tupleRef.value[0]++\n    expect(tupleRef.value[0]).toBe(1)\n    tupleRef.value[1] += '1'\n    expect(tupleRef.value[1]).toBe('11')\n    tupleRef.value[2].a++\n    expect(tupleRef.value[2].a).toBe(2)\n    expect(tupleRef.value[3]()).toBe(0)\n    tupleRef.value[4].value++\n    expect(tupleRef.value[4].value).toBe(1)\n  })\n\n  it('should keep symbols', () => {\n    const customSymbol = Symbol()\n    const obj = {\n      [Symbol.asyncIterator]: ref(1),\n      [Symbol.hasInstance]: { a: ref('a') },\n      [Symbol.isConcatSpreadable]: { b: ref(true) },\n      [Symbol.iterator]: [ref(1)],\n      [Symbol.match]: new Set<Ref<number>>(),\n      [Symbol.matchAll]: new Map<number, Ref<string>>(),\n      [Symbol.replace]: { arr: [ref('a')] },\n      [Symbol.search]: { set: new Set<Ref<number>>() },\n      [Symbol.species]: { map: new Map<number, Ref<string>>() },\n      [Symbol.split]: new WeakSet<Ref<boolean>>(),\n      [Symbol.toPrimitive]: new WeakMap<Ref<boolean>, string>(),\n      [Symbol.toStringTag]: { weakSet: new WeakSet<Ref<boolean>>() },\n      [Symbol.unscopables]: { weakMap: new WeakMap<Ref<boolean>, string>() },\n      [customSymbol]: { arr: [ref(1)] },\n    }\n\n    const objRef = ref(obj)\n\n    const keys: (keyof typeof obj)[] = [\n      Symbol.asyncIterator,\n      Symbol.hasInstance,\n      Symbol.isConcatSpreadable,\n      Symbol.iterator,\n      Symbol.match,\n      Symbol.matchAll,\n      Symbol.replace,\n      Symbol.search,\n      Symbol.species,\n      Symbol.split,\n      Symbol.toPrimitive,\n      Symbol.toStringTag,\n      Symbol.unscopables,\n      customSymbol,\n    ]\n\n    keys.forEach(key => {\n      expect(objRef.value[key]).toStrictEqual(obj[key])\n    })\n  })\n\n  test('unref', () => {\n    expect(unref(1)).toBe(1)\n    expect(unref(ref(1))).toBe(1)\n  })\n\n  test('shallowRef', () => {\n    const sref = shallowRef({ a: 1 })\n    expect(isReactive(sref.value)).toBe(false)\n\n    let dummy\n    effect(() => {\n      dummy = sref.value.a\n    })\n    expect(dummy).toBe(1)\n\n    sref.value = { a: 2 }\n    expect(isReactive(sref.value)).toBe(false)\n    expect(dummy).toBe(2)\n  })\n\n  test('shallowRef force trigger', () => {\n    const sref = shallowRef({ a: 1 })\n    let dummy\n    effect(() => {\n      dummy = sref.value.a\n    })\n    expect(dummy).toBe(1)\n\n    sref.value.a = 2\n    expect(dummy).toBe(1) // should not trigger yet\n\n    // force trigger\n    triggerRef(sref)\n    expect(dummy).toBe(2)\n  })\n\n  test('shallowRef isShallow', () => {\n    expect(isShallow(shallowRef({ a: 1 }))).toBe(true)\n  })\n\n  test('isRef', () => {\n    expect(isRef(ref(1))).toBe(true)\n    expect(isRef(computed(() => 1))).toBe(true)\n\n    expect(isRef(0)).toBe(false)\n    expect(isRef(1)).toBe(false)\n    // an object that looks like a ref isn't necessarily a ref\n    expect(isRef({ value: 0 })).toBe(false)\n  })\n\n  test('toRef', () => {\n    const a = reactive({\n      x: 1,\n    })\n    const x = toRef(a, 'x')\n\n    const b = ref({ y: 1 })\n\n    const c = toRef(b)\n\n    const d = toRef({ z: 1 })\n\n    expect(isRef(d)).toBe(true)\n    expect(d.value.z).toBe(1)\n\n    expect(c).toBe(b)\n\n    expect(isRef(x)).toBe(true)\n    expect(x.value).toBe(1)\n\n    // source -> proxy\n    a.x = 2\n    expect(x.value).toBe(2)\n\n    // proxy -> source\n    x.value = 3\n    expect(a.x).toBe(3)\n\n    // reactivity\n    let dummyX\n    effect(() => {\n      dummyX = x.value\n    })\n    expect(dummyX).toBe(x.value)\n\n    // mutating source should trigger effect using the proxy refs\n    a.x = 4\n    expect(dummyX).toBe(4)\n\n    // a ref in a non-reactive object should be unwrapped\n    const r: any = { x: ref(1) }\n    const t = toRef(r, 'x')\n    expect(t.value).toBe(1)\n\n    r.x.value = 2\n    expect(t.value).toBe(2)\n\n    t.value = 3\n    expect(t.value).toBe(3)\n    expect(r.x.value).toBe(3)\n\n    // with a default\n    const u = toRef(r, 'x', 7)\n    expect(u.value).toBe(3)\n\n    r.x.value = undefined\n    expect(r.x.value).toBeUndefined()\n    expect(t.value).toBeUndefined()\n    expect(u.value).toBe(7)\n\n    u.value = 7\n    expect(r.x.value).toBe(7)\n    expect(t.value).toBe(7)\n    expect(u.value).toBe(7)\n  })\n\n  test('toRef on array', () => {\n    const a: any = reactive(['a', 'b'])\n    const r = toRef(a, 1)\n    expect(r.value).toBe('b')\n    r.value = 'c'\n    expect(r.value).toBe('c')\n    expect(a[1]).toBe('c')\n\n    a[1] = ref('d')\n    expect(isRef(a[1])).toBe(true)\n    expect(r.value).toBe('d')\n    r.value = 'e'\n    expect(isRef(a[1])).toBe(true)\n    expect(a[1].value).toBe('e')\n\n    const s = toRef(a, 2, 'def')\n    const len = toRef(a, 'length')\n\n    expect(s.value).toBe('def')\n    expect(len.value).toBe(2)\n\n    a.push('f')\n    expect(s.value).toBe('f')\n    expect(len.value).toBe(3)\n\n    len.value = 2\n\n    expect(s.value).toBe('def')\n    expect(len.value).toBe(2)\n\n    const symbol = Symbol()\n    const t = toRef(a, 'foo')\n    const u = toRef(a, symbol)\n    expect(t.value).toBeUndefined()\n    expect(u.value).toBeUndefined()\n\n    const foo = ref(3)\n    const bar = ref(5)\n    a.foo = foo\n    a[symbol] = bar\n    expect(t.value).toBe(3)\n    expect(u.value).toBe(5)\n\n    t.value = 4\n    u.value = 6\n\n    expect(a.foo).toBe(4)\n    expect(foo.value).toBe(4)\n    expect(a[symbol]).toBe(6)\n    expect(bar.value).toBe(6)\n  })\n\n  test('toRef default value', () => {\n    const a: { x: number | undefined } = { x: undefined }\n    const x = toRef(a, 'x', 1)\n    expect(x.value).toBe(1)\n\n    a.x = 2\n    expect(x.value).toBe(2)\n\n    a.x = undefined\n    expect(x.value).toBe(1)\n  })\n\n  test('toRef getter', () => {\n    const x = toRef(() => 1)\n    expect(x.value).toBe(1)\n    expect(isRef(x)).toBe(true)\n    expect(unref(x)).toBe(1)\n    //@ts-expect-error\n    expect(() => (x.value = 123)).toThrow()\n\n    expect(isReadonly(x)).toBe(true)\n  })\n\n  test('toRef lazy evaluation of properties inside a proxy', () => {\n    const fn = vi.fn(() => 5)\n    const num = computed(fn)\n    const a = toRef({ num }, 'num')\n    const b = toRef(reactive({ num }), 'num')\n    const c = toRef(readonly({ num }), 'num')\n    const d = toRef(shallowReactive({ num }), 'num')\n    const e = toRef(shallowReadonly({ num }), 'num')\n\n    expect(fn).not.toHaveBeenCalled()\n\n    expect(a.value).toBe(5)\n    expect(b.value).toBe(5)\n    expect(c.value).toBe(5)\n    expect(d.value).toBe(5)\n    expect(e.value).toBe(5)\n    expect(fn).toHaveBeenCalledTimes(1)\n  })\n\n  test('toRef with shallowReactive/shallowReadonly', () => {\n    const r = ref(0)\n    const s1 = shallowReactive<{ foo: any }>({ foo: r })\n    const t1 = toRef(s1, 'foo', 2)\n    const s2 = shallowReadonly(s1)\n    const t2 = toRef(s2, 'foo', 3)\n\n    expect(r.value).toBe(0)\n    expect(s1.foo.value).toBe(0)\n    expect(t1.value).toBe(0)\n    expect(s2.foo.value).toBe(0)\n    expect(t2.value).toBe(0)\n\n    s1.foo = ref(1)\n\n    expect(r.value).toBe(0)\n    expect(s1.foo.value).toBe(1)\n    expect(t1.value).toBe(1)\n    expect(s2.foo.value).toBe(1)\n    expect(t2.value).toBe(1)\n\n    s1.foo.value = undefined\n\n    expect(r.value).toBe(0)\n    expect(s1.foo.value).toBeUndefined()\n    expect(t1.value).toBe(2)\n    expect(s2.foo.value).toBeUndefined()\n    expect(t2.value).toBe(3)\n\n    t1.value = 2\n\n    expect(r.value).toBe(0)\n    expect(s1.foo.value).toBe(2)\n    expect(t1.value).toBe(2)\n    expect(s2.foo.value).toBe(2)\n    expect(t2.value).toBe(2)\n\n    t2.value = 4\n\n    expect(r.value).toBe(0)\n    expect(s1.foo.value).toBe(4)\n    expect(t1.value).toBe(4)\n    expect(s2.foo.value).toBe(4)\n    expect(t2.value).toBe(4)\n\n    s1.foo = undefined\n\n    expect(r.value).toBe(0)\n    expect(s1.foo).toBeUndefined()\n    expect(t1.value).toBe(2)\n    expect(s2.foo).toBeUndefined()\n    expect(t2.value).toBe(3)\n  })\n\n  test('toRef for shallowReadonly around reactive', () => {\n    const get = vi.fn(() => 3)\n    const set = vi.fn()\n    const num = computed({ get, set })\n    const t = toRef(shallowReadonly(reactive({ num })), 'num')\n\n    expect(get).not.toHaveBeenCalled()\n    expect(set).not.toHaveBeenCalled()\n\n    t.value = 1\n\n    expect(\n      'Set operation on key \"num\" failed: target is readonly',\n    ).toHaveBeenWarned()\n\n    expect(get).not.toHaveBeenCalled()\n    expect(set).not.toHaveBeenCalled()\n\n    expect(t.value).toBe(3)\n\n    expect(get).toHaveBeenCalledTimes(1)\n    expect(set).not.toHaveBeenCalled()\n  })\n\n  test('toRef for readonly around shallowReactive', () => {\n    const get = vi.fn(() => 3)\n    const set = vi.fn()\n    const num = computed({ get, set })\n    const t: Ref<number> = toRef(readonly(shallowReactive({ num })), 'num')\n\n    expect(get).not.toHaveBeenCalled()\n    expect(set).not.toHaveBeenCalled()\n\n    t.value = 1\n\n    expect(\n      'Set operation on key \"num\" failed: target is readonly',\n    ).toHaveBeenWarned()\n\n    expect(get).not.toHaveBeenCalled()\n    expect(set).not.toHaveBeenCalled()\n\n    expect(t.value).toBe(3)\n\n    expect(get).toHaveBeenCalledTimes(1)\n    expect(set).not.toHaveBeenCalled()\n  })\n\n  test(`toRef doesn't bypass the proxy when getting/setting a nested ref`, () => {\n    const r = ref(2)\n    const obj = shallowReactive({ num: r })\n    const t = toRef(obj, 'num')\n\n    expect(t.value).toBe(2)\n\n    effect(() => {\n      t.value = 3\n    })\n\n    expect(t.value).toBe(3)\n    expect(r.value).toBe(3)\n\n    const s = ref(4)\n    obj.num = s\n\n    expect(t.value).toBe(3)\n    expect(s.value).toBe(3)\n  })\n\n  test('toRefs', () => {\n    const a = reactive({\n      x: 1,\n      y: 2,\n    })\n\n    const { x, y } = toRefs(a)\n\n    expect(isRef(x)).toBe(true)\n    expect(isRef(y)).toBe(true)\n    expect(x.value).toBe(1)\n    expect(y.value).toBe(2)\n\n    // source -> proxy\n    a.x = 2\n    a.y = 3\n    expect(x.value).toBe(2)\n    expect(y.value).toBe(3)\n\n    // proxy -> source\n    x.value = 3\n    y.value = 4\n    expect(a.x).toBe(3)\n    expect(a.y).toBe(4)\n\n    // reactivity\n    let dummyX, dummyY\n    effect(() => {\n      dummyX = x.value\n      dummyY = y.value\n    })\n    expect(dummyX).toBe(x.value)\n    expect(dummyY).toBe(y.value)\n\n    // mutating source should trigger effect using the proxy refs\n    a.x = 4\n    a.y = 5\n    expect(dummyX).toBe(4)\n    expect(dummyY).toBe(5)\n  })\n\n  test('toRefs should warn on plain object', () => {\n    toRefs({})\n    expect(`toRefs() expects a reactive object`).toHaveBeenWarned()\n  })\n\n  test('toRefs should warn on plain array', () => {\n    toRefs([])\n    expect(`toRefs() expects a reactive object`).toHaveBeenWarned()\n  })\n\n  test('toRefs reactive array', () => {\n    const arr = reactive(['a', 'b', 'c'])\n    const refs = toRefs(arr)\n\n    expect(Array.isArray(refs)).toBe(true)\n\n    refs[0].value = '1'\n    expect(arr[0]).toBe('1')\n\n    arr[1] = '2'\n    expect(refs[1].value).toBe('2')\n  })\n\n  test('customRef', () => {\n    let value = 1\n    let _trigger: () => void\n\n    const custom = customRef((track, trigger) => ({\n      get() {\n        track()\n        return value\n      },\n      set(newValue: number) {\n        value = newValue\n        _trigger = trigger\n      },\n    }))\n\n    expect(isRef(custom)).toBe(true)\n\n    let dummy\n    effect(() => {\n      dummy = custom.value\n    })\n    expect(dummy).toBe(1)\n\n    custom.value = 2\n    // should not trigger yet\n    expect(dummy).toBe(1)\n\n    _trigger!()\n    expect(dummy).toBe(2)\n  })\n\n  test('should not trigger when setting value to same proxy', () => {\n    const obj = reactive({ count: 0 })\n\n    const a = ref(obj)\n    const spy1 = vi.fn(() => a.value)\n\n    effect(spy1)\n\n    a.value = obj\n    expect(spy1).toBeCalledTimes(1)\n\n    const b = shallowRef(obj)\n    const spy2 = vi.fn(() => b.value)\n\n    effect(spy2)\n\n    b.value = obj\n    expect(spy2).toBeCalledTimes(1)\n  })\n\n  test('ref should preserve value shallow/readonly-ness', () => {\n    const original = {}\n    const r = reactive(original)\n    const s = shallowReactive(original)\n    const rr = readonly(original)\n    const a = ref(original)\n\n    expect(a.value).toBe(r)\n\n    a.value = s\n    expect(a.value).toBe(s)\n    expect(a.value).not.toBe(r)\n\n    a.value = rr\n    expect(a.value).toBe(rr)\n    expect(a.value).not.toBe(r)\n  })\n\n  test('should not trigger when setting the same raw object', () => {\n    const obj = {}\n    const r = ref(obj)\n    const spy = vi.fn()\n    effect(() => spy(r.value))\n    expect(spy).toHaveBeenCalledTimes(1)\n\n    r.value = obj\n    expect(spy).toHaveBeenCalledTimes(1)\n  })\n\n  test('toValue', () => {\n    const a = ref(1)\n    const b = computed(() => a.value + 1)\n    const c = () => a.value + 2\n    const d = 4\n\n    expect(toValue(a)).toBe(1)\n    expect(toValue(b)).toBe(2)\n    expect(toValue(c)).toBe(3)\n    expect(toValue(d)).toBe(4)\n  })\n\n  test('ref w/ customRef w/ getterRef w/ objectRef should store value cache', () => {\n    const refValue = ref(1)\n    // @ts-expect-error private field\n    expect(refValue._value).toBe(1)\n\n    let customRefValueCache = 0\n    const customRefValue = customRef((track, trigger) => {\n      return {\n        get() {\n          track()\n          return customRefValueCache\n        },\n        set(value: number) {\n          customRefValueCache = value\n          trigger()\n        },\n      }\n    })\n    customRefValue.value\n\n    // @ts-expect-error internal field\n    expect(customRefValue._value).toBe(0)\n\n    const getterRefValue = toRef(() => 1)\n    getterRefValue.value\n    // @ts-expect-error internal field\n    expect(getterRefValue._value).toBe(1)\n\n    const objectRefValue = toRef({ value: 1 }, 'value')\n    objectRefValue.value\n    // @ts-expect-error internal field\n    expect(objectRefValue._value).toBe(1)\n  })\n})\n"
  },
  {
    "path": "packages/reactivity/__tests__/shallowReactive.spec.ts",
    "content": "import {\n  isReactive,\n  isShallow,\n  reactive,\n  shallowReactive,\n  shallowReadonly,\n} from '../src/reactive'\n\nimport { effect } from '../src/effect'\nimport { type Ref, isRef, ref } from '../src/ref'\n\ndescribe('shallowReactive', () => {\n  test('should not make non-reactive properties reactive', () => {\n    const props = shallowReactive({ n: { foo: 1 } })\n    expect(isReactive(props.n)).toBe(false)\n  })\n\n  test('should keep reactive properties reactive', () => {\n    const props: any = shallowReactive({ n: reactive({ foo: 1 }) })\n    props.n = reactive({ foo: 2 })\n    expect(isReactive(props.n)).toBe(true)\n  })\n\n  // #2843\n  test('should allow shallow and normal reactive for same target', () => {\n    const original = { foo: {} }\n    const shallowProxy = shallowReactive(original)\n    const reactiveProxy = reactive(original)\n    expect(shallowProxy).not.toBe(reactiveProxy)\n    expect(isReactive(shallowProxy.foo)).toBe(false)\n    expect(isReactive(reactiveProxy.foo)).toBe(true)\n  })\n\n  test('isShallow', () => {\n    expect(isShallow(shallowReactive({}))).toBe(true)\n    expect(isShallow(shallowReadonly({}))).toBe(true)\n  })\n\n  // #5271\n  test('should respect shallow reactive nested inside reactive on reset', () => {\n    const r = reactive({ foo: shallowReactive({ bar: {} }) })\n    expect(isShallow(r.foo)).toBe(true)\n    expect(isReactive(r.foo.bar)).toBe(false)\n\n    r.foo = shallowReactive({ bar: {} })\n    expect(isShallow(r.foo)).toBe(true)\n    expect(isReactive(r.foo.bar)).toBe(false)\n  })\n\n  // vuejs/vue#12597\n  test('should not unwrap refs', () => {\n    const foo = shallowReactive({\n      bar: ref(123),\n    })\n    expect(isRef(foo.bar)).toBe(true)\n    expect(foo.bar.value).toBe(123)\n  })\n\n  // vuejs/vue#12688\n  test('should not mutate refs', () => {\n    const original = ref(123)\n    const foo = shallowReactive<{ bar: Ref<number> | number }>({\n      bar: original,\n    })\n    expect(foo.bar).toBe(original)\n    foo.bar = 234\n    expect(foo.bar).toBe(234)\n    expect(original.value).toBe(123)\n  })\n\n  test('should respect shallow/deep versions of same target on access', () => {\n    const original = {}\n    const shallow = shallowReactive(original)\n    const deep = reactive(original)\n    const r = reactive({ shallow, deep })\n    expect(r.shallow).toBe(shallow)\n    expect(r.deep).toBe(deep)\n  })\n\n  describe('collections', () => {\n    test('should be reactive', () => {\n      const shallowSet = shallowReactive(new Set())\n      const a = {}\n      let size\n\n      effect(() => {\n        size = shallowSet.size\n      })\n\n      expect(size).toBe(0)\n\n      shallowSet.add(a)\n      expect(size).toBe(1)\n\n      shallowSet.delete(a)\n      expect(size).toBe(0)\n    })\n\n    test('should not observe when iterating', () => {\n      const shallowSet = shallowReactive(new Set())\n      const a = {}\n      shallowSet.add(a)\n\n      const spreadA = [...shallowSet][0]\n      expect(isReactive(spreadA)).toBe(false)\n    })\n\n    test('should not get reactive entry', () => {\n      const shallowMap = shallowReactive(new Map())\n      const a = {}\n      const key = 'a'\n\n      shallowMap.set(key, a)\n\n      expect(isReactive(shallowMap.get(key))).toBe(false)\n    })\n\n    test('should not get reactive on foreach', () => {\n      const shallowSet = shallowReactive(new Set())\n      const a = {}\n      shallowSet.add(a)\n\n      shallowSet.forEach(x => expect(isReactive(x)).toBe(false))\n    })\n\n    test('Setting a reactive object on a shallowReactive map', () => {\n      const msg = ref('ads')\n      const bar = reactive({ msg })\n      const foo = shallowReactive(new Map([['foo1', bar]]))\n      foo.set('foo2', bar)\n\n      expect(isReactive(foo.get('foo2'))).toBe(true)\n      expect(isReactive(foo.get('foo1'))).toBe(true)\n    })\n\n    test('Setting a reactive object on a shallowReactive set', () => {\n      const msg = ref(1)\n      const bar = reactive({ msg })\n      const foo = reactive({ msg })\n\n      const deps = shallowReactive(new Set([bar]))\n      deps.add(foo)\n\n      deps.forEach(dep => {\n        expect(isReactive(dep)).toBe(true)\n      })\n    })\n\n    // #1210\n    test('onTrack on called on objectSpread', () => {\n      const onTrackFn = vi.fn()\n      const shallowSet = shallowReactive(new Set())\n      let a\n      effect(\n        () => {\n          a = Array.from(shallowSet)\n        },\n        {\n          onTrack: onTrackFn,\n        },\n      )\n\n      expect(a).toMatchObject([])\n      expect(onTrackFn).toHaveBeenCalled()\n    })\n  })\n\n  describe('array', () => {\n    test('should be reactive', () => {\n      const shallowArray = shallowReactive<unknown[]>([])\n      const a = {}\n      let size\n\n      effect(() => {\n        size = shallowArray.length\n      })\n\n      expect(size).toBe(0)\n\n      shallowArray.push(a)\n      expect(size).toBe(1)\n\n      shallowArray.pop()\n      expect(size).toBe(0)\n    })\n\n    test('should not observe when iterating', () => {\n      const shallowArray = shallowReactive<object[]>([])\n      const a = {}\n      shallowArray.push(a)\n\n      const spreadA = [...shallowArray][0]\n      expect(isReactive(spreadA)).toBe(false)\n    })\n\n    test('onTrack on called on objectSpread', () => {\n      const onTrackFn = vi.fn()\n      const shallowArray = shallowReactive([])\n      let a\n      effect(\n        () => {\n          a = Array.from(shallowArray)\n        },\n        {\n          onTrack: onTrackFn,\n        },\n      )\n\n      expect(a).toMatchObject([])\n      expect(onTrackFn).toHaveBeenCalled()\n    })\n  })\n})\n"
  },
  {
    "path": "packages/reactivity/__tests__/shallowReadonly.spec.ts",
    "content": "import { isReactive, isReadonly, readonly, shallowReadonly } from '../src'\n\ndescribe('reactivity/shallowReadonly', () => {\n  test('should not make non-reactive properties reactive', () => {\n    const props = shallowReadonly({ n: { foo: 1 } })\n    expect(isReactive(props.n)).toBe(false)\n  })\n\n  test('should make root level properties readonly', () => {\n    const props = shallowReadonly({ n: 1 })\n    // @ts-expect-error\n    props.n = 2\n    expect(props.n).toBe(1)\n    expect(\n      `Set operation on key \"n\" failed: target is readonly.`,\n    ).toHaveBeenWarned()\n  })\n\n  // to retain 2.x behavior.\n  test('should NOT make nested properties readonly', () => {\n    const props = shallowReadonly({ n: { foo: 1 } })\n\n    props.n.foo = 2\n    expect(props.n.foo).toBe(2)\n    expect(\n      `Set operation on key \"foo\" failed: target is readonly.`,\n    ).not.toHaveBeenWarned()\n  })\n\n  // #2843\n  test('should differentiate from normal readonly calls', () => {\n    const original = { foo: {} }\n    const shallowProxy = shallowReadonly(original)\n    const reactiveProxy = readonly(original)\n    expect(shallowProxy).not.toBe(reactiveProxy)\n    expect(isReadonly(shallowProxy.foo)).toBe(false)\n    expect(isReadonly(reactiveProxy.foo)).toBe(true)\n  })\n\n  describe('collection/Map', () => {\n    ;[Map, WeakMap].forEach(Collection => {\n      test('should make the map/weak-map readonly', () => {\n        const key = {}\n        const val = { foo: 1 }\n        const original = new Collection([[key, val]])\n        const sroMap = shallowReadonly(original)\n        expect(isReadonly(sroMap)).toBe(true)\n        expect(isReactive(sroMap)).toBe(false)\n        expect(sroMap.get(key)).toBe(val)\n\n        sroMap.set(key, {} as any)\n        expect(\n          `Set operation on key \"[object Object]\" failed: target is readonly.`,\n        ).toHaveBeenWarned()\n      })\n\n      test('should not make nested values readonly', () => {\n        const key = {}\n        const val = { foo: 1 }\n        const original = new Collection([[key, val]])\n        const sroMap = shallowReadonly(original)\n        expect(isReadonly(sroMap.get(key))).toBe(false)\n        expect(isReactive(sroMap.get(key))).toBe(false)\n\n        sroMap.get(key)!.foo = 2\n        expect(\n          `Set operation on key \"foo\" failed: target is readonly.`,\n        ).not.toHaveBeenWarned()\n      })\n    })\n\n    test('should not make the value generated by the iterable method readonly', () => {\n      const key = {}\n      const val = { foo: 1 }\n      const original = new Map([[key, val]])\n      const sroMap = shallowReadonly(original)\n\n      const values1 = [...sroMap.values()]\n      const values2 = [...sroMap.entries()]\n\n      expect(isReadonly(values1[0])).toBe(false)\n      expect(isReactive(values1[0])).toBe(false)\n      expect(values1[0]).toBe(val)\n\n      values1[0].foo = 2\n      expect(\n        `Set operation on key \"foo\" failed: target is readonly.`,\n      ).not.toHaveBeenWarned()\n\n      expect(isReadonly(values2[0][1])).toBe(false)\n      expect(isReactive(values2[0][1])).toBe(false)\n      expect(values2[0][1]).toBe(val)\n\n      values2[0][1].foo = 2\n      expect(\n        `Set operation on key \"foo\" failed: target is readonly.`,\n      ).not.toHaveBeenWarned()\n    })\n\n    test('should not make the value generated by the forEach method readonly', () => {\n      const val = { foo: 1 }\n      const original = new Map([['key', val]])\n      const sroMap = shallowReadonly(original)\n\n      sroMap.forEach(val => {\n        expect(isReadonly(val)).toBe(false)\n        expect(isReactive(val)).toBe(false)\n        expect(val).toBe(val)\n\n        val.foo = 2\n        expect(\n          `Set operation on key \"foo\" failed: target is readonly.`,\n        ).not.toHaveBeenWarned()\n      })\n    })\n\n    test('should return undefined from Map.clear() call', () => {\n      const sroMap = shallowReadonly(new Map())\n      expect(sroMap.clear()).toBeUndefined()\n      expect(`Clear operation failed: target is readonly.`).toHaveBeenWarned()\n    })\n  })\n\n  describe('collection/Set', () => {\n    test('should make the set/weak-set readonly', () => {\n      ;[Set, WeakSet].forEach(Collection => {\n        const obj = { foo: 1 }\n        const original = new Collection([obj])\n        const sroSet = shallowReadonly(original)\n        expect(isReadonly(sroSet)).toBe(true)\n        expect(isReactive(sroSet)).toBe(false)\n        expect(sroSet.has(obj)).toBe(true)\n\n        sroSet.add({} as any)\n        expect(\n          `Add operation on key \"[object Object]\" failed: target is readonly.`,\n        ).toHaveBeenWarned()\n      })\n    })\n\n    test('should not make nested values readonly', () => {\n      const obj = { foo: 1 }\n      const original = new Set([obj])\n      const sroSet = shallowReadonly(original)\n\n      const values = [...sroSet.values()]\n\n      expect(values[0]).toBe(obj)\n      expect(isReadonly(values[0])).toBe(false)\n      expect(isReactive(values[0])).toBe(false)\n\n      sroSet.add({} as any)\n      expect(\n        `Add operation on key \"[object Object]\" failed: target is readonly.`,\n      ).toHaveBeenWarned()\n\n      values[0].foo = 2\n      expect(\n        `Set operation on key \"foo\" failed: target is readonly.`,\n      ).not.toHaveBeenWarned()\n    })\n\n    test('should not make the value generated by the iterable method readonly', () => {\n      const val = { foo: 1 }\n      const original = new Set([val])\n      const sroSet = shallowReadonly(original)\n\n      const values1 = [...sroSet.values()]\n      const values2 = [...sroSet.entries()]\n\n      expect(isReadonly(values1[0])).toBe(false)\n      expect(isReactive(values1[0])).toBe(false)\n      expect(values1[0]).toBe(val)\n\n      values1[0].foo = 2\n      expect(\n        `Set operation on key \"foo\" failed: target is readonly.`,\n      ).not.toHaveBeenWarned()\n\n      expect(isReadonly(values2[0][1])).toBe(false)\n      expect(isReactive(values2[0][1])).toBe(false)\n      expect(values2[0][1]).toBe(val)\n\n      values2[0][1].foo = 2\n      expect(\n        `Set operation on key \"foo\" failed: target is readonly.`,\n      ).not.toHaveBeenWarned()\n    })\n\n    test('should not make the value generated by the forEach method readonly', () => {\n      const val = { foo: 1 }\n      const original = new Set([val])\n      const sroSet = shallowReadonly(original)\n\n      sroSet.forEach(val => {\n        expect(isReadonly(val)).toBe(false)\n        expect(isReactive(val)).toBe(false)\n        expect(val).toBe(val)\n\n        val.foo = 2\n        expect(\n          `Set operation on key \"foo\" failed: target is readonly.`,\n        ).not.toHaveBeenWarned()\n      })\n    })\n\n    test('should return undefined from Set.clear() call', () => {\n      const sroSet = shallowReadonly(new Set())\n      expect(sroSet.clear()).toBeUndefined()\n      expect(`Clear operation failed: target is readonly.`).toHaveBeenWarned()\n    })\n  })\n})\n"
  },
  {
    "path": "packages/reactivity/__tests__/watch.spec.ts",
    "content": "import {\n  EffectScope,\n  type Ref,\n  WatchErrorCodes,\n  type WatchOptions,\n  type WatchScheduler,\n  computed,\n  onWatcherCleanup,\n  ref,\n  watch,\n} from '../src'\n\nconst queue: (() => void)[] = []\n\n// a simple scheduler for testing purposes\nlet isFlushPending = false\nconst resolvedPromise = /*@__PURE__*/ Promise.resolve() as Promise<any>\nconst nextTick = (fn?: () => any) =>\n  fn ? resolvedPromise.then(fn) : resolvedPromise\n\nconst scheduler: WatchScheduler = (job, isFirstRun) => {\n  if (isFirstRun) {\n    job()\n  } else {\n    queue.push(job)\n    flushJobs()\n  }\n}\n\nconst flushJobs = () => {\n  if (isFlushPending) return\n  isFlushPending = true\n  resolvedPromise.then(() => {\n    queue.forEach(job => job())\n    queue.length = 0\n    isFlushPending = false\n  })\n}\n\ndescribe('watch', () => {\n  test('effect', () => {\n    let dummy: any\n    const source = ref(0)\n    watch(() => {\n      dummy = source.value\n    })\n    expect(dummy).toBe(0)\n    source.value++\n    expect(dummy).toBe(1)\n  })\n\n  test('with callback', () => {\n    let dummy: any\n    const source = ref(0)\n    watch(source, () => {\n      dummy = source.value\n    })\n    expect(dummy).toBe(undefined)\n    source.value++\n    expect(dummy).toBe(1)\n  })\n\n  test('call option with error handling', () => {\n    const onError = vi.fn()\n    const call: WatchOptions['call'] = function call(fn, type, args) {\n      if (Array.isArray(fn)) {\n        fn.forEach(f => call(f, type, args))\n        return\n      }\n      try {\n        fn.apply(null, args)\n      } catch (e) {\n        onError(e, type)\n      }\n    }\n\n    watch(\n      () => {\n        throw 'oops in effect'\n      },\n      null,\n      { call },\n    )\n\n    const source = ref(0)\n    const effect = watch(\n      source,\n      () => {\n        onWatcherCleanup(() => {\n          throw 'oops in cleanup'\n        })\n        throw 'oops in watch'\n      },\n      { call },\n    )\n\n    expect(onError.mock.calls.length).toBe(1)\n    expect(onError.mock.calls[0]).toMatchObject([\n      'oops in effect',\n      WatchErrorCodes.WATCH_CALLBACK,\n    ])\n\n    source.value++\n    expect(onError.mock.calls.length).toBe(2)\n    expect(onError.mock.calls[1]).toMatchObject([\n      'oops in watch',\n      WatchErrorCodes.WATCH_CALLBACK,\n    ])\n\n    effect!.stop()\n    source.value++\n    expect(onError.mock.calls.length).toBe(3)\n    expect(onError.mock.calls[2]).toMatchObject([\n      'oops in cleanup',\n      WatchErrorCodes.WATCH_CLEANUP,\n    ])\n  })\n\n  test('watch with onWatcherCleanup', async () => {\n    let dummy = 0\n    let source: Ref<number>\n    const scope = new EffectScope()\n\n    scope.run(() => {\n      source = ref(0)\n      watch(onCleanup => {\n        source.value\n\n        onCleanup(() => (dummy += 2))\n        onWatcherCleanup(() => (dummy += 3))\n        onWatcherCleanup(() => (dummy += 5))\n      })\n    })\n    expect(dummy).toBe(0)\n\n    scope.run(() => {\n      source.value++\n    })\n    expect(dummy).toBe(10)\n\n    scope.run(() => {\n      source.value++\n    })\n    expect(dummy).toBe(20)\n\n    scope.stop()\n    expect(dummy).toBe(30)\n  })\n\n  test('nested calls to baseWatch and onWatcherCleanup', async () => {\n    let calls: string[] = []\n    let source: Ref<number>\n    let copyist: Ref<number>\n    const scope = new EffectScope()\n\n    scope.run(() => {\n      source = ref(0)\n      copyist = ref(0)\n      // sync by default\n      watch(\n        () => {\n          const current = (copyist.value = source.value)\n          onWatcherCleanup(() => calls.push(`sync ${current}`))\n        },\n        null,\n        {},\n      )\n      // with scheduler\n      watch(\n        () => {\n          const current = copyist.value\n          onWatcherCleanup(() => calls.push(`post ${current}`))\n        },\n        null,\n        { scheduler },\n      )\n    })\n\n    await nextTick()\n    expect(calls).toEqual([])\n\n    scope.run(() => source.value++)\n    expect(calls).toEqual(['sync 0'])\n    await nextTick()\n    expect(calls).toEqual(['sync 0', 'post 0'])\n    calls.length = 0\n\n    scope.run(() => source.value++)\n    expect(calls).toEqual(['sync 1'])\n    await nextTick()\n    expect(calls).toEqual(['sync 1', 'post 1'])\n    calls.length = 0\n\n    scope.stop()\n    expect(calls).toEqual(['sync 2', 'post 2'])\n  })\n\n  test('once option should be ignored by simple watch', async () => {\n    let dummy: any\n    const source = ref(0)\n    watch(\n      () => {\n        dummy = source.value\n      },\n      null,\n      { once: true },\n    )\n    expect(dummy).toBe(0)\n\n    source.value++\n    expect(dummy).toBe(1)\n  })\n\n  // #12033\n  test('recursive sync watcher on computed', () => {\n    const r = ref(0)\n    const c = computed(() => r.value)\n\n    watch(c, v => {\n      if (v > 1) {\n        r.value--\n      }\n    })\n\n    expect(r.value).toBe(0)\n    expect(c.value).toBe(0)\n\n    r.value = 10\n    expect(r.value).toBe(1)\n    expect(c.value).toBe(1)\n  })\n\n  // edge case where a nested endBatch() causes an effect to be batched in a\n  // nested batch loop with its .next mutated, causing the outer loop to end\n  // early\n  test('nested batch edge case', () => {\n    // useClamp from VueUse\n    const clamp = (n: number, min: number, max: number) =>\n      Math.min(max, Math.max(min, n))\n    function useClamp(src: Ref<number>, min: number, max: number) {\n      return computed({\n        get() {\n          return (src.value = clamp(src.value, min, max))\n        },\n        set(val) {\n          src.value = clamp(val, min, max)\n        },\n      })\n    }\n\n    const src = ref(1)\n    const clamped = useClamp(src, 1, 5)\n    watch(src, val => (clamped.value = val))\n\n    const spy = vi.fn()\n    watch(clamped, spy)\n\n    src.value = 2\n    expect(spy).toHaveBeenCalledTimes(1)\n    src.value = 10\n    expect(spy).toHaveBeenCalledTimes(2)\n  })\n\n  test('should ensure correct execution order in batch processing', () => {\n    const dummy: number[] = []\n    const n1 = ref(0)\n    const n2 = ref(0)\n    const sum = computed(() => n1.value + n2.value)\n    watch(n1, () => {\n      dummy.push(1)\n      n2.value++\n    })\n    watch(sum, () => dummy.push(2))\n    watch(n1, () => dummy.push(3))\n\n    n1.value++\n\n    expect(dummy).toEqual([1, 2, 3])\n  })\n\n  test('watch with immediate reset and sync flush', () => {\n    const value = ref(false)\n\n    watch(value, () => {\n      value.value = false\n    })\n\n    value.value = true\n    value.value = true\n    expect(value.value).toBe(false)\n  })\n})\n"
  },
  {
    "path": "packages/reactivity/index.js",
    "content": "'use strict'\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./dist/reactivity.cjs.prod.js')\n} else {\n  module.exports = require('./dist/reactivity.cjs.js')\n}\n"
  },
  {
    "path": "packages/reactivity/package.json",
    "content": "{\n  \"name\": \"@vue/reactivity\",\n  \"version\": \"3.5.30\",\n  \"description\": \"@vue/reactivity\",\n  \"main\": \"index.js\",\n  \"module\": \"dist/reactivity.esm-bundler.js\",\n  \"types\": \"dist/reactivity.d.ts\",\n  \"unpkg\": \"dist/reactivity.global.js\",\n  \"jsdelivr\": \"dist/reactivity.global.js\",\n  \"files\": [\n    \"index.js\",\n    \"dist\"\n  ],\n  \"exports\": {\n    \".\": {\n      \"types\": \"./dist/reactivity.d.ts\",\n      \"node\": {\n        \"production\": \"./dist/reactivity.cjs.prod.js\",\n        \"development\": \"./dist/reactivity.cjs.js\",\n        \"default\": \"./index.js\"\n      },\n      \"module\": \"./dist/reactivity.esm-bundler.js\",\n      \"import\": \"./dist/reactivity.esm-bundler.js\",\n      \"require\": \"./index.js\"\n    },\n    \"./*\": \"./*\"\n  },\n  \"sideEffects\": false,\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/vuejs/core.git\",\n    \"directory\": \"packages/reactivity\"\n  },\n  \"buildOptions\": {\n    \"name\": \"VueReactivity\",\n    \"formats\": [\n      \"esm-bundler\",\n      \"esm-browser\",\n      \"cjs\",\n      \"global\"\n    ]\n  },\n  \"keywords\": [\n    \"vue\"\n  ],\n  \"author\": \"Evan You\",\n  \"license\": \"MIT\",\n  \"bugs\": {\n    \"url\": \"https://github.com/vuejs/core/issues\"\n  },\n  \"homepage\": \"https://github.com/vuejs/core/tree/main/packages/reactivity#readme\",\n  \"dependencies\": {\n    \"@vue/shared\": \"workspace:*\"\n  }\n}\n"
  },
  {
    "path": "packages/reactivity/src/arrayInstrumentations.ts",
    "content": "import { TrackOpTypes } from './constants'\nimport { endBatch, pauseTracking, resetTracking, startBatch } from './effect'\nimport {\n  isProxy,\n  isReactive,\n  isReadonly,\n  isShallow,\n  toRaw,\n  toReactive,\n  toReadonly,\n} from './reactive'\nimport { ARRAY_ITERATE_KEY, track } from './dep'\nimport { isArray } from '@vue/shared'\n\n/**\n * Track array iteration and return:\n * - if input is reactive: a cloned raw array with reactive values\n * - if input is non-reactive or shallowReactive: the original raw array\n */\nexport function reactiveReadArray<T>(array: T[]): T[] {\n  const raw = toRaw(array)\n  if (raw === array) return raw\n  track(raw, TrackOpTypes.ITERATE, ARRAY_ITERATE_KEY)\n  return isShallow(array) ? raw : raw.map(toReactive)\n}\n\n/**\n * Track array iteration and return raw array\n */\nexport function shallowReadArray<T>(arr: T[]): T[] {\n  track((arr = toRaw(arr)), TrackOpTypes.ITERATE, ARRAY_ITERATE_KEY)\n  return arr\n}\n\nfunction toWrapped(target: unknown, item: unknown) {\n  if (isReadonly(target)) {\n    return isReactive(target) ? toReadonly(toReactive(item)) : toReadonly(item)\n  }\n  return toReactive(item)\n}\n\nexport const arrayInstrumentations: Record<string | symbol, Function> = <any>{\n  __proto__: null,\n\n  [Symbol.iterator]() {\n    return iterator(this, Symbol.iterator, item => toWrapped(this, item))\n  },\n\n  concat(...args: unknown[]) {\n    return reactiveReadArray(this).concat(\n      ...args.map(x => (isArray(x) ? reactiveReadArray(x) : x)),\n    )\n  },\n\n  entries() {\n    return iterator(this, 'entries', (value: [number, unknown]) => {\n      value[1] = toWrapped(this, value[1])\n      return value\n    })\n  },\n\n  every(\n    fn: (item: unknown, index: number, array: unknown[]) => unknown,\n    thisArg?: unknown,\n  ) {\n    return apply(this, 'every', fn, thisArg, undefined, arguments)\n  },\n\n  filter(\n    fn: (item: unknown, index: number, array: unknown[]) => unknown,\n    thisArg?: unknown,\n  ) {\n    return apply(\n      this,\n      'filter',\n      fn,\n      thisArg,\n      v => v.map((item: unknown) => toWrapped(this, item)),\n      arguments,\n    )\n  },\n\n  find(\n    fn: (item: unknown, index: number, array: unknown[]) => boolean,\n    thisArg?: unknown,\n  ) {\n    return apply(\n      this,\n      'find',\n      fn,\n      thisArg,\n      item => toWrapped(this, item),\n      arguments,\n    )\n  },\n\n  findIndex(\n    fn: (item: unknown, index: number, array: unknown[]) => boolean,\n    thisArg?: unknown,\n  ) {\n    return apply(this, 'findIndex', fn, thisArg, undefined, arguments)\n  },\n\n  findLast(\n    fn: (item: unknown, index: number, array: unknown[]) => boolean,\n    thisArg?: unknown,\n  ) {\n    return apply(\n      this,\n      'findLast',\n      fn,\n      thisArg,\n      item => toWrapped(this, item),\n      arguments,\n    )\n  },\n\n  findLastIndex(\n    fn: (item: unknown, index: number, array: unknown[]) => boolean,\n    thisArg?: unknown,\n  ) {\n    return apply(this, 'findLastIndex', fn, thisArg, undefined, arguments)\n  },\n\n  // flat, flatMap could benefit from ARRAY_ITERATE but are not straight-forward to implement\n\n  forEach(\n    fn: (item: unknown, index: number, array: unknown[]) => unknown,\n    thisArg?: unknown,\n  ) {\n    return apply(this, 'forEach', fn, thisArg, undefined, arguments)\n  },\n\n  includes(...args: unknown[]) {\n    return searchProxy(this, 'includes', args)\n  },\n\n  indexOf(...args: unknown[]) {\n    return searchProxy(this, 'indexOf', args)\n  },\n\n  join(separator?: string) {\n    return reactiveReadArray(this).join(separator)\n  },\n\n  // keys() iterator only reads `length`, no optimization required\n\n  lastIndexOf(...args: unknown[]) {\n    return searchProxy(this, 'lastIndexOf', args)\n  },\n\n  map(\n    fn: (item: unknown, index: number, array: unknown[]) => unknown,\n    thisArg?: unknown,\n  ) {\n    return apply(this, 'map', fn, thisArg, undefined, arguments)\n  },\n\n  pop() {\n    return noTracking(this, 'pop')\n  },\n\n  push(...args: unknown[]) {\n    return noTracking(this, 'push', args)\n  },\n\n  reduce(\n    fn: (\n      acc: unknown,\n      item: unknown,\n      index: number,\n      array: unknown[],\n    ) => unknown,\n    ...args: unknown[]\n  ) {\n    return reduce(this, 'reduce', fn, args)\n  },\n\n  reduceRight(\n    fn: (\n      acc: unknown,\n      item: unknown,\n      index: number,\n      array: unknown[],\n    ) => unknown,\n    ...args: unknown[]\n  ) {\n    return reduce(this, 'reduceRight', fn, args)\n  },\n\n  shift() {\n    return noTracking(this, 'shift')\n  },\n\n  // slice could use ARRAY_ITERATE but also seems to beg for range tracking\n\n  some(\n    fn: (item: unknown, index: number, array: unknown[]) => unknown,\n    thisArg?: unknown,\n  ) {\n    return apply(this, 'some', fn, thisArg, undefined, arguments)\n  },\n\n  splice(...args: unknown[]) {\n    return noTracking(this, 'splice', args)\n  },\n\n  toReversed() {\n    // @ts-expect-error user code may run in es2016+\n    return reactiveReadArray(this).toReversed()\n  },\n\n  toSorted(comparer?: (a: unknown, b: unknown) => number) {\n    // @ts-expect-error user code may run in es2016+\n    return reactiveReadArray(this).toSorted(comparer)\n  },\n\n  toSpliced(...args: unknown[]) {\n    // @ts-expect-error user code may run in es2016+\n    return (reactiveReadArray(this).toSpliced as any)(...args)\n  },\n\n  unshift(...args: unknown[]) {\n    return noTracking(this, 'unshift', args)\n  },\n\n  values() {\n    return iterator(this, 'values', item => toWrapped(this, item))\n  },\n}\n\n// instrument iterators to take ARRAY_ITERATE dependency\nfunction iterator(\n  self: unknown[],\n  method: keyof Array<unknown>,\n  wrapValue: (value: any) => unknown,\n) {\n  // note that taking ARRAY_ITERATE dependency here is not strictly equivalent\n  // to calling iterate on the proxied array.\n  // creating the iterator does not access any array property:\n  // it is only when .next() is called that length and indexes are accessed.\n  // pushed to the extreme, an iterator could be created in one effect scope,\n  // partially iterated in another, then iterated more in yet another.\n  // given that JS iterator can only be read once, this doesn't seem like\n  // a plausible use-case, so this tracking simplification seems ok.\n  const arr = shallowReadArray(self)\n  const iter = (arr[method] as any)() as IterableIterator<unknown> & {\n    _next: IterableIterator<unknown>['next']\n  }\n  if (arr !== self && !isShallow(self)) {\n    iter._next = iter.next\n    iter.next = () => {\n      const result = iter._next()\n      if (!result.done) {\n        result.value = wrapValue(result.value)\n      }\n      return result\n    }\n  }\n  return iter\n}\n\n// in the codebase we enforce es2016, but user code may run in environments\n// higher than that\ntype ArrayMethods = keyof Array<any> | 'findLast' | 'findLastIndex'\n\nconst arrayProto = Array.prototype\n// instrument functions that read (potentially) all items\n// to take ARRAY_ITERATE dependency\nfunction apply(\n  self: unknown[],\n  method: ArrayMethods,\n  fn: (item: unknown, index: number, array: unknown[]) => unknown,\n  thisArg?: unknown,\n  wrappedRetFn?: (result: any) => unknown,\n  args?: IArguments,\n) {\n  const arr = shallowReadArray(self)\n  const needsWrap = arr !== self && !isShallow(self)\n  // @ts-expect-error our code is limited to es2016 but user code is not\n  const methodFn = arr[method]\n\n  // #11759\n  // If the method being called is from a user-extended Array, the arguments will be unknown\n  // (unknown order and unknown parameter types). In this case, we skip the shallowReadArray\n  // handling and directly call apply with self.\n  if (methodFn !== arrayProto[method as any]) {\n    const result = methodFn.apply(self, args)\n    return needsWrap ? toReactive(result) : result\n  }\n\n  let wrappedFn = fn\n  if (arr !== self) {\n    if (needsWrap) {\n      wrappedFn = function (this: unknown, item, index) {\n        return fn.call(this, toWrapped(self, item), index, self)\n      }\n    } else if (fn.length > 2) {\n      wrappedFn = function (this: unknown, item, index) {\n        return fn.call(this, item, index, self)\n      }\n    }\n  }\n  const result = methodFn.call(arr, wrappedFn, thisArg)\n  return needsWrap && wrappedRetFn ? wrappedRetFn(result) : result\n}\n\n// instrument reduce and reduceRight to take ARRAY_ITERATE dependency\nfunction reduce(\n  self: unknown[],\n  method: keyof Array<any>,\n  fn: (acc: unknown, item: unknown, index: number, array: unknown[]) => unknown,\n  args: unknown[],\n) {\n  const arr = shallowReadArray(self)\n  const needsWrap = arr !== self && !isShallow(self)\n  let wrappedFn = fn\n  let wrapInitialAccumulator = false\n  if (arr !== self) {\n    if (needsWrap) {\n      wrapInitialAccumulator = args.length === 0\n      wrappedFn = function (this: unknown, acc, item, index) {\n        if (wrapInitialAccumulator) {\n          wrapInitialAccumulator = false\n          acc = toWrapped(self, acc)\n        }\n        return fn.call(this, acc, toWrapped(self, item), index, self)\n      }\n    } else if (fn.length > 3) {\n      wrappedFn = function (this: unknown, acc, item, index) {\n        return fn.call(this, acc, item, index, self)\n      }\n    }\n  }\n  const result = (arr[method] as any)(wrappedFn, ...args)\n  return wrapInitialAccumulator ? toWrapped(self, result) : result\n}\n\n// instrument identity-sensitive methods to account for reactive proxies\nfunction searchProxy(\n  self: unknown[],\n  method: keyof Array<any>,\n  args: unknown[],\n) {\n  const arr = toRaw(self) as any\n  track(arr, TrackOpTypes.ITERATE, ARRAY_ITERATE_KEY)\n  // we run the method using the original args first (which may be reactive)\n  const res = arr[method](...args)\n\n  // if that didn't work, run it again using raw values.\n  if ((res === -1 || res === false) && isProxy(args[0])) {\n    args[0] = toRaw(args[0])\n    return arr[method](...args)\n  }\n\n  return res\n}\n\n// instrument length-altering mutation methods to avoid length being tracked\n// which leads to infinite loops in some cases (#2137)\nfunction noTracking(\n  self: unknown[],\n  method: keyof Array<any>,\n  args: unknown[] = [],\n) {\n  pauseTracking()\n  startBatch()\n  const res = (toRaw(self) as any)[method].apply(self, args)\n  endBatch()\n  resetTracking()\n  return res\n}\n"
  },
  {
    "path": "packages/reactivity/src/baseHandlers.ts",
    "content": "import {\n  type Target,\n  isReadonly,\n  isShallow,\n  reactive,\n  reactiveMap,\n  readonly,\n  readonlyMap,\n  shallowReactiveMap,\n  shallowReadonlyMap,\n  toRaw,\n} from './reactive'\nimport { arrayInstrumentations } from './arrayInstrumentations'\nimport { ReactiveFlags, TrackOpTypes, TriggerOpTypes } from './constants'\nimport { ITERATE_KEY, track, trigger } from './dep'\nimport {\n  hasChanged,\n  hasOwn,\n  isArray,\n  isIntegerKey,\n  isObject,\n  isSymbol,\n  makeMap,\n} from '@vue/shared'\nimport { isRef } from './ref'\nimport { warn } from './warning'\n\nconst isNonTrackableKeys = /*@__PURE__*/ makeMap(`__proto__,__v_isRef,__isVue`)\n\nconst builtInSymbols = new Set(\n  /*@__PURE__*/\n  Object.getOwnPropertyNames(Symbol)\n    // ios10.x Object.getOwnPropertyNames(Symbol) can enumerate 'arguments' and 'caller'\n    // but accessing them on Symbol leads to TypeError because Symbol is a strict mode\n    // function\n    .filter(key => key !== 'arguments' && key !== 'caller')\n    .map(key => Symbol[key as keyof SymbolConstructor])\n    .filter(isSymbol),\n)\n\nfunction hasOwnProperty(this: object, key: unknown) {\n  // #10455 hasOwnProperty may be called with non-string values\n  if (!isSymbol(key)) key = String(key)\n  const obj = toRaw(this)\n  track(obj, TrackOpTypes.HAS, key)\n  return obj.hasOwnProperty(key as string)\n}\n\nclass BaseReactiveHandler implements ProxyHandler<Target> {\n  constructor(\n    protected readonly _isReadonly = false,\n    protected readonly _isShallow = false,\n  ) {}\n\n  get(target: Target, key: string | symbol, receiver: object): any {\n    if (key === ReactiveFlags.SKIP) return target[ReactiveFlags.SKIP]\n\n    const isReadonly = this._isReadonly,\n      isShallow = this._isShallow\n    if (key === ReactiveFlags.IS_REACTIVE) {\n      return !isReadonly\n    } else if (key === ReactiveFlags.IS_READONLY) {\n      return isReadonly\n    } else if (key === ReactiveFlags.IS_SHALLOW) {\n      return isShallow\n    } else if (key === ReactiveFlags.RAW) {\n      if (\n        receiver ===\n          (isReadonly\n            ? isShallow\n              ? shallowReadonlyMap\n              : readonlyMap\n            : isShallow\n              ? shallowReactiveMap\n              : reactiveMap\n          ).get(target) ||\n        // receiver is not the reactive proxy, but has the same prototype\n        // this means the receiver is a user proxy of the reactive proxy\n        Object.getPrototypeOf(target) === Object.getPrototypeOf(receiver)\n      ) {\n        return target\n      }\n      // early return undefined\n      return\n    }\n\n    const targetIsArray = isArray(target)\n\n    if (!isReadonly) {\n      let fn: Function | undefined\n      if (targetIsArray && (fn = arrayInstrumentations[key])) {\n        return fn\n      }\n      if (key === 'hasOwnProperty') {\n        return hasOwnProperty\n      }\n    }\n\n    const res = Reflect.get(\n      target,\n      key,\n      // if this is a proxy wrapping a ref, return methods using the raw ref\n      // as receiver so that we don't have to call `toRaw` on the ref in all\n      // its class methods\n      isRef(target) ? target : receiver,\n    )\n\n    if (isSymbol(key) ? builtInSymbols.has(key) : isNonTrackableKeys(key)) {\n      return res\n    }\n\n    if (!isReadonly) {\n      track(target, TrackOpTypes.GET, key)\n    }\n\n    if (isShallow) {\n      return res\n    }\n\n    if (isRef(res)) {\n      // ref unwrapping - skip unwrap for Array + integer key.\n      const value = targetIsArray && isIntegerKey(key) ? res : res.value\n      return isReadonly && isObject(value) ? readonly(value) : value\n    }\n\n    if (isObject(res)) {\n      // Convert returned value into a proxy as well. we do the isObject check\n      // here to avoid invalid value warning. Also need to lazy access readonly\n      // and reactive here to avoid circular dependency.\n      return isReadonly ? readonly(res) : reactive(res)\n    }\n\n    return res\n  }\n}\n\nclass MutableReactiveHandler extends BaseReactiveHandler {\n  constructor(isShallow = false) {\n    super(false, isShallow)\n  }\n\n  set(\n    target: Record<string | symbol, unknown>,\n    key: string | symbol,\n    value: unknown,\n    receiver: object,\n  ): boolean {\n    let oldValue = target[key]\n    const isArrayWithIntegerKey = isArray(target) && isIntegerKey(key)\n    if (!this._isShallow) {\n      const isOldValueReadonly = isReadonly(oldValue)\n      if (!isShallow(value) && !isReadonly(value)) {\n        oldValue = toRaw(oldValue)\n        value = toRaw(value)\n      }\n      if (!isArrayWithIntegerKey && isRef(oldValue) && !isRef(value)) {\n        if (isOldValueReadonly) {\n          if (__DEV__) {\n            warn(\n              `Set operation on key \"${String(key)}\" failed: target is readonly.`,\n              target[key],\n            )\n          }\n          return true\n        } else {\n          oldValue.value = value\n          return true\n        }\n      }\n    } else {\n      // in shallow mode, objects are set as-is regardless of reactive or not\n    }\n\n    const hadKey = isArrayWithIntegerKey\n      ? Number(key) < target.length\n      : hasOwn(target, key)\n    const result = Reflect.set(\n      target,\n      key,\n      value,\n      isRef(target) ? target : receiver,\n    )\n    // don't trigger if target is something up in the prototype chain of original\n    if (target === toRaw(receiver)) {\n      if (!hadKey) {\n        trigger(target, TriggerOpTypes.ADD, key, value)\n      } else if (hasChanged(value, oldValue)) {\n        trigger(target, TriggerOpTypes.SET, key, value, oldValue)\n      }\n    }\n    return result\n  }\n\n  deleteProperty(\n    target: Record<string | symbol, unknown>,\n    key: string | symbol,\n  ): boolean {\n    const hadKey = hasOwn(target, key)\n    const oldValue = target[key]\n    const result = Reflect.deleteProperty(target, key)\n    if (result && hadKey) {\n      trigger(target, TriggerOpTypes.DELETE, key, undefined, oldValue)\n    }\n    return result\n  }\n\n  has(target: Record<string | symbol, unknown>, key: string | symbol): boolean {\n    const result = Reflect.has(target, key)\n    if (!isSymbol(key) || !builtInSymbols.has(key)) {\n      track(target, TrackOpTypes.HAS, key)\n    }\n    return result\n  }\n\n  ownKeys(target: Record<string | symbol, unknown>): (string | symbol)[] {\n    track(\n      target,\n      TrackOpTypes.ITERATE,\n      isArray(target) ? 'length' : ITERATE_KEY,\n    )\n    return Reflect.ownKeys(target)\n  }\n}\n\nclass ReadonlyReactiveHandler extends BaseReactiveHandler {\n  constructor(isShallow = false) {\n    super(true, isShallow)\n  }\n\n  set(target: object, key: string | symbol) {\n    if (__DEV__) {\n      warn(\n        `Set operation on key \"${String(key)}\" failed: target is readonly.`,\n        target,\n      )\n    }\n    return true\n  }\n\n  deleteProperty(target: object, key: string | symbol) {\n    if (__DEV__) {\n      warn(\n        `Delete operation on key \"${String(key)}\" failed: target is readonly.`,\n        target,\n      )\n    }\n    return true\n  }\n}\n\nexport const mutableHandlers: ProxyHandler<object> =\n  /*@__PURE__*/ new MutableReactiveHandler()\n\nexport const readonlyHandlers: ProxyHandler<object> =\n  /*@__PURE__*/ new ReadonlyReactiveHandler()\n\nexport const shallowReactiveHandlers: MutableReactiveHandler =\n  /*@__PURE__*/ new MutableReactiveHandler(true)\n\n// Props handlers are special in the sense that it should not unwrap top-level\n// refs (in order to allow refs to be explicitly passed down), but should\n// retain the reactivity of the normal readonly object.\nexport const shallowReadonlyHandlers: ReadonlyReactiveHandler =\n  /*@__PURE__*/ new ReadonlyReactiveHandler(true)\n"
  },
  {
    "path": "packages/reactivity/src/collectionHandlers.ts",
    "content": "import {\n  type Target,\n  isReadonly,\n  isShallow,\n  toRaw,\n  toReactive,\n  toReadonly,\n} from './reactive'\nimport { ITERATE_KEY, MAP_KEY_ITERATE_KEY, track, trigger } from './dep'\nimport { ReactiveFlags, TrackOpTypes, TriggerOpTypes } from './constants'\nimport {\n  capitalize,\n  extend,\n  hasChanged,\n  hasOwn,\n  isMap,\n  toRawType,\n} from '@vue/shared'\nimport { warn } from './warning'\n\ntype CollectionTypes = IterableCollections | WeakCollections\n\ntype IterableCollections = (Map<any, any> | Set<any>) & Target\ntype WeakCollections = (WeakMap<any, any> | WeakSet<any>) & Target\ntype MapTypes = (Map<any, any> | WeakMap<any, any>) & Target\ntype SetTypes = (Set<any> | WeakSet<any>) & Target\n\nconst toShallow = <T extends unknown>(value: T): T => value\n\nconst getProto = <T extends CollectionTypes>(v: T): any =>\n  Reflect.getPrototypeOf(v)\n\nfunction createIterableMethod(\n  method: string | symbol,\n  isReadonly: boolean,\n  isShallow: boolean,\n) {\n  return function (\n    this: IterableCollections,\n    ...args: unknown[]\n  ): Iterable<unknown> & Iterator<unknown> {\n    const target = this[ReactiveFlags.RAW]\n    const rawTarget = toRaw(target)\n    const targetIsMap = isMap(rawTarget)\n    const isPair =\n      method === 'entries' || (method === Symbol.iterator && targetIsMap)\n    const isKeyOnly = method === 'keys' && targetIsMap\n    const innerIterator = target[method](...args)\n    const wrap = isShallow ? toShallow : isReadonly ? toReadonly : toReactive\n    !isReadonly &&\n      track(\n        rawTarget,\n        TrackOpTypes.ITERATE,\n        isKeyOnly ? MAP_KEY_ITERATE_KEY : ITERATE_KEY,\n      )\n    // return a wrapped iterator which returns observed versions of the\n    // values emitted from the real iterator\n    return extend(\n      // inheriting all iterator properties\n      Object.create(innerIterator),\n      {\n        // iterator protocol\n        next() {\n          const { value, done } = innerIterator.next()\n          return done\n            ? { value, done }\n            : {\n                value: isPair ? [wrap(value[0]), wrap(value[1])] : wrap(value),\n                done,\n              }\n        },\n      },\n    )\n  }\n}\n\nfunction createReadonlyMethod(type: TriggerOpTypes): Function {\n  return function (this: CollectionTypes, ...args: unknown[]) {\n    if (__DEV__) {\n      const key = args[0] ? `on key \"${args[0]}\" ` : ``\n      warn(\n        `${capitalize(type)} operation ${key}failed: target is readonly.`,\n        toRaw(this),\n      )\n    }\n    return type === TriggerOpTypes.DELETE\n      ? false\n      : type === TriggerOpTypes.CLEAR\n        ? undefined\n        : this\n  }\n}\n\ntype Instrumentations = Record<string | symbol, Function | number>\n\nfunction createInstrumentations(\n  readonly: boolean,\n  shallow: boolean,\n): Instrumentations {\n  const instrumentations: Instrumentations = {\n    get(this: MapTypes, key: unknown) {\n      // #1772: readonly(reactive(Map)) should return readonly + reactive version\n      // of the value\n      const target = this[ReactiveFlags.RAW]\n      const rawTarget = toRaw(target)\n      const rawKey = toRaw(key)\n      if (!readonly) {\n        if (hasChanged(key, rawKey)) {\n          track(rawTarget, TrackOpTypes.GET, key)\n        }\n        track(rawTarget, TrackOpTypes.GET, rawKey)\n      }\n      const { has } = getProto(rawTarget)\n      const wrap = shallow ? toShallow : readonly ? toReadonly : toReactive\n      if (has.call(rawTarget, key)) {\n        return wrap(target.get(key))\n      } else if (has.call(rawTarget, rawKey)) {\n        return wrap(target.get(rawKey))\n      } else if (target !== rawTarget) {\n        // #3602 readonly(reactive(Map))\n        // ensure that the nested reactive `Map` can do tracking for itself\n        target.get(key)\n      }\n    },\n    get size() {\n      const target = (this as unknown as IterableCollections)[ReactiveFlags.RAW]\n      !readonly && track(toRaw(target), TrackOpTypes.ITERATE, ITERATE_KEY)\n      return target.size\n    },\n    has(this: CollectionTypes, key: unknown): boolean {\n      const target = this[ReactiveFlags.RAW]\n      const rawTarget = toRaw(target)\n      const rawKey = toRaw(key)\n      if (!readonly) {\n        if (hasChanged(key, rawKey)) {\n          track(rawTarget, TrackOpTypes.HAS, key)\n        }\n        track(rawTarget, TrackOpTypes.HAS, rawKey)\n      }\n      return key === rawKey\n        ? target.has(key)\n        : target.has(key) || target.has(rawKey)\n    },\n    forEach(this: IterableCollections, callback: Function, thisArg?: unknown) {\n      const observed = this\n      const target = observed[ReactiveFlags.RAW]\n      const rawTarget = toRaw(target)\n      const wrap = shallow ? toShallow : readonly ? toReadonly : toReactive\n      !readonly && track(rawTarget, TrackOpTypes.ITERATE, ITERATE_KEY)\n      return target.forEach((value: unknown, key: unknown) => {\n        // important: make sure the callback is\n        // 1. invoked with the reactive map as `this` and 3rd arg\n        // 2. the value received should be a corresponding reactive/readonly.\n        return callback.call(thisArg, wrap(value), wrap(key), observed)\n      })\n    },\n  }\n\n  extend(\n    instrumentations,\n    readonly\n      ? {\n          add: createReadonlyMethod(TriggerOpTypes.ADD),\n          set: createReadonlyMethod(TriggerOpTypes.SET),\n          delete: createReadonlyMethod(TriggerOpTypes.DELETE),\n          clear: createReadonlyMethod(TriggerOpTypes.CLEAR),\n        }\n      : {\n          add(this: SetTypes, value: unknown) {\n            const target = toRaw(this)\n            const proto = getProto(target)\n            const rawValue = toRaw(value)\n            const valueToAdd =\n              !shallow && !isShallow(value) && !isReadonly(value)\n                ? rawValue\n                : value\n            const hadKey =\n              proto.has.call(target, valueToAdd) ||\n              (hasChanged(value, valueToAdd) &&\n                proto.has.call(target, value)) ||\n              (hasChanged(rawValue, valueToAdd) &&\n                proto.has.call(target, rawValue))\n            if (!hadKey) {\n              target.add(valueToAdd)\n              trigger(target, TriggerOpTypes.ADD, valueToAdd, valueToAdd)\n            }\n            return this\n          },\n          set(this: MapTypes, key: unknown, value: unknown) {\n            if (!shallow && !isShallow(value) && !isReadonly(value)) {\n              value = toRaw(value)\n            }\n            const target = toRaw(this)\n            const { has, get } = getProto(target)\n\n            let hadKey = has.call(target, key)\n            if (!hadKey) {\n              key = toRaw(key)\n              hadKey = has.call(target, key)\n            } else if (__DEV__) {\n              checkIdentityKeys(target, has, key)\n            }\n\n            const oldValue = get.call(target, key)\n            target.set(key, value)\n            if (!hadKey) {\n              trigger(target, TriggerOpTypes.ADD, key, value)\n            } else if (hasChanged(value, oldValue)) {\n              trigger(target, TriggerOpTypes.SET, key, value, oldValue)\n            }\n            return this\n          },\n          delete(this: CollectionTypes, key: unknown) {\n            const target = toRaw(this)\n            const { has, get } = getProto(target)\n            let hadKey = has.call(target, key)\n            if (!hadKey) {\n              key = toRaw(key)\n              hadKey = has.call(target, key)\n            } else if (__DEV__) {\n              checkIdentityKeys(target, has, key)\n            }\n\n            const oldValue = get ? get.call(target, key) : undefined\n            // forward the operation before queueing reactions\n            const result = target.delete(key)\n            if (hadKey) {\n              trigger(target, TriggerOpTypes.DELETE, key, undefined, oldValue)\n            }\n            return result\n          },\n          clear(this: IterableCollections) {\n            const target = toRaw(this)\n            const hadItems = target.size !== 0\n            const oldTarget = __DEV__\n              ? isMap(target)\n                ? new Map(target)\n                : new Set(target)\n              : undefined\n            // forward the operation before queueing reactions\n            const result = target.clear()\n            if (hadItems) {\n              trigger(\n                target,\n                TriggerOpTypes.CLEAR,\n                undefined,\n                undefined,\n                oldTarget,\n              )\n            }\n            return result\n          },\n        },\n  )\n\n  const iteratorMethods = [\n    'keys',\n    'values',\n    'entries',\n    Symbol.iterator,\n  ] as const\n\n  iteratorMethods.forEach(method => {\n    instrumentations[method] = createIterableMethod(method, readonly, shallow)\n  })\n\n  return instrumentations\n}\n\nfunction createInstrumentationGetter(isReadonly: boolean, shallow: boolean) {\n  const instrumentations = createInstrumentations(isReadonly, shallow)\n\n  return (\n    target: CollectionTypes,\n    key: string | symbol,\n    receiver: CollectionTypes,\n  ) => {\n    if (key === ReactiveFlags.IS_REACTIVE) {\n      return !isReadonly\n    } else if (key === ReactiveFlags.IS_READONLY) {\n      return isReadonly\n    } else if (key === ReactiveFlags.RAW) {\n      return target\n    }\n\n    return Reflect.get(\n      hasOwn(instrumentations, key) && key in target\n        ? instrumentations\n        : target,\n      key,\n      receiver,\n    )\n  }\n}\n\nexport const mutableCollectionHandlers: ProxyHandler<CollectionTypes> = {\n  get: /*@__PURE__*/ createInstrumentationGetter(false, false),\n}\n\nexport const shallowCollectionHandlers: ProxyHandler<CollectionTypes> = {\n  get: /*@__PURE__*/ createInstrumentationGetter(false, true),\n}\n\nexport const readonlyCollectionHandlers: ProxyHandler<CollectionTypes> = {\n  get: /*@__PURE__*/ createInstrumentationGetter(true, false),\n}\n\nexport const shallowReadonlyCollectionHandlers: ProxyHandler<CollectionTypes> =\n  {\n    get: /*@__PURE__*/ createInstrumentationGetter(true, true),\n  }\n\nfunction checkIdentityKeys(\n  target: CollectionTypes,\n  has: (key: unknown) => boolean,\n  key: unknown,\n) {\n  const rawKey = toRaw(key)\n  if (rawKey !== key && has.call(target, rawKey)) {\n    const type = toRawType(target)\n    warn(\n      `Reactive ${type} contains both the raw and reactive ` +\n        `versions of the same object${type === `Map` ? ` as keys` : ``}, ` +\n        `which can lead to inconsistencies. ` +\n        `Avoid differentiating between the raw and reactive versions ` +\n        `of an object and only use the reactive version if possible.`,\n    )\n  }\n}\n"
  },
  {
    "path": "packages/reactivity/src/computed.ts",
    "content": "import { isFunction } from '@vue/shared'\nimport {\n  type DebuggerEvent,\n  type DebuggerOptions,\n  EffectFlags,\n  type Subscriber,\n  activeSub,\n  batch,\n  refreshComputed,\n} from './effect'\nimport type { Ref } from './ref'\nimport { warn } from './warning'\nimport { Dep, type Link, globalVersion } from './dep'\nimport { ReactiveFlags, TrackOpTypes } from './constants'\n\ndeclare const ComputedRefSymbol: unique symbol\ndeclare const WritableComputedRefSymbol: unique symbol\n\ninterface BaseComputedRef<T, S = T> extends Ref<T, S> {\n  [ComputedRefSymbol]: true\n  /**\n   * @deprecated computed no longer uses effect\n   */\n  effect: ComputedRefImpl\n}\n\nexport interface ComputedRef<T = any> extends BaseComputedRef<T> {\n  readonly value: T\n}\n\nexport interface WritableComputedRef<T, S = T> extends BaseComputedRef<T, S> {\n  [WritableComputedRefSymbol]: true\n}\n\nexport type ComputedGetter<T> = (oldValue?: T) => T\nexport type ComputedSetter<T> = (newValue: T) => void\n\nexport interface WritableComputedOptions<T, S = T> {\n  get: ComputedGetter<T>\n  set: ComputedSetter<S>\n}\n\n/**\n * @private exported by @vue/reactivity for Vue core use, but not exported from\n * the main vue package\n */\nexport class ComputedRefImpl<T = any> implements Subscriber {\n  /**\n   * @internal\n   */\n  _value: any = undefined\n  /**\n   * @internal\n   */\n  readonly dep: Dep = new Dep(this)\n  /**\n   * @internal\n   */\n  readonly __v_isRef = true\n  // TODO isolatedDeclarations ReactiveFlags.IS_REF\n  /**\n   * @internal\n   */\n  readonly __v_isReadonly: boolean\n  // TODO isolatedDeclarations ReactiveFlags.IS_READONLY\n  // A computed is also a subscriber that tracks other deps\n  /**\n   * @internal\n   */\n  deps?: Link = undefined\n  /**\n   * @internal\n   */\n  depsTail?: Link = undefined\n  /**\n   * @internal\n   */\n  flags: EffectFlags = EffectFlags.DIRTY\n  /**\n   * @internal\n   */\n  globalVersion: number = globalVersion - 1\n  /**\n   * @internal\n   */\n  isSSR: boolean\n  /**\n   * @internal\n   */\n  next?: Subscriber = undefined\n\n  // for backwards compat\n  effect: this = this\n  // dev only\n  onTrack?: (event: DebuggerEvent) => void\n  // dev only\n  onTrigger?: (event: DebuggerEvent) => void\n\n  /**\n   * Dev only\n   * @internal\n   */\n  _warnRecursive?: boolean\n\n  constructor(\n    public fn: ComputedGetter<T>,\n    private readonly setter: ComputedSetter<T> | undefined,\n    isSSR: boolean,\n  ) {\n    this[ReactiveFlags.IS_READONLY] = !setter\n    this.isSSR = isSSR\n  }\n\n  /**\n   * @internal\n   */\n  notify(): true | void {\n    this.flags |= EffectFlags.DIRTY\n    if (\n      !(this.flags & EffectFlags.NOTIFIED) &&\n      // avoid infinite self recursion\n      activeSub !== this\n    ) {\n      batch(this, true)\n      return true\n    } else if (__DEV__) {\n      // TODO warn\n    }\n  }\n\n  get value(): T {\n    const link = __DEV__\n      ? this.dep.track({\n          target: this,\n          type: TrackOpTypes.GET,\n          key: 'value',\n        })\n      : this.dep.track()\n    refreshComputed(this)\n    // sync version after evaluation\n    if (link) {\n      link.version = this.dep.version\n    }\n    return this._value\n  }\n\n  set value(newValue) {\n    if (this.setter) {\n      this.setter(newValue)\n    } else if (__DEV__) {\n      warn('Write operation failed: computed value is readonly')\n    }\n  }\n}\n\n/**\n * Takes a getter function and returns a readonly reactive ref object for the\n * returned value from the getter. It can also take an object with get and set\n * functions to create a writable ref object.\n *\n * @example\n * ```js\n * // Creating a readonly computed ref:\n * const count = ref(1)\n * const plusOne = computed(() => count.value + 1)\n *\n * console.log(plusOne.value) // 2\n * plusOne.value++ // error\n * ```\n *\n * ```js\n * // Creating a writable computed ref:\n * const count = ref(1)\n * const plusOne = computed({\n *   get: () => count.value + 1,\n *   set: (val) => {\n *     count.value = val - 1\n *   }\n * })\n *\n * plusOne.value = 1\n * console.log(count.value) // 0\n * ```\n *\n * @param getter - Function that produces the next value.\n * @param debugOptions - For debugging. See {@link https://vuejs.org/guide/extras/reactivity-in-depth.html#computed-debugging}.\n * @see {@link https://vuejs.org/api/reactivity-core.html#computed}\n */\nexport function computed<T>(\n  getter: ComputedGetter<T>,\n  debugOptions?: DebuggerOptions,\n): ComputedRef<T>\nexport function computed<T, S = T>(\n  options: WritableComputedOptions<T, S>,\n  debugOptions?: DebuggerOptions,\n): WritableComputedRef<T, S>\n/*@__NO_SIDE_EFFECTS__*/\nexport function computed<T>(\n  getterOrOptions: ComputedGetter<T> | WritableComputedOptions<T>,\n  debugOptions?: DebuggerOptions,\n  isSSR = false,\n) {\n  let getter: ComputedGetter<T>\n  let setter: ComputedSetter<T> | undefined\n\n  if (isFunction(getterOrOptions)) {\n    getter = getterOrOptions\n  } else {\n    getter = getterOrOptions.get\n    setter = getterOrOptions.set\n  }\n\n  const cRef = new ComputedRefImpl(getter, setter, isSSR)\n\n  if (__DEV__ && debugOptions && !isSSR) {\n    cRef.onTrack = debugOptions.onTrack\n    cRef.onTrigger = debugOptions.onTrigger\n  }\n\n  return cRef as any\n}\n"
  },
  {
    "path": "packages/reactivity/src/constants.ts",
    "content": "// using literal strings instead of numbers so that it's easier to inspect\n// debugger events\n\nexport enum TrackOpTypes {\n  GET = 'get',\n  HAS = 'has',\n  ITERATE = 'iterate',\n}\n\nexport enum TriggerOpTypes {\n  SET = 'set',\n  ADD = 'add',\n  DELETE = 'delete',\n  CLEAR = 'clear',\n}\n\nexport enum ReactiveFlags {\n  SKIP = '__v_skip',\n  IS_REACTIVE = '__v_isReactive',\n  IS_READONLY = '__v_isReadonly',\n  IS_SHALLOW = '__v_isShallow',\n  RAW = '__v_raw',\n  IS_REF = '__v_isRef',\n}\n"
  },
  {
    "path": "packages/reactivity/src/dep.ts",
    "content": "import { extend, isArray, isIntegerKey, isMap, isSymbol } from '@vue/shared'\nimport type { ComputedRefImpl } from './computed'\nimport { type TrackOpTypes, TriggerOpTypes } from './constants'\nimport {\n  type DebuggerEventExtraInfo,\n  EffectFlags,\n  type Subscriber,\n  activeSub,\n  endBatch,\n  shouldTrack,\n  startBatch,\n} from './effect'\n\n/**\n * Incremented every time a reactive change happens\n * This is used to give computed a fast path to avoid re-compute when nothing\n * has changed.\n */\nexport let globalVersion = 0\n\n/**\n * Represents a link between a source (Dep) and a subscriber (Effect or Computed).\n * Deps and subs have a many-to-many relationship - each link between a\n * dep and a sub is represented by a Link instance.\n *\n * A Link is also a node in two doubly-linked lists - one for the associated\n * sub to track all its deps, and one for the associated dep to track all its\n * subs.\n *\n * @internal\n */\nexport class Link {\n  /**\n   * - Before each effect run, all previous dep links' version are reset to -1\n   * - During the run, a link's version is synced with the source dep on access\n   * - After the run, links with version -1 (that were never used) are cleaned\n   *   up\n   */\n  version: number\n\n  /**\n   * Pointers for doubly-linked lists\n   */\n  nextDep?: Link\n  prevDep?: Link\n  nextSub?: Link\n  prevSub?: Link\n  prevActiveLink?: Link\n\n  constructor(\n    public sub: Subscriber,\n    public dep: Dep,\n  ) {\n    this.version = dep.version\n    this.nextDep =\n      this.prevDep =\n      this.nextSub =\n      this.prevSub =\n      this.prevActiveLink =\n        undefined\n  }\n}\n\n/**\n * @internal\n */\nexport class Dep {\n  version = 0\n  /**\n   * Link between this dep and the current active effect\n   */\n  activeLink?: Link = undefined\n\n  /**\n   * Doubly linked list representing the subscribing effects (tail)\n   */\n  subs?: Link = undefined\n\n  /**\n   * Doubly linked list representing the subscribing effects (head)\n   * DEV only, for invoking onTrigger hooks in correct order\n   */\n  subsHead?: Link\n\n  /**\n   * For object property deps cleanup\n   */\n  map?: KeyToDepMap = undefined\n  key?: unknown = undefined\n\n  /**\n   * Subscriber counter\n   */\n  sc: number = 0\n\n  /**\n   * @internal\n   */\n  readonly __v_skip = true\n  // TODO isolatedDeclarations ReactiveFlags.SKIP\n\n  constructor(public computed?: ComputedRefImpl | undefined) {\n    if (__DEV__) {\n      this.subsHead = undefined\n    }\n  }\n\n  track(debugInfo?: DebuggerEventExtraInfo): Link | undefined {\n    if (!activeSub || !shouldTrack || activeSub === this.computed) {\n      return\n    }\n\n    let link = this.activeLink\n    if (link === undefined || link.sub !== activeSub) {\n      link = this.activeLink = new Link(activeSub, this)\n\n      // add the link to the activeEffect as a dep (as tail)\n      if (!activeSub.deps) {\n        activeSub.deps = activeSub.depsTail = link\n      } else {\n        link.prevDep = activeSub.depsTail\n        activeSub.depsTail!.nextDep = link\n        activeSub.depsTail = link\n      }\n\n      addSub(link)\n    } else if (link.version === -1) {\n      // reused from last run - already a sub, just sync version\n      link.version = this.version\n\n      // If this dep has a next, it means it's not at the tail - move it to the\n      // tail. This ensures the effect's dep list is in the order they are\n      // accessed during evaluation.\n      if (link.nextDep) {\n        const next = link.nextDep\n        next.prevDep = link.prevDep\n        if (link.prevDep) {\n          link.prevDep.nextDep = next\n        }\n\n        link.prevDep = activeSub.depsTail\n        link.nextDep = undefined\n        activeSub.depsTail!.nextDep = link\n        activeSub.depsTail = link\n\n        // this was the head - point to the new head\n        if (activeSub.deps === link) {\n          activeSub.deps = next\n        }\n      }\n    }\n\n    if (__DEV__ && activeSub.onTrack) {\n      activeSub.onTrack(\n        extend(\n          {\n            effect: activeSub,\n          },\n          debugInfo,\n        ),\n      )\n    }\n\n    return link\n  }\n\n  trigger(debugInfo?: DebuggerEventExtraInfo): void {\n    this.version++\n    globalVersion++\n    this.notify(debugInfo)\n  }\n\n  notify(debugInfo?: DebuggerEventExtraInfo): void {\n    startBatch()\n    try {\n      if (__DEV__) {\n        // subs are notified and batched in reverse-order and then invoked in\n        // original order at the end of the batch, but onTrigger hooks should\n        // be invoked in original order here.\n        for (let head = this.subsHead; head; head = head.nextSub) {\n          if (head.sub.onTrigger && !(head.sub.flags & EffectFlags.NOTIFIED)) {\n            head.sub.onTrigger(\n              extend(\n                {\n                  effect: head.sub,\n                },\n                debugInfo,\n              ),\n            )\n          }\n        }\n      }\n      for (let link = this.subs; link; link = link.prevSub) {\n        if (link.sub.notify()) {\n          // if notify() returns `true`, this is a computed. Also call notify\n          // on its dep - it's called here instead of inside computed's notify\n          // in order to reduce call stack depth.\n          ;(link.sub as ComputedRefImpl).dep.notify()\n        }\n      }\n    } finally {\n      endBatch()\n    }\n  }\n}\n\nfunction addSub(link: Link) {\n  link.dep.sc++\n  if (link.sub.flags & EffectFlags.TRACKING) {\n    const computed = link.dep.computed\n    // computed getting its first subscriber\n    // enable tracking + lazily subscribe to all its deps\n    if (computed && !link.dep.subs) {\n      computed.flags |= EffectFlags.TRACKING | EffectFlags.DIRTY\n      for (let l = computed.deps; l; l = l.nextDep) {\n        addSub(l)\n      }\n    }\n\n    const currentTail = link.dep.subs\n    if (currentTail !== link) {\n      link.prevSub = currentTail\n      if (currentTail) currentTail.nextSub = link\n    }\n\n    if (__DEV__ && link.dep.subsHead === undefined) {\n      link.dep.subsHead = link\n    }\n\n    link.dep.subs = link\n  }\n}\n\n// The main WeakMap that stores {target -> key -> dep} connections.\n// Conceptually, it's easier to think of a dependency as a Dep class\n// which maintains a Set of subscribers, but we simply store them as\n// raw Maps to reduce memory overhead.\ntype KeyToDepMap = Map<any, Dep>\n\nexport const targetMap: WeakMap<object, KeyToDepMap> = new WeakMap()\n\nexport const ITERATE_KEY: unique symbol = Symbol(\n  __DEV__ ? 'Object iterate' : '',\n)\nexport const MAP_KEY_ITERATE_KEY: unique symbol = Symbol(\n  __DEV__ ? 'Map keys iterate' : '',\n)\nexport const ARRAY_ITERATE_KEY: unique symbol = Symbol(\n  __DEV__ ? 'Array iterate' : '',\n)\n\n/**\n * Tracks access to a reactive property.\n *\n * This will check which effect is running at the moment and record it as dep\n * which records all effects that depend on the reactive property.\n *\n * @param target - Object holding the reactive property.\n * @param type - Defines the type of access to the reactive property.\n * @param key - Identifier of the reactive property to track.\n */\nexport function track(target: object, type: TrackOpTypes, key: unknown): void {\n  if (shouldTrack && activeSub) {\n    let depsMap = targetMap.get(target)\n    if (!depsMap) {\n      targetMap.set(target, (depsMap = new Map()))\n    }\n    let dep = depsMap.get(key)\n    if (!dep) {\n      depsMap.set(key, (dep = new Dep()))\n      dep.map = depsMap\n      dep.key = key\n    }\n    if (__DEV__) {\n      dep.track({\n        target,\n        type,\n        key,\n      })\n    } else {\n      dep.track()\n    }\n  }\n}\n\n/**\n * Finds all deps associated with the target (or a specific property) and\n * triggers the effects stored within.\n *\n * @param target - The reactive object.\n * @param type - Defines the type of the operation that needs to trigger effects.\n * @param key - Can be used to target a specific reactive property in the target object.\n */\nexport function trigger(\n  target: object,\n  type: TriggerOpTypes,\n  key?: unknown,\n  newValue?: unknown,\n  oldValue?: unknown,\n  oldTarget?: Map<unknown, unknown> | Set<unknown>,\n): void {\n  const depsMap = targetMap.get(target)\n  if (!depsMap) {\n    // never been tracked\n    globalVersion++\n    return\n  }\n\n  const run = (dep: Dep | undefined) => {\n    if (dep) {\n      if (__DEV__) {\n        dep.trigger({\n          target,\n          type,\n          key,\n          newValue,\n          oldValue,\n          oldTarget,\n        })\n      } else {\n        dep.trigger()\n      }\n    }\n  }\n\n  startBatch()\n\n  if (type === TriggerOpTypes.CLEAR) {\n    // collection being cleared\n    // trigger all effects for target\n    depsMap.forEach(run)\n  } else {\n    const targetIsArray = isArray(target)\n    const isArrayIndex = targetIsArray && isIntegerKey(key)\n\n    if (targetIsArray && key === 'length') {\n      const newLength = Number(newValue)\n      depsMap.forEach((dep, key) => {\n        if (\n          key === 'length' ||\n          key === ARRAY_ITERATE_KEY ||\n          (!isSymbol(key) && key >= newLength)\n        ) {\n          run(dep)\n        }\n      })\n    } else {\n      // schedule runs for SET | ADD | DELETE\n      if (key !== void 0 || depsMap.has(void 0)) {\n        run(depsMap.get(key))\n      }\n\n      // schedule ARRAY_ITERATE for any numeric key change (length is handled above)\n      if (isArrayIndex) {\n        run(depsMap.get(ARRAY_ITERATE_KEY))\n      }\n\n      // also run for iteration key on ADD | DELETE | Map.SET\n      switch (type) {\n        case TriggerOpTypes.ADD:\n          if (!targetIsArray) {\n            run(depsMap.get(ITERATE_KEY))\n            if (isMap(target)) {\n              run(depsMap.get(MAP_KEY_ITERATE_KEY))\n            }\n          } else if (isArrayIndex) {\n            // new index added to array -> length changes\n            run(depsMap.get('length'))\n          }\n          break\n        case TriggerOpTypes.DELETE:\n          if (!targetIsArray) {\n            run(depsMap.get(ITERATE_KEY))\n            if (isMap(target)) {\n              run(depsMap.get(MAP_KEY_ITERATE_KEY))\n            }\n          }\n          break\n        case TriggerOpTypes.SET:\n          if (isMap(target)) {\n            run(depsMap.get(ITERATE_KEY))\n          }\n          break\n      }\n    }\n  }\n\n  endBatch()\n}\n\nexport function getDepFromReactive(\n  object: any,\n  key: string | number | symbol,\n): Dep | undefined {\n  const depMap = targetMap.get(object)\n  return depMap && depMap.get(key)\n}\n"
  },
  {
    "path": "packages/reactivity/src/effect.ts",
    "content": "import { extend, hasChanged } from '@vue/shared'\nimport type { ComputedRefImpl } from './computed'\nimport type { TrackOpTypes, TriggerOpTypes } from './constants'\nimport { type Link, globalVersion } from './dep'\nimport { activeEffectScope } from './effectScope'\nimport { warn } from './warning'\n\nexport type EffectScheduler = (...args: any[]) => any\n\nexport type DebuggerEvent = {\n  effect: Subscriber\n} & DebuggerEventExtraInfo\n\nexport type DebuggerEventExtraInfo = {\n  target: object\n  type: TrackOpTypes | TriggerOpTypes\n  key: any\n  newValue?: any\n  oldValue?: any\n  oldTarget?: Map<any, any> | Set<any>\n}\n\nexport interface DebuggerOptions {\n  onTrack?: (event: DebuggerEvent) => void\n  onTrigger?: (event: DebuggerEvent) => void\n}\n\nexport interface ReactiveEffectOptions extends DebuggerOptions {\n  scheduler?: EffectScheduler\n  allowRecurse?: boolean\n  onStop?: () => void\n}\n\nexport interface ReactiveEffectRunner<T = any> {\n  (): T\n  effect: ReactiveEffect\n}\n\nexport let activeSub: Subscriber | undefined\n\nexport enum EffectFlags {\n  /**\n   * ReactiveEffect only\n   */\n  ACTIVE = 1 << 0,\n  RUNNING = 1 << 1,\n  TRACKING = 1 << 2,\n  NOTIFIED = 1 << 3,\n  DIRTY = 1 << 4,\n  ALLOW_RECURSE = 1 << 5,\n  PAUSED = 1 << 6,\n  EVALUATED = 1 << 7,\n}\n\n/**\n * Subscriber is a type that tracks (or subscribes to) a list of deps.\n */\nexport interface Subscriber extends DebuggerOptions {\n  /**\n   * Head of the doubly linked list representing the deps\n   * @internal\n   */\n  deps?: Link\n  /**\n   * Tail of the same list\n   * @internal\n   */\n  depsTail?: Link\n  /**\n   * @internal\n   */\n  flags: EffectFlags\n  /**\n   * @internal\n   */\n  next?: Subscriber\n  /**\n   * returning `true` indicates it's a computed that needs to call notify\n   * on its dep too\n   * @internal\n   */\n  notify(): true | void\n}\n\nconst pausedQueueEffects = new WeakSet<ReactiveEffect>()\n\nexport class ReactiveEffect<T = any>\n  implements Subscriber, ReactiveEffectOptions\n{\n  /**\n   * @internal\n   */\n  deps?: Link = undefined\n  /**\n   * @internal\n   */\n  depsTail?: Link = undefined\n  /**\n   * @internal\n   */\n  flags: EffectFlags = EffectFlags.ACTIVE | EffectFlags.TRACKING\n  /**\n   * @internal\n   */\n  next?: Subscriber = undefined\n  /**\n   * @internal\n   */\n  cleanup?: () => void = undefined\n\n  scheduler?: EffectScheduler = undefined\n  onStop?: () => void\n  onTrack?: (event: DebuggerEvent) => void\n  onTrigger?: (event: DebuggerEvent) => void\n\n  constructor(public fn: () => T) {\n    if (activeEffectScope && activeEffectScope.active) {\n      activeEffectScope.effects.push(this)\n    }\n  }\n\n  pause(): void {\n    this.flags |= EffectFlags.PAUSED\n  }\n\n  resume(): void {\n    if (this.flags & EffectFlags.PAUSED) {\n      this.flags &= ~EffectFlags.PAUSED\n      if (pausedQueueEffects.has(this)) {\n        pausedQueueEffects.delete(this)\n        this.trigger()\n      }\n    }\n  }\n\n  /**\n   * @internal\n   */\n  notify(): void {\n    if (\n      this.flags & EffectFlags.RUNNING &&\n      !(this.flags & EffectFlags.ALLOW_RECURSE)\n    ) {\n      return\n    }\n    if (!(this.flags & EffectFlags.NOTIFIED)) {\n      batch(this)\n    }\n  }\n\n  run(): T {\n    // TODO cleanupEffect\n\n    if (!(this.flags & EffectFlags.ACTIVE)) {\n      // stopped during cleanup\n      return this.fn()\n    }\n\n    this.flags |= EffectFlags.RUNNING\n    cleanupEffect(this)\n    prepareDeps(this)\n    const prevEffect = activeSub\n    const prevShouldTrack = shouldTrack\n    activeSub = this\n    shouldTrack = true\n\n    try {\n      return this.fn()\n    } finally {\n      if (__DEV__ && activeSub !== this) {\n        warn(\n          'Active effect was not restored correctly - ' +\n            'this is likely a Vue internal bug.',\n        )\n      }\n      cleanupDeps(this)\n      activeSub = prevEffect\n      shouldTrack = prevShouldTrack\n      this.flags &= ~EffectFlags.RUNNING\n    }\n  }\n\n  stop(): void {\n    if (this.flags & EffectFlags.ACTIVE) {\n      for (let link = this.deps; link; link = link.nextDep) {\n        removeSub(link)\n      }\n      this.deps = this.depsTail = undefined\n      cleanupEffect(this)\n      this.onStop && this.onStop()\n      this.flags &= ~EffectFlags.ACTIVE\n    }\n  }\n\n  trigger(): void {\n    if (this.flags & EffectFlags.PAUSED) {\n      pausedQueueEffects.add(this)\n    } else if (this.scheduler) {\n      this.scheduler()\n    } else {\n      this.runIfDirty()\n    }\n  }\n\n  /**\n   * @internal\n   */\n  runIfDirty(): void {\n    if (isDirty(this)) {\n      this.run()\n    }\n  }\n\n  get dirty(): boolean {\n    return isDirty(this)\n  }\n}\n\n/**\n * For debugging\n */\n// function printDeps(sub: Subscriber) {\n//   let d = sub.deps\n//   let ds = []\n//   while (d) {\n//     ds.push(d)\n//     d = d.nextDep\n//   }\n//   return ds.map(d => ({\n//     id: d.id,\n//     prev: d.prevDep?.id,\n//     next: d.nextDep?.id,\n//   }))\n// }\n\nlet batchDepth = 0\nlet batchedSub: Subscriber | undefined\nlet batchedComputed: Subscriber | undefined\n\nexport function batch(sub: Subscriber, isComputed = false): void {\n  sub.flags |= EffectFlags.NOTIFIED\n  if (isComputed) {\n    sub.next = batchedComputed\n    batchedComputed = sub\n    return\n  }\n  sub.next = batchedSub\n  batchedSub = sub\n}\n\n/**\n * @internal\n */\nexport function startBatch(): void {\n  batchDepth++\n}\n\n/**\n * Run batched effects when all batches have ended\n * @internal\n */\nexport function endBatch(): void {\n  if (--batchDepth > 0) {\n    return\n  }\n\n  if (batchedComputed) {\n    let e: Subscriber | undefined = batchedComputed\n    batchedComputed = undefined\n    while (e) {\n      const next: Subscriber | undefined = e.next\n      e.next = undefined\n      e.flags &= ~EffectFlags.NOTIFIED\n      e = next\n    }\n  }\n\n  let error: unknown\n  while (batchedSub) {\n    let e: Subscriber | undefined = batchedSub\n    batchedSub = undefined\n    while (e) {\n      const next: Subscriber | undefined = e.next\n      e.next = undefined\n      e.flags &= ~EffectFlags.NOTIFIED\n      if (e.flags & EffectFlags.ACTIVE) {\n        try {\n          // ACTIVE flag is effect-only\n          ;(e as ReactiveEffect).trigger()\n        } catch (err) {\n          if (!error) error = err\n        }\n      }\n      e = next\n    }\n  }\n\n  if (error) throw error\n}\n\nfunction prepareDeps(sub: Subscriber) {\n  // Prepare deps for tracking, starting from the head\n  for (let link = sub.deps; link; link = link.nextDep) {\n    // set all previous deps' (if any) version to -1 so that we can track\n    // which ones are unused after the run\n    link.version = -1\n    // store previous active sub if link was being used in another context\n    link.prevActiveLink = link.dep.activeLink\n    link.dep.activeLink = link\n  }\n}\n\nfunction cleanupDeps(sub: Subscriber) {\n  // Cleanup unused deps\n  let head\n  let tail = sub.depsTail\n  let link = tail\n  while (link) {\n    const prev = link.prevDep\n    if (link.version === -1) {\n      if (link === tail) tail = prev\n      // unused - remove it from the dep's subscribing effect list\n      removeSub(link)\n      // also remove it from this effect's dep list\n      removeDep(link)\n    } else {\n      // The new head is the last node seen which wasn't removed\n      // from the doubly-linked list\n      head = link\n    }\n\n    // restore previous active link if any\n    link.dep.activeLink = link.prevActiveLink\n    link.prevActiveLink = undefined\n    link = prev\n  }\n  // set the new head & tail\n  sub.deps = head\n  sub.depsTail = tail\n}\n\nfunction isDirty(sub: Subscriber): boolean {\n  for (let link = sub.deps; link; link = link.nextDep) {\n    if (\n      link.dep.version !== link.version ||\n      (link.dep.computed &&\n        (refreshComputed(link.dep.computed) ||\n          link.dep.version !== link.version))\n    ) {\n      return true\n    }\n  }\n  // @ts-expect-error only for backwards compatibility where libs manually set\n  // this flag - e.g. Pinia's testing module\n  if (sub._dirty) {\n    return true\n  }\n  return false\n}\n\n/**\n * Returning false indicates the refresh failed\n * @internal\n */\nexport function refreshComputed(computed: ComputedRefImpl): undefined {\n  if (\n    computed.flags & EffectFlags.TRACKING &&\n    !(computed.flags & EffectFlags.DIRTY)\n  ) {\n    return\n  }\n  computed.flags &= ~EffectFlags.DIRTY\n\n  // Global version fast path when no reactive changes has happened since\n  // last refresh.\n  if (computed.globalVersion === globalVersion) {\n    return\n  }\n  computed.globalVersion = globalVersion\n\n  // In SSR there will be no render effect, so the computed has no subscriber\n  // and therefore tracks no deps, thus we cannot rely on the dirty check.\n  // Instead, computed always re-evaluate and relies on the globalVersion\n  // fast path above for caching.\n  // #12337 if computed has no deps (does not rely on any reactive data) and evaluated,\n  // there is no need to re-evaluate.\n  if (\n    !computed.isSSR &&\n    computed.flags & EffectFlags.EVALUATED &&\n    ((!computed.deps && !(computed as any)._dirty) || !isDirty(computed))\n  ) {\n    return\n  }\n  computed.flags |= EffectFlags.RUNNING\n\n  const dep = computed.dep\n  const prevSub = activeSub\n  const prevShouldTrack = shouldTrack\n  activeSub = computed\n  shouldTrack = true\n\n  try {\n    prepareDeps(computed)\n    const value = computed.fn(computed._value)\n    if (dep.version === 0 || hasChanged(value, computed._value)) {\n      computed.flags |= EffectFlags.EVALUATED\n      computed._value = value\n      dep.version++\n    }\n  } catch (err) {\n    dep.version++\n    throw err\n  } finally {\n    activeSub = prevSub\n    shouldTrack = prevShouldTrack\n    cleanupDeps(computed)\n    computed.flags &= ~EffectFlags.RUNNING\n  }\n}\n\nfunction removeSub(link: Link, soft = false) {\n  const { dep, prevSub, nextSub } = link\n  if (prevSub) {\n    prevSub.nextSub = nextSub\n    link.prevSub = undefined\n  }\n  if (nextSub) {\n    nextSub.prevSub = prevSub\n    link.nextSub = undefined\n  }\n  if (__DEV__ && dep.subsHead === link) {\n    // was previous head, point new head to next\n    dep.subsHead = nextSub\n  }\n\n  if (dep.subs === link) {\n    // was previous tail, point new tail to prev\n    dep.subs = prevSub\n\n    if (!prevSub && dep.computed) {\n      // if computed, unsubscribe it from all its deps so this computed and its\n      // value can be GCed\n      dep.computed.flags &= ~EffectFlags.TRACKING\n      for (let l = dep.computed.deps; l; l = l.nextDep) {\n        // here we are only \"soft\" unsubscribing because the computed still keeps\n        // referencing the deps and the dep should not decrease its sub count\n        removeSub(l, true)\n      }\n    }\n  }\n\n  if (!soft && !--dep.sc && dep.map) {\n    // #11979\n    // property dep no longer has effect subscribers, delete it\n    // this mostly is for the case where an object is kept in memory but only a\n    // subset of its properties is tracked at one time\n    dep.map.delete(dep.key)\n  }\n}\n\nfunction removeDep(link: Link) {\n  const { prevDep, nextDep } = link\n  if (prevDep) {\n    prevDep.nextDep = nextDep\n    link.prevDep = undefined\n  }\n  if (nextDep) {\n    nextDep.prevDep = prevDep\n    link.nextDep = undefined\n  }\n}\n\nexport function effect<T = any>(\n  fn: () => T,\n  options?: ReactiveEffectOptions,\n): ReactiveEffectRunner<T> {\n  if ((fn as ReactiveEffectRunner).effect instanceof ReactiveEffect) {\n    fn = (fn as ReactiveEffectRunner).effect.fn\n  }\n\n  const e = new ReactiveEffect(fn)\n  if (options) {\n    extend(e, options)\n  }\n  try {\n    e.run()\n  } catch (err) {\n    e.stop()\n    throw err\n  }\n  const runner = e.run.bind(e) as ReactiveEffectRunner\n  runner.effect = e\n  return runner\n}\n\n/**\n * Stops the effect associated with the given runner.\n *\n * @param runner - Association with the effect to stop tracking.\n */\nexport function stop(runner: ReactiveEffectRunner): void {\n  runner.effect.stop()\n}\n\n/**\n * @internal\n */\nexport let shouldTrack = true\nconst trackStack: boolean[] = []\n\n/**\n * Temporarily pauses tracking.\n */\nexport function pauseTracking(): void {\n  trackStack.push(shouldTrack)\n  shouldTrack = false\n}\n\n/**\n * Re-enables effect tracking (if it was paused).\n */\nexport function enableTracking(): void {\n  trackStack.push(shouldTrack)\n  shouldTrack = true\n}\n\n/**\n * Resets the previous global effect tracking state.\n */\nexport function resetTracking(): void {\n  const last = trackStack.pop()\n  shouldTrack = last === undefined ? true : last\n}\n\n/**\n * Registers a cleanup function for the current active effect.\n * The cleanup function is called right before the next effect run, or when the\n * effect is stopped.\n *\n * Throws a warning if there is no current active effect. The warning can be\n * suppressed by passing `true` to the second argument.\n *\n * @param fn - the cleanup function to be registered\n * @param failSilently - if `true`, will not throw warning when called without\n * an active effect.\n */\nexport function onEffectCleanup(fn: () => void, failSilently = false): void {\n  if (activeSub instanceof ReactiveEffect) {\n    activeSub.cleanup = fn\n  } else if (__DEV__ && !failSilently) {\n    warn(\n      `onEffectCleanup() was called when there was no active effect` +\n        ` to associate with.`,\n    )\n  }\n}\n\nfunction cleanupEffect(e: ReactiveEffect) {\n  const { cleanup } = e\n  e.cleanup = undefined\n  if (cleanup) {\n    // run cleanup without active effect\n    const prevSub = activeSub\n    activeSub = undefined\n    try {\n      cleanup()\n    } finally {\n      activeSub = prevSub\n    }\n  }\n}\n"
  },
  {
    "path": "packages/reactivity/src/effectScope.ts",
    "content": "import type { ReactiveEffect } from './effect'\nimport { warn } from './warning'\n\nexport let activeEffectScope: EffectScope | undefined\n\nexport class EffectScope {\n  /**\n   * @internal\n   */\n  private _active = true\n  /**\n   * @internal track `on` calls, allow `on` call multiple times\n   */\n  private _on = 0\n  /**\n   * @internal\n   */\n  effects: ReactiveEffect[] = []\n  /**\n   * @internal\n   */\n  cleanups: (() => void)[] = []\n\n  private _isPaused = false\n\n  /**\n   * only assigned by undetached scope\n   * @internal\n   */\n  parent: EffectScope | undefined\n  /**\n   * record undetached scopes\n   * @internal\n   */\n  scopes: EffectScope[] | undefined\n  /**\n   * track a child scope's index in its parent's scopes array for optimized\n   * removal\n   * @internal\n   */\n  private index: number | undefined\n\n  readonly __v_skip = true\n  // TODO isolatedDeclarations ReactiveFlags.SKIP\n\n  constructor(public detached = false) {\n    this.parent = activeEffectScope\n    if (!detached && activeEffectScope) {\n      this.index =\n        (activeEffectScope.scopes || (activeEffectScope.scopes = [])).push(\n          this,\n        ) - 1\n    }\n  }\n\n  get active(): boolean {\n    return this._active\n  }\n\n  pause(): void {\n    if (this._active) {\n      this._isPaused = true\n      let i, l\n      if (this.scopes) {\n        for (i = 0, l = this.scopes.length; i < l; i++) {\n          this.scopes[i].pause()\n        }\n      }\n      for (i = 0, l = this.effects.length; i < l; i++) {\n        this.effects[i].pause()\n      }\n    }\n  }\n\n  /**\n   * Resumes the effect scope, including all child scopes and effects.\n   */\n  resume(): void {\n    if (this._active) {\n      if (this._isPaused) {\n        this._isPaused = false\n        let i, l\n        if (this.scopes) {\n          for (i = 0, l = this.scopes.length; i < l; i++) {\n            this.scopes[i].resume()\n          }\n        }\n        for (i = 0, l = this.effects.length; i < l; i++) {\n          this.effects[i].resume()\n        }\n      }\n    }\n  }\n\n  run<T>(fn: () => T): T | undefined {\n    if (this._active) {\n      const currentEffectScope = activeEffectScope\n      try {\n        activeEffectScope = this\n        return fn()\n      } finally {\n        activeEffectScope = currentEffectScope\n      }\n    } else if (__DEV__) {\n      warn(`cannot run an inactive effect scope.`)\n    }\n  }\n\n  prevScope: EffectScope | undefined\n  /**\n   * This should only be called on non-detached scopes\n   * @internal\n   */\n  on(): void {\n    if (++this._on === 1) {\n      this.prevScope = activeEffectScope\n      activeEffectScope = this\n    }\n  }\n\n  /**\n   * This should only be called on non-detached scopes\n   * @internal\n   */\n  off(): void {\n    if (this._on > 0 && --this._on === 0) {\n      activeEffectScope = this.prevScope\n      this.prevScope = undefined\n    }\n  }\n\n  stop(fromParent?: boolean): void {\n    if (this._active) {\n      this._active = false\n      let i, l\n      for (i = 0, l = this.effects.length; i < l; i++) {\n        this.effects[i].stop()\n      }\n      this.effects.length = 0\n\n      for (i = 0, l = this.cleanups.length; i < l; i++) {\n        this.cleanups[i]()\n      }\n      this.cleanups.length = 0\n\n      if (this.scopes) {\n        for (i = 0, l = this.scopes.length; i < l; i++) {\n          this.scopes[i].stop(true)\n        }\n        this.scopes.length = 0\n      }\n\n      // nested scope, dereference from parent to avoid memory leaks\n      if (!this.detached && this.parent && !fromParent) {\n        // optimized O(1) removal\n        const last = this.parent.scopes!.pop()\n        if (last && last !== this) {\n          this.parent.scopes![this.index!] = last\n          last.index = this.index!\n        }\n      }\n      this.parent = undefined\n    }\n  }\n}\n\n/**\n * Creates an effect scope object which can capture the reactive effects (i.e.\n * computed and watchers) created within it so that these effects can be\n * disposed together. For detailed use cases of this API, please consult its\n * corresponding {@link https://github.com/vuejs/rfcs/blob/master/active-rfcs/0041-reactivity-effect-scope.md | RFC}.\n *\n * @param detached - Can be used to create a \"detached\" effect scope.\n * @see {@link https://vuejs.org/api/reactivity-advanced.html#effectscope}\n */\nexport function effectScope(detached?: boolean): EffectScope {\n  return new EffectScope(detached)\n}\n\n/**\n * Returns the current active effect scope if there is one.\n *\n * @see {@link https://vuejs.org/api/reactivity-advanced.html#getcurrentscope}\n */\nexport function getCurrentScope(): EffectScope | undefined {\n  return activeEffectScope\n}\n\n/**\n * Registers a dispose callback on the current active effect scope. The\n * callback will be invoked when the associated effect scope is stopped.\n *\n * @param fn - The callback function to attach to the scope's cleanup.\n * @see {@link https://vuejs.org/api/reactivity-advanced.html#onscopedispose}\n */\nexport function onScopeDispose(fn: () => void, failSilently = false): void {\n  if (activeEffectScope) {\n    activeEffectScope.cleanups.push(fn)\n  } else if (__DEV__ && !failSilently) {\n    warn(\n      `onScopeDispose() is called when there is no active effect scope` +\n        ` to be associated with.`,\n    )\n  }\n}\n"
  },
  {
    "path": "packages/reactivity/src/index.ts",
    "content": "export {\n  ref,\n  shallowRef,\n  isRef,\n  toRef,\n  toValue,\n  toRefs,\n  unref,\n  proxyRefs,\n  customRef,\n  triggerRef,\n  type Ref,\n  type MaybeRef,\n  type MaybeRefOrGetter,\n  type ToRef,\n  type ToRefs,\n  type UnwrapRef,\n  type ShallowRef,\n  type ShallowUnwrapRef,\n  type RefUnwrapBailTypes,\n  type CustomRefFactory,\n} from './ref'\nexport {\n  reactive,\n  readonly,\n  isReactive,\n  isReadonly,\n  isShallow,\n  isProxy,\n  shallowReactive,\n  shallowReadonly,\n  markRaw,\n  toRaw,\n  toReactive,\n  toReadonly,\n  type Raw,\n  type DeepReadonly,\n  type ShallowReactive,\n  type UnwrapNestedRefs,\n  type Reactive,\n  type ReactiveMarker,\n} from './reactive'\nexport {\n  computed,\n  type ComputedRef,\n  type WritableComputedRef,\n  type WritableComputedOptions,\n  type ComputedGetter,\n  type ComputedSetter,\n  type ComputedRefImpl,\n} from './computed'\nexport {\n  effect,\n  stop,\n  enableTracking,\n  pauseTracking,\n  resetTracking,\n  onEffectCleanup,\n  ReactiveEffect,\n  EffectFlags,\n  type ReactiveEffectRunner,\n  type ReactiveEffectOptions,\n  type EffectScheduler,\n  type DebuggerOptions,\n  type DebuggerEvent,\n  type DebuggerEventExtraInfo,\n} from './effect'\nexport {\n  trigger,\n  track,\n  ITERATE_KEY,\n  ARRAY_ITERATE_KEY,\n  MAP_KEY_ITERATE_KEY,\n} from './dep'\nexport {\n  effectScope,\n  EffectScope,\n  getCurrentScope,\n  onScopeDispose,\n} from './effectScope'\nexport { reactiveReadArray, shallowReadArray } from './arrayInstrumentations'\nexport { TrackOpTypes, TriggerOpTypes, ReactiveFlags } from './constants'\nexport {\n  watch,\n  getCurrentWatcher,\n  traverse,\n  onWatcherCleanup,\n  WatchErrorCodes,\n  type WatchOptions,\n  type WatchScheduler,\n  type WatchStopHandle,\n  type WatchHandle,\n  type WatchEffect,\n  type WatchSource,\n  type WatchCallback,\n  type OnCleanup,\n} from './watch'\n"
  },
  {
    "path": "packages/reactivity/src/reactive.ts",
    "content": "import { def, hasOwn, isObject, toRawType } from '@vue/shared'\nimport {\n  mutableHandlers,\n  readonlyHandlers,\n  shallowReactiveHandlers,\n  shallowReadonlyHandlers,\n} from './baseHandlers'\nimport {\n  mutableCollectionHandlers,\n  readonlyCollectionHandlers,\n  shallowCollectionHandlers,\n  shallowReadonlyCollectionHandlers,\n} from './collectionHandlers'\nimport type { RawSymbol, Ref, UnwrapRefSimple } from './ref'\nimport { ReactiveFlags } from './constants'\nimport { warn } from './warning'\n\nexport interface Target {\n  [ReactiveFlags.SKIP]?: boolean\n  [ReactiveFlags.IS_REACTIVE]?: boolean\n  [ReactiveFlags.IS_READONLY]?: boolean\n  [ReactiveFlags.IS_SHALLOW]?: boolean\n  [ReactiveFlags.RAW]?: any\n}\n\nexport const reactiveMap: WeakMap<Target, any> = new WeakMap<Target, any>()\nexport const shallowReactiveMap: WeakMap<Target, any> = new WeakMap<\n  Target,\n  any\n>()\nexport const readonlyMap: WeakMap<Target, any> = new WeakMap<Target, any>()\nexport const shallowReadonlyMap: WeakMap<Target, any> = new WeakMap<\n  Target,\n  any\n>()\n\nenum TargetType {\n  INVALID = 0,\n  COMMON = 1,\n  COLLECTION = 2,\n}\n\nfunction targetTypeMap(rawType: string) {\n  switch (rawType) {\n    case 'Object':\n    case 'Array':\n      return TargetType.COMMON\n    case 'Map':\n    case 'Set':\n    case 'WeakMap':\n    case 'WeakSet':\n      return TargetType.COLLECTION\n    default:\n      return TargetType.INVALID\n  }\n}\n\nfunction getTargetType(value: Target) {\n  return value[ReactiveFlags.SKIP] || !Object.isExtensible(value)\n    ? TargetType.INVALID\n    : targetTypeMap(toRawType(value))\n}\n\n// only unwrap nested ref\nexport type UnwrapNestedRefs<T> = T extends Ref ? T : UnwrapRefSimple<T>\n\ndeclare const ReactiveMarkerSymbol: unique symbol\n\nexport interface ReactiveMarker {\n  [ReactiveMarkerSymbol]?: void\n}\n\nexport type Reactive<T> = UnwrapNestedRefs<T> &\n  (T extends readonly any[] ? ReactiveMarker : {})\n\n/**\n * Returns a reactive proxy of the object.\n *\n * The reactive conversion is \"deep\": it affects all nested properties. A\n * reactive object also deeply unwraps any properties that are refs while\n * maintaining reactivity.\n *\n * @example\n * ```js\n * const obj = reactive({ count: 0 })\n * ```\n *\n * @param target - The source object.\n * @see {@link https://vuejs.org/api/reactivity-core.html#reactive}\n */\nexport function reactive<T extends object>(target: T): Reactive<T>\n/*@__NO_SIDE_EFFECTS__*/\nexport function reactive(target: object) {\n  // if trying to observe a readonly proxy, return the readonly version.\n  if (isReadonly(target)) {\n    return target\n  }\n  return createReactiveObject(\n    target,\n    false,\n    mutableHandlers,\n    mutableCollectionHandlers,\n    reactiveMap,\n  )\n}\n\nexport declare const ShallowReactiveMarker: unique symbol\n\nexport type ShallowReactive<T> = T & { [ShallowReactiveMarker]?: true }\n\n/**\n * Shallow version of {@link reactive}.\n *\n * Unlike {@link reactive}, there is no deep conversion: only root-level\n * properties are reactive for a shallow reactive object. Property values are\n * stored and exposed as-is - this also means properties with ref values will\n * not be automatically unwrapped.\n *\n * @example\n * ```js\n * const state = shallowReactive({\n *   foo: 1,\n *   nested: {\n *     bar: 2\n *   }\n * })\n *\n * // mutating state's own properties is reactive\n * state.foo++\n *\n * // ...but does not convert nested objects\n * isReactive(state.nested) // false\n *\n * // NOT reactive\n * state.nested.bar++\n * ```\n *\n * @param target - The source object.\n * @see {@link https://vuejs.org/api/reactivity-advanced.html#shallowreactive}\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function shallowReactive<T extends object>(\n  target: T,\n): ShallowReactive<T> {\n  return createReactiveObject(\n    target,\n    false,\n    shallowReactiveHandlers,\n    shallowCollectionHandlers,\n    shallowReactiveMap,\n  )\n}\n\ntype Primitive = string | number | boolean | bigint | symbol | undefined | null\nexport type Builtin = Primitive | Function | Date | Error | RegExp\nexport type DeepReadonly<T> = T extends Builtin\n  ? T\n  : T extends Map<infer K, infer V>\n    ? ReadonlyMap<DeepReadonly<K>, DeepReadonly<V>>\n    : T extends ReadonlyMap<infer K, infer V>\n      ? ReadonlyMap<DeepReadonly<K>, DeepReadonly<V>>\n      : T extends WeakMap<infer K, infer V>\n        ? WeakMap<DeepReadonly<K>, DeepReadonly<V>>\n        : T extends Set<infer U>\n          ? ReadonlySet<DeepReadonly<U>>\n          : T extends ReadonlySet<infer U>\n            ? ReadonlySet<DeepReadonly<U>>\n            : T extends WeakSet<infer U>\n              ? WeakSet<DeepReadonly<U>>\n              : T extends Promise<infer U>\n                ? Promise<DeepReadonly<U>>\n                : T extends Ref<infer U, unknown>\n                  ? Readonly<Ref<DeepReadonly<U>>>\n                  : T extends {}\n                    ? { readonly [K in keyof T]: DeepReadonly<T[K]> }\n                    : Readonly<T>\n\n/**\n * Takes an object (reactive or plain) or a ref and returns a readonly proxy to\n * the original.\n *\n * A readonly proxy is deep: any nested property accessed will be readonly as\n * well. It also has the same ref-unwrapping behavior as {@link reactive},\n * except the unwrapped values will also be made readonly.\n *\n * @example\n * ```js\n * const original = reactive({ count: 0 })\n *\n * const copy = readonly(original)\n *\n * watchEffect(() => {\n *   // works for reactivity tracking\n *   console.log(copy.count)\n * })\n *\n * // mutating original will trigger watchers relying on the copy\n * original.count++\n *\n * // mutating the copy will fail and result in a warning\n * copy.count++ // warning!\n * ```\n *\n * @param target - The source object.\n * @see {@link https://vuejs.org/api/reactivity-core.html#readonly}\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function readonly<T extends object>(\n  target: T,\n): DeepReadonly<UnwrapNestedRefs<T>> {\n  return createReactiveObject(\n    target,\n    true,\n    readonlyHandlers,\n    readonlyCollectionHandlers,\n    readonlyMap,\n  )\n}\n\n/**\n * Shallow version of {@link readonly}.\n *\n * Unlike {@link readonly}, there is no deep conversion: only root-level\n * properties are made readonly. Property values are stored and exposed as-is -\n * this also means properties with ref values will not be automatically\n * unwrapped.\n *\n * @example\n * ```js\n * const state = shallowReadonly({\n *   foo: 1,\n *   nested: {\n *     bar: 2\n *   }\n * })\n *\n * // mutating state's own properties will fail\n * state.foo++\n *\n * // ...but works on nested objects\n * isReadonly(state.nested) // false\n *\n * // works\n * state.nested.bar++\n * ```\n *\n * @param target - The source object.\n * @see {@link https://vuejs.org/api/reactivity-advanced.html#shallowreadonly}\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function shallowReadonly<T extends object>(target: T): Readonly<T> {\n  return createReactiveObject(\n    target,\n    true,\n    shallowReadonlyHandlers,\n    shallowReadonlyCollectionHandlers,\n    shallowReadonlyMap,\n  )\n}\n\nfunction createReactiveObject(\n  target: Target,\n  isReadonly: boolean,\n  baseHandlers: ProxyHandler<any>,\n  collectionHandlers: ProxyHandler<any>,\n  proxyMap: WeakMap<Target, any>,\n) {\n  if (!isObject(target)) {\n    if (__DEV__) {\n      warn(\n        `value cannot be made ${isReadonly ? 'readonly' : 'reactive'}: ${String(\n          target,\n        )}`,\n      )\n    }\n    return target\n  }\n  // target is already a Proxy, return it.\n  // exception: calling readonly() on a reactive object\n  if (\n    target[ReactiveFlags.RAW] &&\n    !(isReadonly && target[ReactiveFlags.IS_REACTIVE])\n  ) {\n    return target\n  }\n  // only specific value types can be observed.\n  const targetType = getTargetType(target)\n  if (targetType === TargetType.INVALID) {\n    return target\n  }\n  // target already has corresponding Proxy\n  const existingProxy = proxyMap.get(target)\n  if (existingProxy) {\n    return existingProxy\n  }\n  const proxy = new Proxy(\n    target,\n    targetType === TargetType.COLLECTION ? collectionHandlers : baseHandlers,\n  )\n  proxyMap.set(target, proxy)\n  return proxy\n}\n\n/**\n * Checks if an object is a proxy created by {@link reactive} or\n * {@link shallowReactive} (or {@link ref} in some cases).\n *\n * @example\n * ```js\n * isReactive(reactive({}))            // => true\n * isReactive(readonly(reactive({})))  // => true\n * isReactive(ref({}).value)           // => true\n * isReactive(readonly(ref({})).value) // => true\n * isReactive(ref(true))               // => false\n * isReactive(shallowRef({}).value)    // => false\n * isReactive(shallowReactive({}))     // => true\n * ```\n *\n * @param value - The value to check.\n * @see {@link https://vuejs.org/api/reactivity-utilities.html#isreactive}\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function isReactive(value: unknown): boolean {\n  if (isReadonly(value)) {\n    return isReactive((value as Target)[ReactiveFlags.RAW])\n  }\n  return !!(value && (value as Target)[ReactiveFlags.IS_REACTIVE])\n}\n\n/**\n * Checks whether the passed value is a readonly object. The properties of a\n * readonly object can change, but they can't be assigned directly via the\n * passed object.\n *\n * The proxies created by {@link readonly} and {@link shallowReadonly} are\n * both considered readonly, as is a computed ref without a set function.\n *\n * @param value - The value to check.\n * @see {@link https://vuejs.org/api/reactivity-utilities.html#isreadonly}\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function isReadonly(value: unknown): boolean {\n  return !!(value && (value as Target)[ReactiveFlags.IS_READONLY])\n}\n\n/*@__NO_SIDE_EFFECTS__*/\nexport function isShallow(value: unknown): boolean {\n  return !!(value && (value as Target)[ReactiveFlags.IS_SHALLOW])\n}\n\n/**\n * Checks if an object is a proxy created by {@link reactive},\n * {@link readonly}, {@link shallowReactive} or {@link shallowReadonly}.\n *\n * @param value - The value to check.\n * @see {@link https://vuejs.org/api/reactivity-utilities.html#isproxy}\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function isProxy(value: any): boolean {\n  return value ? !!value[ReactiveFlags.RAW] : false\n}\n\n/**\n * Returns the raw, original object of a Vue-created proxy.\n *\n * `toRaw()` can return the original object from proxies created by\n * {@link reactive}, {@link readonly}, {@link shallowReactive} or\n * {@link shallowReadonly}.\n *\n * This is an escape hatch that can be used to temporarily read without\n * incurring proxy access / tracking overhead or write without triggering\n * changes. It is **not** recommended to hold a persistent reference to the\n * original object. Use with caution.\n *\n * @example\n * ```js\n * const foo = {}\n * const reactiveFoo = reactive(foo)\n *\n * console.log(toRaw(reactiveFoo) === foo) // true\n * ```\n *\n * @param observed - The object for which the \"raw\" value is requested.\n * @see {@link https://vuejs.org/api/reactivity-advanced.html#toraw}\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function toRaw<T>(observed: T): T {\n  const raw = observed && (observed as Target)[ReactiveFlags.RAW]\n  return raw ? toRaw(raw) : observed\n}\n\nexport type Raw<T> = T & { [RawSymbol]?: true }\n\n/**\n * Marks an object so that it will never be converted to a proxy. Returns the\n * object itself.\n *\n * @example\n * ```js\n * const foo = markRaw({})\n * console.log(isReactive(reactive(foo))) // false\n *\n * // also works when nested inside other reactive objects\n * const bar = reactive({ foo })\n * console.log(isReactive(bar.foo)) // false\n * ```\n *\n * **Warning:** `markRaw()` together with the shallow APIs such as\n * {@link shallowReactive} allow you to selectively opt-out of the default\n * deep reactive/readonly conversion and embed raw, non-proxied objects in your\n * state graph.\n *\n * @param value - The object to be marked as \"raw\".\n * @see {@link https://vuejs.org/api/reactivity-advanced.html#markraw}\n */\nexport function markRaw<T extends object>(value: T): Raw<T> {\n  if (!hasOwn(value, ReactiveFlags.SKIP) && Object.isExtensible(value)) {\n    def(value, ReactiveFlags.SKIP, true)\n  }\n  return value\n}\n\n/**\n * Returns a reactive proxy of the given value (if possible).\n *\n * If the given value is not an object, the original value itself is returned.\n *\n * @param value - The value for which a reactive proxy shall be created.\n */\nexport const toReactive = <T extends unknown>(value: T): T =>\n  isObject(value) ? reactive(value) : value\n\n/**\n * Returns a readonly proxy of the given value (if possible).\n *\n * If the given value is not an object, the original value itself is returned.\n *\n * @param value - The value for which a readonly proxy shall be created.\n */\nexport const toReadonly = <T extends unknown>(value: T): DeepReadonly<T> =>\n  isObject(value) ? readonly(value) : (value as DeepReadonly<T>)\n"
  },
  {
    "path": "packages/reactivity/src/ref.ts",
    "content": "import {\n  type IfAny,\n  hasChanged,\n  isArray,\n  isFunction,\n  isIntegerKey,\n  isObject,\n} from '@vue/shared'\nimport { Dep, getDepFromReactive } from './dep'\nimport {\n  type Builtin,\n  type ShallowReactiveMarker,\n  type Target,\n  isProxy,\n  isReactive,\n  isReadonly,\n  isShallow,\n  toRaw,\n  toReactive,\n} from './reactive'\nimport type { ComputedRef, WritableComputedRef } from './computed'\nimport { ReactiveFlags, TrackOpTypes, TriggerOpTypes } from './constants'\nimport { warn } from './warning'\n\ndeclare const RefSymbol: unique symbol\nexport declare const RawSymbol: unique symbol\n\nexport interface Ref<T = any, S = T> {\n  get value(): T\n  set value(_: S)\n  /**\n   * Type differentiator only.\n   * We need this to be in public d.ts but don't want it to show up in IDE\n   * autocomplete, so we use a private Symbol instead.\n   */\n  [RefSymbol]: true\n}\n\n/**\n * Checks if a value is a ref object.\n *\n * @param r - The value to inspect.\n * @see {@link https://vuejs.org/api/reactivity-utilities.html#isref}\n */\nexport function isRef<T>(r: Ref<T> | unknown): r is Ref<T>\n/*@__NO_SIDE_EFFECTS__*/\nexport function isRef(r: any): r is Ref {\n  return r ? r[ReactiveFlags.IS_REF] === true : false\n}\n\n/**\n * Takes an inner value and returns a reactive and mutable ref object, which\n * has a single property `.value` that points to the inner value.\n *\n * @param value - The object to wrap in the ref.\n * @see {@link https://vuejs.org/api/reactivity-core.html#ref}\n */\nexport function ref<T>(\n  value: T,\n): [T] extends [Ref] ? IfAny<T, Ref<T>, T> : Ref<UnwrapRef<T>, UnwrapRef<T> | T>\nexport function ref<T = any>(): Ref<T | undefined>\n/*@__NO_SIDE_EFFECTS__*/\nexport function ref(value?: unknown) {\n  return createRef(value, false)\n}\n\ndeclare const ShallowRefMarker: unique symbol\n\nexport type ShallowRef<T = any, S = T> = Ref<T, S> & {\n  [ShallowRefMarker]?: true\n}\n\n/**\n * Shallow version of {@link ref}.\n *\n * @example\n * ```js\n * const state = shallowRef({ count: 1 })\n *\n * // does NOT trigger change\n * state.value.count = 2\n *\n * // does trigger change\n * state.value = { count: 2 }\n * ```\n *\n * @param value - The \"inner value\" for the shallow ref.\n * @see {@link https://vuejs.org/api/reactivity-advanced.html#shallowref}\n */\nexport function shallowRef<T>(\n  value: T,\n): Ref extends T\n  ? T extends Ref\n    ? IfAny<T, ShallowRef<T>, T>\n    : ShallowRef<T>\n  : ShallowRef<T>\nexport function shallowRef<T = any>(): ShallowRef<T | undefined>\n/*@__NO_SIDE_EFFECTS__*/\nexport function shallowRef(value?: unknown) {\n  return createRef(value, true)\n}\n\nfunction createRef(rawValue: unknown, shallow: boolean) {\n  if (isRef(rawValue)) {\n    return rawValue\n  }\n  return new RefImpl(rawValue, shallow)\n}\n\n/**\n * @internal\n */\nclass RefImpl<T = any> {\n  _value: T\n  private _rawValue: T\n\n  dep: Dep = new Dep()\n\n  public readonly [ReactiveFlags.IS_REF] = true\n  public readonly [ReactiveFlags.IS_SHALLOW]: boolean = false\n\n  constructor(value: T, isShallow: boolean) {\n    this._rawValue = isShallow ? value : toRaw(value)\n    this._value = isShallow ? value : toReactive(value)\n    this[ReactiveFlags.IS_SHALLOW] = isShallow\n  }\n\n  get value() {\n    if (__DEV__) {\n      this.dep.track({\n        target: this,\n        type: TrackOpTypes.GET,\n        key: 'value',\n      })\n    } else {\n      this.dep.track()\n    }\n    return this._value\n  }\n\n  set value(newValue) {\n    const oldValue = this._rawValue\n    const useDirectValue =\n      this[ReactiveFlags.IS_SHALLOW] ||\n      isShallow(newValue) ||\n      isReadonly(newValue)\n    newValue = useDirectValue ? newValue : toRaw(newValue)\n    if (hasChanged(newValue, oldValue)) {\n      this._rawValue = newValue\n      this._value = useDirectValue ? newValue : toReactive(newValue)\n      if (__DEV__) {\n        this.dep.trigger({\n          target: this,\n          type: TriggerOpTypes.SET,\n          key: 'value',\n          newValue,\n          oldValue,\n        })\n      } else {\n        this.dep.trigger()\n      }\n    }\n  }\n}\n\n/**\n * Force trigger effects that depends on a shallow ref. This is typically used\n * after making deep mutations to the inner value of a shallow ref.\n *\n * @example\n * ```js\n * const shallow = shallowRef({\n *   greet: 'Hello, world'\n * })\n *\n * // Logs \"Hello, world\" once for the first run-through\n * watchEffect(() => {\n *   console.log(shallow.value.greet)\n * })\n *\n * // This won't trigger the effect because the ref is shallow\n * shallow.value.greet = 'Hello, universe'\n *\n * // Logs \"Hello, universe\"\n * triggerRef(shallow)\n * ```\n *\n * @param ref - The ref whose tied effects shall be executed.\n * @see {@link https://vuejs.org/api/reactivity-advanced.html#triggerref}\n */\nexport function triggerRef(ref: Ref): void {\n  // ref may be an instance of ObjectRefImpl\n  if ((ref as unknown as RefImpl).dep) {\n    if (__DEV__) {\n      ;(ref as unknown as RefImpl).dep.trigger({\n        target: ref,\n        type: TriggerOpTypes.SET,\n        key: 'value',\n        newValue: (ref as unknown as RefImpl)._value,\n      })\n    } else {\n      ;(ref as unknown as RefImpl).dep.trigger()\n    }\n  }\n}\n\nexport type MaybeRef<T = any> =\n  | T\n  | Ref<T>\n  | ShallowRef<T>\n  | WritableComputedRef<T>\n\nexport type MaybeRefOrGetter<T = any> = MaybeRef<T> | ComputedRef<T> | (() => T)\n\n/**\n * Returns the inner value if the argument is a ref, otherwise return the\n * argument itself. This is a sugar function for\n * `val = isRef(val) ? val.value : val`.\n *\n * @example\n * ```js\n * function useFoo(x: number | Ref<number>) {\n *   const unwrapped = unref(x)\n *   // unwrapped is guaranteed to be number now\n * }\n * ```\n *\n * @param ref - Ref or plain value to be converted into the plain value.\n * @see {@link https://vuejs.org/api/reactivity-utilities.html#unref}\n */\nexport function unref<T>(ref: MaybeRef<T> | ComputedRef<T>): T {\n  return isRef(ref) ? ref.value : ref\n}\n\n/**\n * Normalizes values / refs / getters to values.\n * This is similar to {@link unref}, except that it also normalizes getters.\n * If the argument is a getter, it will be invoked and its return value will\n * be returned.\n *\n * @example\n * ```js\n * toValue(1) // 1\n * toValue(ref(1)) // 1\n * toValue(() => 1) // 1\n * ```\n *\n * @param source - A getter, an existing ref, or a non-function value.\n * @see {@link https://vuejs.org/api/reactivity-utilities.html#tovalue}\n */\nexport function toValue<T>(source: MaybeRefOrGetter<T>): T {\n  return isFunction(source) ? source() : unref(source)\n}\n\nconst shallowUnwrapHandlers: ProxyHandler<any> = {\n  get: (target, key, receiver) =>\n    key === ReactiveFlags.RAW\n      ? target\n      : unref(Reflect.get(target, key, receiver)),\n  set: (target, key, value, receiver) => {\n    const oldValue = target[key]\n    if (isRef(oldValue) && !isRef(value)) {\n      oldValue.value = value\n      return true\n    } else {\n      return Reflect.set(target, key, value, receiver)\n    }\n  },\n}\n\n/**\n * Returns a proxy for the given object that shallowly unwraps properties that\n * are refs. If the object already is reactive, it's returned as-is. If not, a\n * new reactive proxy is created.\n *\n * @param objectWithRefs - Either an already-reactive object or a simple object\n * that contains refs.\n */\nexport function proxyRefs<T extends object>(\n  objectWithRefs: T,\n): ShallowUnwrapRef<T> {\n  return isReactive(objectWithRefs)\n    ? (objectWithRefs as ShallowUnwrapRef<T>)\n    : new Proxy(objectWithRefs, shallowUnwrapHandlers)\n}\n\nexport type CustomRefFactory<T> = (\n  track: () => void,\n  trigger: () => void,\n) => {\n  get: () => T\n  set: (value: T) => void\n}\n\nclass CustomRefImpl<T> {\n  public dep: Dep\n\n  private readonly _get: ReturnType<CustomRefFactory<T>>['get']\n  private readonly _set: ReturnType<CustomRefFactory<T>>['set']\n\n  public readonly [ReactiveFlags.IS_REF] = true\n\n  public _value: T = undefined!\n\n  constructor(factory: CustomRefFactory<T>) {\n    const dep = (this.dep = new Dep())\n    const { get, set } = factory(dep.track.bind(dep), dep.trigger.bind(dep))\n    this._get = get\n    this._set = set\n  }\n\n  get value() {\n    return (this._value = this._get())\n  }\n\n  set value(newVal) {\n    this._set(newVal)\n  }\n}\n\n/**\n * Creates a customized ref with explicit control over its dependency tracking\n * and updates triggering.\n *\n * @param factory - The function that receives the `track` and `trigger` callbacks.\n * @see {@link https://vuejs.org/api/reactivity-advanced.html#customref}\n */\nexport function customRef<T>(factory: CustomRefFactory<T>): Ref<T> {\n  return new CustomRefImpl(factory) as any\n}\n\nexport type ToRefs<T = any> = {\n  [K in keyof T]: ToRef<T[K]>\n}\n\n/**\n * Converts a reactive object to a plain object where each property of the\n * resulting object is a ref pointing to the corresponding property of the\n * original object. Each individual ref is created using {@link toRef}.\n *\n * @param object - Reactive object to be made into an object of linked refs.\n * @see {@link https://vuejs.org/api/reactivity-utilities.html#torefs}\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function toRefs<T extends object>(object: T): ToRefs<T> {\n  if (__DEV__ && !isProxy(object)) {\n    warn(`toRefs() expects a reactive object but received a plain one.`)\n  }\n  const ret: any = isArray(object) ? new Array(object.length) : {}\n  for (const key in object) {\n    ret[key] = propertyToRef(object, key)\n  }\n  return ret\n}\n\nclass ObjectRefImpl<T extends object, K extends keyof T> {\n  public readonly [ReactiveFlags.IS_REF] = true\n  public _value: T[K] = undefined!\n\n  private readonly _raw: T\n  private readonly _shallow: boolean\n\n  constructor(\n    private readonly _object: T,\n    private readonly _key: K,\n    private readonly _defaultValue?: T[K],\n  ) {\n    this._raw = toRaw(_object)\n\n    let shallow = true\n    let obj = _object\n\n    // For an array with integer key, refs are not unwrapped\n    if (!isArray(_object) || !isIntegerKey(String(_key))) {\n      // Otherwise, check each proxy layer for unwrapping\n      do {\n        shallow = !isProxy(obj) || isShallow(obj)\n      } while (shallow && (obj = (obj as Target)[ReactiveFlags.RAW]))\n    }\n\n    this._shallow = shallow\n  }\n\n  get value() {\n    let val = this._object[this._key]\n    if (this._shallow) {\n      val = unref(val)\n    }\n    return (this._value = val === undefined ? this._defaultValue! : val)\n  }\n\n  set value(newVal) {\n    if (this._shallow && isRef(this._raw[this._key])) {\n      const nestedRef = this._object[this._key]\n      if (isRef(nestedRef)) {\n        nestedRef.value = newVal\n        return\n      }\n    }\n\n    this._object[this._key] = newVal\n  }\n\n  get dep(): Dep | undefined {\n    return getDepFromReactive(this._raw, this._key)\n  }\n}\n\nclass GetterRefImpl<T> {\n  public readonly [ReactiveFlags.IS_REF] = true\n  public readonly [ReactiveFlags.IS_READONLY] = true\n  public _value: T = undefined!\n\n  constructor(private readonly _getter: () => T) {}\n  get value() {\n    return (this._value = this._getter())\n  }\n}\n\nexport type ToRef<T> = IfAny<T, Ref<T>, [T] extends [Ref] ? T : Ref<T>>\n\n/**\n * Used to normalize values / refs / getters into refs.\n *\n * @example\n * ```js\n * // returns existing refs as-is\n * toRef(existingRef)\n *\n * // creates a ref that calls the getter on .value access\n * toRef(() => props.foo)\n *\n * // creates normal refs from non-function values\n * // equivalent to ref(1)\n * toRef(1)\n * ```\n *\n * Can also be used to create a ref for a property on a source reactive object.\n * The created ref is synced with its source property: mutating the source\n * property will update the ref, and vice-versa.\n *\n * @example\n * ```js\n * const state = reactive({\n *   foo: 1,\n *   bar: 2\n * })\n *\n * const fooRef = toRef(state, 'foo')\n *\n * // mutating the ref updates the original\n * fooRef.value++\n * console.log(state.foo) // 2\n *\n * // mutating the original also updates the ref\n * state.foo++\n * console.log(fooRef.value) // 3\n * ```\n *\n * @param source - A getter, an existing ref, a non-function value, or a\n *                 reactive object to create a property ref from.\n * @param [key] - (optional) Name of the property in the reactive object.\n * @see {@link https://vuejs.org/api/reactivity-utilities.html#toref}\n */\nexport function toRef<T>(\n  value: T,\n): T extends () => infer R\n  ? Readonly<Ref<R>>\n  : T extends Ref\n    ? T\n    : Ref<UnwrapRef<T>>\nexport function toRef<T extends object, K extends keyof T>(\n  object: T,\n  key: K,\n): ToRef<T[K]>\nexport function toRef<T extends object, K extends keyof T>(\n  object: T,\n  key: K,\n  defaultValue: T[K],\n): ToRef<Exclude<T[K], undefined>>\n/*@__NO_SIDE_EFFECTS__*/\nexport function toRef(\n  source: Record<string, any> | MaybeRef,\n  key?: string,\n  defaultValue?: unknown,\n): Ref {\n  if (isRef(source)) {\n    return source\n  } else if (isFunction(source)) {\n    return new GetterRefImpl(source) as any\n  } else if (isObject(source) && arguments.length > 1) {\n    return propertyToRef(source, key!, defaultValue)\n  } else {\n    return ref(source)\n  }\n}\n\nfunction propertyToRef(\n  source: Record<string, any>,\n  key: string,\n  defaultValue?: unknown,\n) {\n  return new ObjectRefImpl(source, key, defaultValue) as any\n}\n\n/**\n * This is a special exported interface for other packages to declare\n * additional types that should bail out for ref unwrapping. For example\n * \\@vue/runtime-dom can declare it like so in its d.ts:\n *\n * ``` ts\n * declare module '@vue/reactivity' {\n *   export interface RefUnwrapBailTypes {\n *     runtimeDOMBailTypes: Node | Window\n *   }\n * }\n * ```\n */\nexport interface RefUnwrapBailTypes {}\n\nexport type ShallowUnwrapRef<T> = {\n  [K in keyof T]: DistributeRef<T[K]>\n}\n\ntype DistributeRef<T> = T extends Ref<infer V, unknown> ? V : T\n\nexport type UnwrapRef<T> =\n  T extends ShallowRef<infer V, unknown>\n    ? V\n    : T extends Ref<infer V, unknown>\n      ? UnwrapRefSimple<V>\n      : UnwrapRefSimple<T>\n\nexport type UnwrapRefSimple<T> = T extends\n  | Builtin\n  | Ref\n  | RefUnwrapBailTypes[keyof RefUnwrapBailTypes]\n  | { [RawSymbol]?: true }\n  ? T\n  : T extends Map<infer K, infer V>\n    ? Map<K, UnwrapRefSimple<V>> & UnwrapRef<Omit<T, keyof Map<any, any>>>\n    : T extends WeakMap<infer K, infer V>\n      ? WeakMap<K, UnwrapRefSimple<V>> &\n          UnwrapRef<Omit<T, keyof WeakMap<any, any>>>\n      : T extends Set<infer V>\n        ? Set<UnwrapRefSimple<V>> & UnwrapRef<Omit<T, keyof Set<any>>>\n        : T extends WeakSet<infer V>\n          ? WeakSet<UnwrapRefSimple<V>> & UnwrapRef<Omit<T, keyof WeakSet<any>>>\n          : T extends ReadonlyArray<any>\n            ? { [K in keyof T]: UnwrapRefSimple<T[K]> }\n            : T extends object & { [ShallowReactiveMarker]?: never }\n              ? {\n                  [P in keyof T]: P extends symbol ? T[P] : UnwrapRef<T[P]>\n                }\n              : T\n"
  },
  {
    "path": "packages/reactivity/src/warning.ts",
    "content": "export function warn(msg: string, ...args: any[]): void {\n  console.warn(`[Vue warn] ${msg}`, ...args)\n}\n"
  },
  {
    "path": "packages/reactivity/src/watch.ts",
    "content": "import {\n  EMPTY_OBJ,\n  NOOP,\n  hasChanged,\n  isArray,\n  isFunction,\n  isMap,\n  isObject,\n  isPlainObject,\n  isSet,\n  remove,\n} from '@vue/shared'\nimport { warn } from './warning'\nimport type { ComputedRef } from './computed'\nimport { ReactiveFlags } from './constants'\nimport {\n  type DebuggerOptions,\n  EffectFlags,\n  type EffectScheduler,\n  ReactiveEffect,\n  pauseTracking,\n  resetTracking,\n} from './effect'\nimport { isReactive, isShallow } from './reactive'\nimport { type Ref, isRef } from './ref'\nimport { getCurrentScope } from './effectScope'\n\n// These errors were transferred from `packages/runtime-core/src/errorHandling.ts`\n// to @vue/reactivity to allow co-location with the moved base watch logic, hence\n// it is essential to keep these values unchanged.\nexport enum WatchErrorCodes {\n  WATCH_GETTER = 2,\n  WATCH_CALLBACK,\n  WATCH_CLEANUP,\n}\n\nexport type WatchEffect = (onCleanup: OnCleanup) => void\n\nexport type WatchSource<T = any> = Ref<T, any> | ComputedRef<T> | (() => T)\n\nexport type WatchCallback<V = any, OV = any> = (\n  value: V,\n  oldValue: OV,\n  onCleanup: OnCleanup,\n) => any\n\nexport type OnCleanup = (cleanupFn: () => void) => void\n\nexport interface WatchOptions<Immediate = boolean> extends DebuggerOptions {\n  immediate?: Immediate\n  deep?: boolean | number\n  once?: boolean\n  scheduler?: WatchScheduler\n  onWarn?: (msg: string, ...args: any[]) => void\n  /**\n   * @internal\n   */\n  augmentJob?: (job: (...args: any[]) => void) => void\n  /**\n   * @internal\n   */\n  call?: (\n    fn: Function | Function[],\n    type: WatchErrorCodes,\n    args?: unknown[],\n  ) => void\n}\n\nexport type WatchStopHandle = () => void\n\nexport interface WatchHandle extends WatchStopHandle {\n  pause: () => void\n  resume: () => void\n  stop: () => void\n}\n\n// initial value for watchers to trigger on undefined initial values\nconst INITIAL_WATCHER_VALUE = {}\n\nexport type WatchScheduler = (job: () => void, isFirstRun: boolean) => void\n\nconst cleanupMap: WeakMap<ReactiveEffect, (() => void)[]> = new WeakMap()\nlet activeWatcher: ReactiveEffect | undefined = undefined\n\n/**\n * Returns the current active effect if there is one.\n */\nexport function getCurrentWatcher(): ReactiveEffect<any> | undefined {\n  return activeWatcher\n}\n\n/**\n * Registers a cleanup callback on the current active effect. This\n * registered cleanup callback will be invoked right before the\n * associated effect re-runs.\n *\n * @param cleanupFn - The callback function to attach to the effect's cleanup.\n * @param failSilently - if `true`, will not throw warning when called without\n * an active effect.\n * @param owner - The effect that this cleanup function should be attached to.\n * By default, the current active effect.\n */\nexport function onWatcherCleanup(\n  cleanupFn: () => void,\n  failSilently = false,\n  owner: ReactiveEffect | undefined = activeWatcher,\n): void {\n  if (owner) {\n    let cleanups = cleanupMap.get(owner)\n    if (!cleanups) cleanupMap.set(owner, (cleanups = []))\n    cleanups.push(cleanupFn)\n  } else if (__DEV__ && !failSilently) {\n    warn(\n      `onWatcherCleanup() was called when there was no active watcher` +\n        ` to associate with.`,\n    )\n  }\n}\n\nexport function watch(\n  source: WatchSource | WatchSource[] | WatchEffect | object,\n  cb?: WatchCallback | null,\n  options: WatchOptions = EMPTY_OBJ,\n): WatchHandle {\n  const { immediate, deep, once, scheduler, augmentJob, call } = options\n\n  const warnInvalidSource = (s: unknown) => {\n    ;(options.onWarn || warn)(\n      `Invalid watch source: `,\n      s,\n      `A watch source can only be a getter/effect function, a ref, ` +\n        `a reactive object, or an array of these types.`,\n    )\n  }\n\n  const reactiveGetter = (source: object) => {\n    // traverse will happen in wrapped getter below\n    if (deep) return source\n    // for `deep: false | 0` or shallow reactive, only traverse root-level properties\n    if (isShallow(source) || deep === false || deep === 0)\n      return traverse(source, 1)\n    // for `deep: undefined` on a reactive object, deeply traverse all properties\n    return traverse(source)\n  }\n\n  let effect: ReactiveEffect\n  let getter: () => any\n  let cleanup: (() => void) | undefined\n  let boundCleanup: typeof onWatcherCleanup\n  let forceTrigger = false\n  let isMultiSource = false\n\n  if (isRef(source)) {\n    getter = () => source.value\n    forceTrigger = isShallow(source)\n  } else if (isReactive(source)) {\n    getter = () => reactiveGetter(source)\n    forceTrigger = true\n  } else if (isArray(source)) {\n    isMultiSource = true\n    forceTrigger = source.some(s => isReactive(s) || isShallow(s))\n    getter = () =>\n      source.map(s => {\n        if (isRef(s)) {\n          return s.value\n        } else if (isReactive(s)) {\n          return reactiveGetter(s)\n        } else if (isFunction(s)) {\n          return call ? call(s, WatchErrorCodes.WATCH_GETTER) : s()\n        } else {\n          __DEV__ && warnInvalidSource(s)\n        }\n      })\n  } else if (isFunction(source)) {\n    if (cb) {\n      // getter with cb\n      getter = call\n        ? () => call(source, WatchErrorCodes.WATCH_GETTER)\n        : (source as () => any)\n    } else {\n      // no cb -> simple effect\n      getter = () => {\n        if (cleanup) {\n          pauseTracking()\n          try {\n            cleanup()\n          } finally {\n            resetTracking()\n          }\n        }\n        const currentEffect = activeWatcher\n        activeWatcher = effect\n        try {\n          return call\n            ? call(source, WatchErrorCodes.WATCH_CALLBACK, [boundCleanup])\n            : source(boundCleanup)\n        } finally {\n          activeWatcher = currentEffect\n        }\n      }\n    }\n  } else {\n    getter = NOOP\n    __DEV__ && warnInvalidSource(source)\n  }\n\n  if (cb && deep) {\n    const baseGetter = getter\n    const depth = deep === true ? Infinity : deep\n    getter = () => traverse(baseGetter(), depth)\n  }\n\n  const scope = getCurrentScope()\n  const watchHandle: WatchHandle = () => {\n    effect.stop()\n    if (scope && scope.active) {\n      remove(scope.effects, effect)\n    }\n  }\n\n  if (once && cb) {\n    const _cb = cb\n    cb = (...args) => {\n      _cb(...args)\n      watchHandle()\n    }\n  }\n\n  let oldValue: any = isMultiSource\n    ? new Array((source as []).length).fill(INITIAL_WATCHER_VALUE)\n    : INITIAL_WATCHER_VALUE\n\n  const job = (immediateFirstRun?: boolean) => {\n    if (\n      !(effect.flags & EffectFlags.ACTIVE) ||\n      (!effect.dirty && !immediateFirstRun)\n    ) {\n      return\n    }\n    if (cb) {\n      // watch(source, cb)\n      const newValue = effect.run()\n      if (\n        deep ||\n        forceTrigger ||\n        (isMultiSource\n          ? (newValue as any[]).some((v, i) => hasChanged(v, oldValue[i]))\n          : hasChanged(newValue, oldValue))\n      ) {\n        // cleanup before running cb again\n        if (cleanup) {\n          cleanup()\n        }\n        const currentWatcher = activeWatcher\n        activeWatcher = effect\n        try {\n          const args = [\n            newValue,\n            // pass undefined as the old value when it's changed for the first time\n            oldValue === INITIAL_WATCHER_VALUE\n              ? undefined\n              : isMultiSource && oldValue[0] === INITIAL_WATCHER_VALUE\n                ? []\n                : oldValue,\n            boundCleanup,\n          ]\n          oldValue = newValue\n          call\n            ? call(cb!, WatchErrorCodes.WATCH_CALLBACK, args)\n            : // @ts-expect-error\n              cb!(...args)\n        } finally {\n          activeWatcher = currentWatcher\n        }\n      }\n    } else {\n      // watchEffect\n      effect.run()\n    }\n  }\n\n  if (augmentJob) {\n    augmentJob(job)\n  }\n\n  effect = new ReactiveEffect(getter)\n\n  effect.scheduler = scheduler\n    ? () => scheduler(job, false)\n    : (job as EffectScheduler)\n\n  boundCleanup = fn => onWatcherCleanup(fn, false, effect)\n\n  cleanup = effect.onStop = () => {\n    const cleanups = cleanupMap.get(effect)\n    if (cleanups) {\n      if (call) {\n        call(cleanups, WatchErrorCodes.WATCH_CLEANUP)\n      } else {\n        for (const cleanup of cleanups) cleanup()\n      }\n      cleanupMap.delete(effect)\n    }\n  }\n\n  if (__DEV__) {\n    effect.onTrack = options.onTrack\n    effect.onTrigger = options.onTrigger\n  }\n\n  // initial run\n  if (cb) {\n    if (immediate) {\n      job(true)\n    } else {\n      oldValue = effect.run()\n    }\n  } else if (scheduler) {\n    scheduler(job.bind(null, true), true)\n  } else {\n    effect.run()\n  }\n\n  watchHandle.pause = effect.pause.bind(effect)\n  watchHandle.resume = effect.resume.bind(effect)\n  watchHandle.stop = watchHandle\n\n  return watchHandle\n}\n\nexport function traverse(\n  value: unknown,\n  depth: number = Infinity,\n  seen?: Map<unknown, number>,\n): unknown {\n  if (depth <= 0 || !isObject(value) || (value as any)[ReactiveFlags.SKIP]) {\n    return value\n  }\n\n  seen = seen || new Map()\n  if ((seen.get(value) || 0) >= depth) {\n    return value\n  }\n  seen.set(value, depth)\n  depth--\n  if (isRef(value)) {\n    traverse(value.value, depth, seen)\n  } else if (isArray(value)) {\n    for (let i = 0; i < value.length; i++) {\n      traverse(value[i], depth, seen)\n    }\n  } else if (isSet(value) || isMap(value)) {\n    value.forEach((v: any) => {\n      traverse(v, depth, seen)\n    })\n  } else if (isPlainObject(value)) {\n    for (const key in value) {\n      traverse(value[key], depth, seen)\n    }\n    for (const key of Object.getOwnPropertySymbols(value)) {\n      if (Object.prototype.propertyIsEnumerable.call(value, key)) {\n        traverse(value[key as any], depth, seen)\n      }\n    }\n  }\n  return value\n}\n"
  },
  {
    "path": "packages/runtime-core/LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2018-present, Yuxi (Evan) You\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "packages/runtime-core/README.md",
    "content": "# @vue/runtime-core\n\n> This package is published only for typing and building custom renderers. It is NOT meant to be used in applications.\n\nFor full exposed APIs, see `src/index.ts`.\n\n## Building a Custom Renderer\n\n```ts\nimport { createRenderer } from '@vue/runtime-core'\n\nconst { render, createApp } = createRenderer({\n  patchProp,\n  insert,\n  remove,\n  createElement,\n  // ...\n})\n\n// `render` is the low-level API\n// `createApp` returns an app instance with configurable context shared\n// by the entire app tree.\nexport { render, createApp }\n\nexport * from '@vue/runtime-core'\n```\n\nSee `@vue/runtime-dom` for how a DOM-targeting renderer is implemented.\n"
  },
  {
    "path": "packages/runtime-core/__tests__/apiAsyncComponent.spec.ts",
    "content": "import {\n  type Component,\n  KeepAlive,\n  Suspense,\n  defineAsyncComponent,\n  h,\n  nextTick,\n  ref,\n} from '../src'\nimport { createApp, nodeOps, serializeInner } from '@vue/runtime-test'\nimport { onActivated } from '../src/components/KeepAlive'\n\nconst timeout = (n: number = 0) => new Promise(r => setTimeout(r, n))\n\ndescribe('api: defineAsyncComponent', () => {\n  test('simple usage', async () => {\n    let resolve: (comp: Component) => void\n    const Foo = defineAsyncComponent(\n      () =>\n        new Promise(r => {\n          resolve = r as any\n        }),\n    )\n\n    const toggle = ref(true)\n    const root = nodeOps.createElement('div')\n    createApp({\n      render: () => (toggle.value ? h(Foo) : null),\n    }).mount(root)\n\n    expect(serializeInner(root)).toBe('<!---->')\n\n    resolve!(() => 'resolved')\n    // first time resolve, wait for macro task since there are multiple\n    // microtasks / .then() calls\n    await timeout()\n    expect(serializeInner(root)).toBe('resolved')\n\n    toggle.value = false\n    await nextTick()\n    expect(serializeInner(root)).toBe('<!---->')\n\n    // already resolved component should update on nextTick\n    toggle.value = true\n    await nextTick()\n    expect(serializeInner(root)).toBe('resolved')\n  })\n\n  test('with loading component', async () => {\n    let resolve: (comp: Component) => void\n    const Foo = defineAsyncComponent({\n      loader: () =>\n        new Promise(r => {\n          resolve = r as any\n        }),\n      loadingComponent: () => 'loading',\n      delay: 1, // defaults to 200\n    })\n\n    const toggle = ref(true)\n    const root = nodeOps.createElement('div')\n    createApp({\n      render: () => (toggle.value ? h(Foo) : null),\n    }).mount(root)\n\n    // due to the delay, initial mount should be empty\n    expect(serializeInner(root)).toBe('<!---->')\n\n    // loading show up after delay\n    await timeout(1)\n    expect(serializeInner(root)).toBe('loading')\n\n    resolve!(() => 'resolved')\n    await timeout()\n    expect(serializeInner(root)).toBe('resolved')\n\n    toggle.value = false\n    await nextTick()\n    expect(serializeInner(root)).toBe('<!---->')\n\n    // already resolved component should update on nextTick without loading\n    // state\n    toggle.value = true\n    await nextTick()\n    expect(serializeInner(root)).toBe('resolved')\n  })\n\n  test('with loading component + explicit delay (0)', async () => {\n    let resolve: (comp: Component) => void\n    const Foo = defineAsyncComponent({\n      loader: () =>\n        new Promise(r => {\n          resolve = r as any\n        }),\n      loadingComponent: () => 'loading',\n      delay: 0,\n    })\n\n    const toggle = ref(true)\n    const root = nodeOps.createElement('div')\n    createApp({\n      render: () => (toggle.value ? h(Foo) : null),\n    }).mount(root)\n\n    // with delay: 0, should show loading immediately\n    expect(serializeInner(root)).toBe('loading')\n\n    resolve!(() => 'resolved')\n    await timeout()\n    expect(serializeInner(root)).toBe('resolved')\n\n    toggle.value = false\n    await nextTick()\n    expect(serializeInner(root)).toBe('<!---->')\n\n    // already resolved component should update on nextTick without loading\n    // state\n    toggle.value = true\n    await nextTick()\n    expect(serializeInner(root)).toBe('resolved')\n  })\n\n  test('error without error component', async () => {\n    let resolve: (comp: Component) => void\n    let reject: (e: Error) => void\n    const Foo = defineAsyncComponent(\n      () =>\n        new Promise((_resolve, _reject) => {\n          resolve = _resolve as any\n          reject = _reject\n        }),\n    )\n\n    const toggle = ref(true)\n    const root = nodeOps.createElement('div')\n    const app = createApp({\n      render: () => (toggle.value ? h(Foo) : null),\n    })\n\n    const handler = (app.config.errorHandler = vi.fn())\n\n    app.mount(root)\n    expect(serializeInner(root)).toBe('<!---->')\n\n    const err = new Error('foo')\n    reject!(err)\n    await timeout()\n    expect(handler).toHaveBeenCalled()\n    expect(handler.mock.calls[0][0]).toBe(err)\n    expect(serializeInner(root)).toBe('<!---->')\n\n    toggle.value = false\n    await nextTick()\n    expect(serializeInner(root)).toBe('<!---->')\n\n    // errored out on previous load, toggle and mock success this time\n    toggle.value = true\n    await nextTick()\n    expect(serializeInner(root)).toBe('<!---->')\n\n    // should render this time\n    resolve!(() => 'resolved')\n    await timeout()\n    expect(serializeInner(root)).toBe('resolved')\n  })\n\n  test('error with error component', async () => {\n    let resolve: (comp: Component) => void\n    let reject: (e: Error) => void\n    const Foo = defineAsyncComponent({\n      loader: () =>\n        new Promise((_resolve, _reject) => {\n          resolve = _resolve as any\n          reject = _reject\n        }),\n      errorComponent: (props: { error: Error }) => props.error.message,\n    })\n\n    const toggle = ref(true)\n    const root = nodeOps.createElement('div')\n    const app = createApp({\n      render: () => (toggle.value ? h(Foo) : null),\n    })\n\n    const handler = (app.config.errorHandler = vi.fn())\n\n    app.mount(root)\n    expect(serializeInner(root)).toBe('<!---->')\n\n    const err = new Error('errored out')\n    reject!(err)\n    await timeout()\n    expect(handler).toHaveBeenCalled()\n    expect(serializeInner(root)).toBe('errored out')\n\n    toggle.value = false\n    await nextTick()\n    expect(serializeInner(root)).toBe('<!---->')\n\n    // errored out on previous load, toggle and mock success this time\n    toggle.value = true\n    await nextTick()\n    expect(serializeInner(root)).toBe('<!---->')\n\n    // should render this time\n    resolve!(() => 'resolved')\n    await timeout()\n    expect(serializeInner(root)).toBe('resolved')\n  })\n\n  // #2129\n  test('error with error component, without global handler', async () => {\n    let resolve: (comp: Component) => void\n    let reject: (e: Error) => void\n    const Foo = defineAsyncComponent({\n      loader: () =>\n        new Promise((_resolve, _reject) => {\n          resolve = _resolve as any\n          reject = _reject\n        }),\n      errorComponent: (props: { error: Error }) => props.error.message,\n    })\n\n    const toggle = ref(true)\n    const root = nodeOps.createElement('div')\n    const app = createApp({\n      render: () => (toggle.value ? h(Foo) : null),\n    })\n\n    app.mount(root)\n    expect(serializeInner(root)).toBe('<!---->')\n\n    const err = new Error('errored out')\n    reject!(err)\n    await timeout()\n    expect(serializeInner(root)).toBe('errored out')\n    expect(\n      'Unhandled error during execution of async component loader',\n    ).toHaveBeenWarned()\n\n    toggle.value = false\n    await nextTick()\n    expect(serializeInner(root)).toBe('<!---->')\n\n    // errored out on previous load, toggle and mock success this time\n    toggle.value = true\n    await nextTick()\n    expect(serializeInner(root)).toBe('<!---->')\n\n    // should render this time\n    resolve!(() => 'resolved')\n    await timeout()\n    expect(serializeInner(root)).toBe('resolved')\n  })\n\n  test('error with error + loading components', async () => {\n    let resolve: (comp: Component) => void\n    let reject: (e: Error) => void\n    const Foo = defineAsyncComponent({\n      loader: () =>\n        new Promise((_resolve, _reject) => {\n          resolve = _resolve as any\n          reject = _reject\n        }),\n      errorComponent: (props: { error: Error }) => props.error.message,\n      loadingComponent: () => 'loading',\n      delay: 1,\n    })\n\n    const toggle = ref(true)\n    const root = nodeOps.createElement('div')\n    const app = createApp({\n      render: () => (toggle.value ? h(Foo) : null),\n    })\n\n    const handler = (app.config.errorHandler = vi.fn())\n\n    app.mount(root)\n\n    // due to the delay, initial mount should be empty\n    expect(serializeInner(root)).toBe('<!---->')\n\n    // loading show up after delay\n    await timeout(1)\n    expect(serializeInner(root)).toBe('loading')\n\n    const err = new Error('errored out')\n    reject!(err)\n    await timeout()\n    expect(handler).toHaveBeenCalled()\n    expect(serializeInner(root)).toBe('errored out')\n\n    toggle.value = false\n    await nextTick()\n    expect(serializeInner(root)).toBe('<!---->')\n\n    // errored out on previous load, toggle and mock success this time\n    toggle.value = true\n    await nextTick()\n    expect(serializeInner(root)).toBe('<!---->')\n\n    // loading show up after delay\n    await timeout(1)\n    expect(serializeInner(root)).toBe('loading')\n\n    // should render this time\n    resolve!(() => 'resolved')\n    await timeout()\n    expect(serializeInner(root)).toBe('resolved')\n  })\n\n  test('timeout without error component', async () => {\n    let resolve: (comp: Component) => void\n    const Foo = defineAsyncComponent({\n      loader: () =>\n        new Promise(_resolve => {\n          resolve = _resolve as any\n        }),\n      timeout: 1,\n    })\n\n    const root = nodeOps.createElement('div')\n    const app = createApp({\n      render: () => h(Foo),\n    })\n\n    const handler = vi.fn()\n    app.config.errorHandler = handler\n\n    app.mount(root)\n    expect(serializeInner(root)).toBe('<!---->')\n\n    await timeout(1)\n    expect(handler).toHaveBeenCalled()\n    expect(handler.mock.calls[0][0].message).toMatch(\n      `Async component timed out after 1ms.`,\n    )\n    expect(serializeInner(root)).toBe('<!---->')\n\n    // if it resolved after timeout, should still work\n    resolve!(() => 'resolved')\n    await timeout()\n    expect(serializeInner(root)).toBe('resolved')\n  })\n\n  test('timeout with error component', async () => {\n    let resolve: (comp: Component) => void\n    const Foo = defineAsyncComponent({\n      loader: () =>\n        new Promise(_resolve => {\n          resolve = _resolve as any\n        }),\n      timeout: 1,\n      errorComponent: () => 'timed out',\n    })\n\n    const root = nodeOps.createElement('div')\n    const app = createApp({\n      render: () => h(Foo),\n    })\n\n    const handler = (app.config.errorHandler = vi.fn())\n\n    app.mount(root)\n    expect(serializeInner(root)).toBe('<!---->')\n\n    await timeout(1)\n    expect(handler).toHaveBeenCalled()\n    expect(serializeInner(root)).toBe('timed out')\n\n    // if it resolved after timeout, should still work\n    resolve!(() => 'resolved')\n    await timeout()\n    expect(serializeInner(root)).toBe('resolved')\n  })\n\n  test('timeout with error + loading components', async () => {\n    let resolve: (comp: Component) => void\n    const Foo = defineAsyncComponent({\n      loader: () =>\n        new Promise(_resolve => {\n          resolve = _resolve as any\n        }),\n      delay: 1,\n      timeout: 16,\n      errorComponent: () => 'timed out',\n      loadingComponent: () => 'loading',\n    })\n\n    const root = nodeOps.createElement('div')\n    const app = createApp({\n      render: () => h(Foo),\n    })\n    const handler = (app.config.errorHandler = vi.fn())\n    app.mount(root)\n    expect(serializeInner(root)).toBe('<!---->')\n    await timeout(1)\n    expect(serializeInner(root)).toBe('loading')\n\n    await timeout(16)\n    expect(serializeInner(root)).toBe('timed out')\n    expect(handler).toHaveBeenCalled()\n\n    resolve!(() => 'resolved')\n    await timeout()\n    expect(serializeInner(root)).toBe('resolved')\n  })\n\n  test('timeout without error component, but with loading component', async () => {\n    let resolve: (comp: Component) => void\n    const Foo = defineAsyncComponent({\n      loader: () =>\n        new Promise(_resolve => {\n          resolve = _resolve as any\n        }),\n      delay: 1,\n      timeout: 16,\n      loadingComponent: () => 'loading',\n    })\n\n    const root = nodeOps.createElement('div')\n    const app = createApp({\n      render: () => h(Foo),\n    })\n    const handler = vi.fn()\n    app.config.errorHandler = handler\n    app.mount(root)\n    expect(serializeInner(root)).toBe('<!---->')\n    await timeout(1)\n    expect(serializeInner(root)).toBe('loading')\n\n    await timeout(16)\n    expect(handler).toHaveBeenCalled()\n    expect(handler.mock.calls[0][0].message).toMatch(\n      `Async component timed out after 16ms.`,\n    )\n    // should still display loading\n    expect(serializeInner(root)).toBe('loading')\n\n    resolve!(() => 'resolved')\n    await timeout()\n    expect(serializeInner(root)).toBe('resolved')\n  })\n\n  test('with suspense', async () => {\n    let resolve: (comp: Component) => void\n    const Foo = defineAsyncComponent(\n      () =>\n        new Promise(_resolve => {\n          resolve = _resolve as any\n        }),\n    )\n\n    const root = nodeOps.createElement('div')\n    const app = createApp({\n      render: () =>\n        h(Suspense, null, {\n          default: () => h('div', [h(Foo), ' & ', h(Foo)]),\n          fallback: () => 'loading',\n        }),\n    })\n\n    app.mount(root)\n    expect(serializeInner(root)).toBe('loading')\n\n    resolve!(() => 'resolved')\n    await timeout()\n    expect(serializeInner(root)).toBe('<div>resolved & resolved</div>')\n  })\n\n  test('suspensible: false', async () => {\n    let resolve: (comp: Component) => void\n    const Foo = defineAsyncComponent({\n      loader: () =>\n        new Promise(_resolve => {\n          resolve = _resolve as any\n        }),\n      suspensible: false,\n    })\n\n    const root = nodeOps.createElement('div')\n    const app = createApp({\n      render: () =>\n        h(Suspense, null, {\n          default: () => h('div', [h(Foo), ' & ', h(Foo)]),\n          fallback: () => 'loading',\n        }),\n    })\n\n    app.mount(root)\n    // should not show suspense fallback\n    expect(serializeInner(root)).toBe('<div><!----> & <!----></div>')\n\n    resolve!(() => 'resolved')\n    await timeout()\n    expect(serializeInner(root)).toBe('<div>resolved & resolved</div>')\n  })\n\n  test('suspense with error handling', async () => {\n    let reject: (e: Error) => void\n    const Foo = defineAsyncComponent(\n      () =>\n        new Promise((_resolve, _reject) => {\n          reject = _reject\n        }),\n    )\n\n    const root = nodeOps.createElement('div')\n    const app = createApp({\n      render: () =>\n        h(Suspense, null, {\n          default: () => h('div', [h(Foo), ' & ', h(Foo)]),\n          fallback: () => 'loading',\n        }),\n    })\n\n    const handler = (app.config.errorHandler = vi.fn())\n    app.mount(root)\n    expect(serializeInner(root)).toBe('loading')\n\n    reject!(new Error('no'))\n    await timeout()\n    expect(handler).toHaveBeenCalled()\n    expect(serializeInner(root)).toBe('<div><!----> & <!----></div>')\n  })\n\n  test('retry (success)', async () => {\n    let loaderCallCount = 0\n    let resolve: (comp: Component) => void\n    let reject: (e: Error) => void\n\n    const Foo = defineAsyncComponent({\n      loader: () => {\n        loaderCallCount++\n        return new Promise((_resolve, _reject) => {\n          resolve = _resolve as any\n          reject = _reject\n        })\n      },\n      onError(error, retry, fail) {\n        if (error.message.match(/foo/)) {\n          retry()\n        } else {\n          fail()\n        }\n      },\n    })\n\n    const root = nodeOps.createElement('div')\n    const app = createApp({\n      render: () => h(Foo),\n    })\n\n    const handler = (app.config.errorHandler = vi.fn())\n    app.mount(root)\n    expect(serializeInner(root)).toBe('<!---->')\n    expect(loaderCallCount).toBe(1)\n\n    const err = new Error('foo')\n    reject!(err)\n    await timeout()\n    expect(handler).not.toHaveBeenCalled()\n    expect(loaderCallCount).toBe(2)\n    expect(serializeInner(root)).toBe('<!---->')\n\n    // should render this time\n    resolve!(() => 'resolved')\n    await timeout()\n    expect(handler).not.toHaveBeenCalled()\n    expect(serializeInner(root)).toBe('resolved')\n  })\n\n  test('retry (skipped)', async () => {\n    let loaderCallCount = 0\n    let reject: (e: Error) => void\n\n    const Foo = defineAsyncComponent({\n      loader: () => {\n        loaderCallCount++\n        return new Promise((_resolve, _reject) => {\n          reject = _reject\n        })\n      },\n      onError(error, retry, fail) {\n        if (error.message.match(/bar/)) {\n          retry()\n        } else {\n          fail()\n        }\n      },\n    })\n\n    const root = nodeOps.createElement('div')\n    const app = createApp({\n      render: () => h(Foo),\n    })\n\n    const handler = (app.config.errorHandler = vi.fn())\n    app.mount(root)\n    expect(serializeInner(root)).toBe('<!---->')\n    expect(loaderCallCount).toBe(1)\n\n    const err = new Error('foo')\n    reject!(err)\n    await timeout()\n    // should fail because retryWhen returns false\n    expect(handler).toHaveBeenCalled()\n    expect(handler.mock.calls[0][0]).toBe(err)\n    expect(loaderCallCount).toBe(1)\n    expect(serializeInner(root)).toBe('<!---->')\n  })\n\n  test('retry (fail w/ max retry attempts)', async () => {\n    let loaderCallCount = 0\n    let reject: (e: Error) => void\n\n    const Foo = defineAsyncComponent({\n      loader: () => {\n        loaderCallCount++\n        return new Promise((_resolve, _reject) => {\n          reject = _reject\n        })\n      },\n      onError(error, retry, fail, attempts) {\n        if (error.message.match(/foo/) && attempts <= 1) {\n          retry()\n        } else {\n          fail()\n        }\n      },\n    })\n\n    const root = nodeOps.createElement('div')\n    const app = createApp({\n      render: () => h(Foo),\n    })\n\n    const handler = (app.config.errorHandler = vi.fn())\n    app.mount(root)\n    expect(serializeInner(root)).toBe('<!---->')\n    expect(loaderCallCount).toBe(1)\n\n    // first retry\n    const err = new Error('foo')\n    reject!(err)\n    await timeout()\n    expect(handler).not.toHaveBeenCalled()\n    expect(loaderCallCount).toBe(2)\n    expect(serializeInner(root)).toBe('<!---->')\n\n    // 2nd retry, should fail due to reaching maxRetries\n    reject!(err)\n    await timeout()\n    expect(handler).toHaveBeenCalled()\n    expect(handler.mock.calls[0][0]).toBe(err)\n    expect(loaderCallCount).toBe(2)\n    expect(serializeInner(root)).toBe('<!---->')\n  })\n\n  test('template ref forwarding', async () => {\n    let resolve: (comp: Component) => void\n    const Foo = defineAsyncComponent(\n      () =>\n        new Promise(r => {\n          resolve = r as any\n        }),\n    )\n\n    const fooRef = ref<any>(null)\n    const toggle = ref(true)\n    const root = nodeOps.createElement('div')\n    createApp({\n      render: () => (toggle.value ? h(Foo, { ref: fooRef }) : null),\n    }).mount(root)\n\n    expect(serializeInner(root)).toBe('<!---->')\n    expect(fooRef.value).toBe(null)\n\n    resolve!({\n      data() {\n        return {\n          id: 'foo',\n        }\n      },\n      render: () => 'resolved',\n    })\n    // first time resolve, wait for macro task since there are multiple\n    // microtasks / .then() calls\n    await timeout()\n    expect(serializeInner(root)).toBe('resolved')\n    expect(fooRef.value.id).toBe('foo')\n\n    toggle.value = false\n    await nextTick()\n    expect(serializeInner(root)).toBe('<!---->')\n    expect(fooRef.value).toBe(null)\n\n    // already resolved component should update on nextTick\n    toggle.value = true\n    await nextTick()\n    expect(serializeInner(root)).toBe('resolved')\n    expect(fooRef.value.id).toBe('foo')\n  })\n\n  // #3188\n  test('the forwarded template ref should always exist when doing multi patching', async () => {\n    let resolve: (comp: Component) => void\n    const Foo = defineAsyncComponent(\n      () =>\n        new Promise(r => {\n          resolve = r as any\n        }),\n    )\n\n    const fooRef = ref<any>(null)\n    const toggle = ref(true)\n    const updater = ref(0)\n\n    const root = nodeOps.createElement('div')\n    createApp({\n      render: () =>\n        toggle.value ? [h(Foo, { ref: fooRef }), updater.value] : null,\n    }).mount(root)\n\n    expect(serializeInner(root)).toBe('<!---->0')\n    expect(fooRef.value).toBe(null)\n\n    resolve!({\n      data() {\n        return {\n          id: 'foo',\n        }\n      },\n      render: () => 'resolved',\n    })\n\n    await timeout()\n    expect(serializeInner(root)).toBe('resolved0')\n    expect(fooRef.value.id).toBe('foo')\n\n    updater.value++\n    await nextTick()\n    expect(serializeInner(root)).toBe('resolved1')\n    expect(fooRef.value.id).toBe('foo')\n\n    toggle.value = false\n    await nextTick()\n    expect(serializeInner(root)).toBe('<!---->')\n    expect(fooRef.value).toBe(null)\n  })\n\n  test('vnode hooks on async wrapper', async () => {\n    let resolve: (comp: Component) => void\n    const Foo = defineAsyncComponent(\n      () =>\n        new Promise(r => {\n          resolve = r as any\n        }),\n    )\n    const updater = ref(0)\n\n    const vnodeHooks = {\n      onVnodeBeforeMount: vi.fn(),\n      onVnodeMounted: vi.fn(),\n      onVnodeBeforeUpdate: vi.fn(),\n      onVnodeUpdated: vi.fn(),\n      onVnodeBeforeUnmount: vi.fn(),\n      onVnodeUnmounted: vi.fn(),\n    }\n\n    const toggle = ref(true)\n\n    const root = nodeOps.createElement('div')\n    createApp({\n      render: () => (toggle.value ? [h(Foo, vnodeHooks), updater.value] : null),\n    }).mount(root)\n\n    expect(serializeInner(root)).toBe('<!---->0')\n\n    resolve!({\n      data() {\n        return {\n          id: 'foo',\n        }\n      },\n      render: () => 'resolved',\n    })\n\n    await timeout()\n    expect(serializeInner(root)).toBe('resolved0')\n    expect(vnodeHooks.onVnodeBeforeMount).toHaveBeenCalledTimes(1)\n    expect(vnodeHooks.onVnodeMounted).toHaveBeenCalledTimes(1)\n\n    updater.value++\n    await nextTick()\n    expect(serializeInner(root)).toBe('resolved1')\n    expect(vnodeHooks.onVnodeBeforeUpdate).toHaveBeenCalledTimes(1)\n    expect(vnodeHooks.onVnodeUpdated).toHaveBeenCalledTimes(1)\n\n    toggle.value = false\n    await nextTick()\n    expect(serializeInner(root)).toBe('<!---->')\n    expect(vnodeHooks.onVnodeBeforeUnmount).toHaveBeenCalledTimes(1)\n    expect(vnodeHooks.onVnodeUnmounted).toHaveBeenCalledTimes(1)\n  })\n\n  test('with KeepAlive', async () => {\n    const spy = vi.fn()\n    let resolve: (comp: Component) => void\n\n    const Foo = defineAsyncComponent(\n      () =>\n        new Promise(r => {\n          resolve = r as any\n        }),\n    )\n\n    const Bar = defineAsyncComponent(() => Promise.resolve(() => 'Bar'))\n\n    const toggle = ref(true)\n    const root = nodeOps.createElement('div')\n    const app = createApp({\n      render: () => h(KeepAlive, [toggle.value ? h(Foo) : h(Bar)]),\n    })\n\n    app.mount(root)\n    await nextTick()\n\n    resolve!({\n      setup() {\n        onActivated(() => {\n          spy()\n        })\n        return () => 'Foo'\n      },\n    })\n\n    await timeout()\n    expect(serializeInner(root)).toBe('Foo')\n    expect(spy).toBeCalledTimes(1)\n\n    toggle.value = false\n    await timeout()\n    expect(serializeInner(root)).toBe('Bar')\n  })\n\n  // 11916\n  test('with KeepAlive + include', async () => {\n    const spy = vi.fn()\n    let resolve: (comp: Component) => void\n\n    const Foo = defineAsyncComponent(\n      () =>\n        new Promise(r => {\n          resolve = r as any\n        }),\n    )\n\n    const root = nodeOps.createElement('div')\n    const app = createApp({\n      render: () => h(KeepAlive, { include: 'Foo' }, [h(Foo)]),\n    })\n\n    app.mount(root)\n    await nextTick()\n\n    resolve!({\n      name: 'Foo',\n      setup() {\n        onActivated(spy)\n        return () => 'Foo'\n      },\n    })\n\n    await timeout()\n    expect(serializeInner(root)).toBe('Foo')\n    expect(spy).toBeCalledTimes(1)\n  })\n})\n"
  },
  {
    "path": "packages/runtime-core/__tests__/apiCreateApp.spec.ts",
    "content": "import {\n  type Plugin,\n  createApp,\n  defineComponent,\n  getCurrentInstance,\n  h,\n  inject,\n  nextTick,\n  nodeOps,\n  onMounted,\n  provide,\n  ref,\n  resolveComponent,\n  resolveDirective,\n  serializeInner,\n  watch,\n  withDirectives,\n} from '@vue/runtime-test'\n\ndescribe('api: createApp', () => {\n  test('mount', () => {\n    const Comp = defineComponent({\n      props: {\n        count: {\n          default: 0,\n        },\n      },\n      setup(props) {\n        return () => props.count\n      },\n    })\n\n    const root1 = nodeOps.createElement('div')\n    createApp(Comp).mount(root1)\n    expect(serializeInner(root1)).toBe(`0`)\n    //#5571 mount multiple apps to the same host element\n    createApp(Comp).mount(root1)\n    expect(\n      `There is already an app instance mounted on the host container`,\n    ).toHaveBeenWarned()\n\n    // mount with props\n    const root2 = nodeOps.createElement('div')\n    const app2 = createApp(Comp, { count: 1 })\n    app2.mount(root2)\n    expect(serializeInner(root2)).toBe(`1`)\n\n    // remount warning\n    const root3 = nodeOps.createElement('div')\n    app2.mount(root3)\n    expect(serializeInner(root3)).toBe(``)\n    expect(`already been mounted`).toHaveBeenWarned()\n  })\n\n  test('unmount', () => {\n    const Comp = defineComponent({\n      props: {\n        count: {\n          default: 0,\n        },\n      },\n      setup(props) {\n        return () => props.count\n      },\n    })\n\n    const root = nodeOps.createElement('div')\n    const app = createApp(Comp)\n\n    // warning\n    app.unmount()\n    expect(`that is not mounted`).toHaveBeenWarned()\n\n    app.mount(root)\n\n    app.unmount()\n    expect(serializeInner(root)).toBe(``)\n  })\n\n  test('provide', () => {\n    const Root = {\n      setup() {\n        // test override\n        provide('foo', 3)\n        return () => h(Child)\n      },\n    }\n\n    const Child = {\n      setup() {\n        const foo = inject('foo')\n        const bar = inject('bar')\n        try {\n          inject('__proto__')\n        } catch (e: any) {}\n        return () => `${foo},${bar}`\n      },\n    }\n\n    const app = createApp(Root)\n    app.provide('foo', 1)\n    app.provide('bar', 2)\n\n    const root = nodeOps.createElement('div')\n    app.mount(root)\n    expect(serializeInner(root)).toBe(`3,2`)\n    expect('[Vue warn]: injection \"__proto__\" not found.').toHaveBeenWarned()\n\n    const app2 = createApp(Root)\n    app2.provide('bar', 1)\n    app2.provide('bar', 2)\n    expect(`App already provides property with key \"bar\".`).toHaveBeenWarned()\n  })\n\n  test('runWithContext', () => {\n    const app = createApp({\n      setup() {\n        provide('foo', 'should not be seen')\n\n        // nested createApp\n        const childApp = createApp({\n          setup() {\n            provide('foo', 'foo from child')\n          },\n        })\n\n        childApp.provide('foo', 2)\n        expect(childApp.runWithContext(() => inject('foo'))).toBe(2)\n\n        return () => h('div')\n      },\n    })\n    app.provide('foo', 1)\n\n    expect(app.runWithContext(() => inject('foo'))).toBe(1)\n    const root = nodeOps.createElement('div')\n    app.mount(root)\n\n    expect(\n      app.runWithContext(() => {\n        app.runWithContext(() => {})\n        return inject('foo')\n      }),\n    ).toBe(1)\n\n    // ensure the context is restored\n    inject('foo')\n    expect('inject() can only be used inside setup').toHaveBeenWarned()\n  })\n\n  test('component', () => {\n    const Root = {\n      // local override\n      components: {\n        BarBaz: () => 'barbaz-local!',\n      },\n      setup() {\n        // resolve in setup\n        const FooBar = resolveComponent('foo-bar')\n        return () => {\n          // resolve in render\n          const BarBaz = resolveComponent('bar-baz')\n          return h('div', [h(FooBar), h(BarBaz)])\n        }\n      },\n    }\n\n    const app = createApp(Root)\n\n    const FooBar = () => 'foobar!'\n    app.component('FooBar', FooBar)\n    expect(app.component('FooBar')).toBe(FooBar)\n\n    app.component('BarBaz', () => 'barbaz!')\n\n    app.component('BarBaz', () => 'barbaz!')\n    expect(\n      'Component \"BarBaz\" has already been registered in target app.',\n    ).toHaveBeenWarnedTimes(1)\n\n    const root = nodeOps.createElement('div')\n    app.mount(root)\n    expect(serializeInner(root)).toBe(`<div>foobar!barbaz-local!</div>`)\n  })\n\n  test('directive', () => {\n    const spy1 = vi.fn()\n    const spy2 = vi.fn()\n    const spy3 = vi.fn()\n\n    const Root = {\n      // local override\n      directives: {\n        BarBaz: { mounted: spy3 },\n      },\n      setup() {\n        // resolve in setup\n        const FooBar = resolveDirective('foo-bar')\n        return () => {\n          // resolve in render\n          const BarBaz = resolveDirective('bar-baz')\n          return withDirectives(h('div'), [[FooBar], [BarBaz]])\n        }\n      },\n    }\n\n    const app = createApp(Root)\n\n    const FooBar = { mounted: spy1 }\n    app.directive('FooBar', FooBar)\n    expect(app.directive('FooBar')).toBe(FooBar)\n\n    app.directive('BarBaz', {\n      mounted: spy2,\n    })\n\n    app.directive('BarBaz', {\n      mounted: spy2,\n    })\n    expect(\n      'Directive \"BarBaz\" has already been registered in target app.',\n    ).toHaveBeenWarnedTimes(1)\n\n    const root = nodeOps.createElement('div')\n    app.mount(root)\n    expect(spy1).toHaveBeenCalled()\n    expect(spy2).not.toHaveBeenCalled()\n    expect(spy3).toHaveBeenCalled()\n\n    app.directive('bind', FooBar)\n    expect(\n      `Do not use built-in directive ids as custom directive id: bind`,\n    ).toHaveBeenWarned()\n  })\n\n  test('mixin', () => {\n    const calls: string[] = []\n    const mixinA = {\n      data() {\n        return {\n          a: 1,\n        }\n      },\n      created(this: any) {\n        calls.push('mixinA created')\n        expect(this.a).toBe(1)\n        expect(this.b).toBe(2)\n        expect(this.c).toBe(3)\n      },\n      mounted() {\n        calls.push('mixinA mounted')\n      },\n    }\n    const mixinB = {\n      name: 'mixinB',\n      data() {\n        return {\n          b: 2,\n        }\n      },\n      created(this: any) {\n        calls.push('mixinB created')\n        expect(this.a).toBe(1)\n        expect(this.b).toBe(2)\n        expect(this.c).toBe(3)\n      },\n      mounted() {\n        calls.push('mixinB mounted')\n      },\n    }\n    const Comp = {\n      data() {\n        return {\n          c: 3,\n        }\n      },\n      created(this: any) {\n        calls.push('comp created')\n        expect(this.a).toBe(1)\n        expect(this.b).toBe(2)\n        expect(this.c).toBe(3)\n      },\n      mounted() {\n        calls.push('comp mounted')\n      },\n      render(this: any) {\n        return `${this.a}${this.b}${this.c}`\n      },\n    }\n\n    const app = createApp(Comp)\n    app.mixin(mixinA)\n    app.mixin(mixinB)\n\n    app.mixin(mixinA)\n    app.mixin(mixinB)\n    expect(\n      'Mixin has already been applied to target app',\n    ).toHaveBeenWarnedTimes(2)\n    expect(\n      'Mixin has already been applied to target app: mixinB',\n    ).toHaveBeenWarnedTimes(1)\n\n    const root = nodeOps.createElement('div')\n    app.mount(root)\n\n    expect(serializeInner(root)).toBe(`123`)\n    expect(calls).toEqual([\n      'mixinA created',\n      'mixinB created',\n      'comp created',\n      'mixinA mounted',\n      'mixinB mounted',\n      'comp mounted',\n    ])\n  })\n\n  test('use', () => {\n    const PluginA: Plugin = app => app.provide('foo', 1)\n    const PluginB: Plugin = {\n      install: (app, arg1, arg2) => app.provide('bar', arg1 + arg2),\n    }\n    class PluginC {\n      someProperty = {}\n      static install() {\n        app.provide('baz', 2)\n      }\n    }\n    const PluginD: any = undefined\n\n    const Root = {\n      setup() {\n        const foo = inject('foo')\n        const bar = inject('bar')\n        return () => `${foo},${bar}`\n      },\n    }\n\n    const app = createApp(Root)\n    app.use(PluginA)\n    app.use(PluginB, 1, 1)\n    app.use(PluginC)\n\n    const root = nodeOps.createElement('div')\n    app.mount(root)\n    expect(serializeInner(root)).toBe(`1,2`)\n\n    app.use(PluginA)\n    expect(\n      `Plugin has already been applied to target app`,\n    ).toHaveBeenWarnedTimes(1)\n\n    app.use(PluginD)\n    expect(\n      `A plugin must either be a function or an object with an \"install\" ` +\n        `function.`,\n    ).toHaveBeenWarnedTimes(1)\n  })\n\n  test('onUnmount', () => {\n    const cleanup = vi.fn().mockName('plugin cleanup')\n    const PluginA: Plugin = app => {\n      app.provide('foo', 1)\n      app.onUnmount(cleanup)\n    }\n    const PluginB: Plugin = {\n      install: (app, arg1, arg2) => {\n        app.provide('bar', arg1 + arg2)\n        app.onUnmount(cleanup)\n      },\n    }\n\n    const app = createApp({\n      render: () => `Test`,\n    })\n    app.use(PluginA)\n    app.use(PluginB)\n\n    const root = nodeOps.createElement('div')\n    app.mount(root)\n\n    //also can be added after mount\n    app.onUnmount(cleanup)\n\n    app.unmount()\n\n    expect(cleanup).toHaveBeenCalledTimes(3)\n  })\n\n  test('config.errorHandler', () => {\n    const error = new Error()\n    const count = ref(0)\n\n    const handler = vi.fn((err, instance, info) => {\n      expect(err).toBe(error)\n      expect(instance.count).toBe(count.value)\n      expect(info).toBe(`render function`)\n    })\n\n    const Root = {\n      setup() {\n        const count = ref(0)\n        return {\n          count,\n        }\n      },\n      render() {\n        throw error\n      },\n    }\n\n    const app = createApp(Root)\n    app.config.errorHandler = handler\n    app.mount(nodeOps.createElement('div'))\n    expect(handler).toHaveBeenCalled()\n  })\n\n  test('config.warnHandler', () => {\n    let ctx: any\n    const handler = vi.fn((msg, instance, trace) => {\n      expect(msg).toMatch(`Component is missing template or render function`)\n      expect(instance).toBe(ctx.proxy)\n      expect(trace).toMatch(`Hello`)\n    })\n\n    const Root = {\n      name: 'Hello',\n      setup() {\n        ctx = getCurrentInstance()\n      },\n    }\n\n    const app = createApp(Root)\n    app.config.warnHandler = handler\n    app.mount(nodeOps.createElement('div'))\n    expect(handler).toHaveBeenCalledTimes(1)\n  })\n\n  describe('config.isNativeTag', () => {\n    const isNativeTag = vi.fn(tag => tag === 'div')\n\n    test('Component.name', () => {\n      const Root = {\n        name: 'div',\n        render() {\n          return null\n        },\n      }\n\n      const app = createApp(Root)\n\n      Object.defineProperty(app.config, 'isNativeTag', {\n        value: isNativeTag,\n        writable: false,\n      })\n\n      app.mount(nodeOps.createElement('div'))\n      expect(\n        `Do not use built-in or reserved HTML elements as component id: div`,\n      ).toHaveBeenWarned()\n    })\n\n    test('Component.components', () => {\n      const Root = {\n        components: {\n          div: () => 'div',\n        },\n        render() {\n          return null\n        },\n      }\n\n      const app = createApp(Root)\n      Object.defineProperty(app.config, 'isNativeTag', {\n        value: isNativeTag,\n        writable: false,\n      })\n\n      app.mount(nodeOps.createElement('div'))\n      expect(\n        `Do not use built-in or reserved HTML elements as component id: div`,\n      ).toHaveBeenWarned()\n    })\n\n    test('Component.directives', () => {\n      const Root = {\n        directives: {\n          bind: () => {},\n        },\n        render() {\n          return null\n        },\n      }\n\n      const app = createApp(Root)\n      app.mount(nodeOps.createElement('div'))\n      expect(\n        `Do not use built-in directive ids as custom directive id: bind`,\n      ).toHaveBeenWarned()\n    })\n\n    test('register using app.component', () => {\n      const app = createApp({\n        render() {},\n      })\n\n      Object.defineProperty(app.config, 'isNativeTag', {\n        value: isNativeTag,\n        writable: false,\n      })\n\n      app.component('div', () => 'div')\n      app.mount(nodeOps.createElement('div'))\n      expect(\n        `Do not use built-in or reserved HTML elements as component id: div`,\n      ).toHaveBeenWarned()\n    })\n  })\n\n  test('config.optionMergeStrategies', () => {\n    let merged: string\n    const App = defineComponent({\n      render() {},\n      mixins: [{ foo: 'mixin' }],\n      extends: { foo: 'extends' },\n      foo: 'local',\n      beforeCreate() {\n        merged = this.$options.foo\n      },\n    })\n\n    const app = createApp(App)\n    app.mixin({\n      foo: 'global',\n    })\n    app.config.optionMergeStrategies.foo = (a, b) => (a ? `${a},` : ``) + b\n\n    app.mount(nodeOps.createElement('div'))\n    expect(merged!).toBe('global,extends,mixin,local')\n  })\n\n  test('config.globalProperties', () => {\n    const app = createApp({\n      render() {\n        return this.foo\n      },\n    })\n    app.config.globalProperties.foo = 'hello'\n    const root = nodeOps.createElement('div')\n    app.mount(root)\n    expect(serializeInner(root)).toBe('hello')\n  })\n\n  test('config.throwUnhandledErrorInProduction', () => {\n    __DEV__ = false\n    try {\n      const err = new Error()\n      const app = createApp({\n        setup() {\n          throw err\n        },\n      })\n      app.config.throwUnhandledErrorInProduction = true\n      const root = nodeOps.createElement('div')\n      expect(() => app.mount(root)).toThrow(err)\n    } finally {\n      __DEV__ = true\n    }\n  })\n\n  test('return property \"_\" should not overwrite \"ctx._\", __isScriptSetup: false', () => {\n    const Comp = defineComponent({\n      setup() {\n        return {\n          _: ref(0), // return property \"_\" should not overwrite \"ctx._\"\n        }\n      },\n      render() {\n        return h('input', {\n          ref: 'input',\n        })\n      },\n    })\n\n    const root1 = nodeOps.createElement('div')\n    createApp(Comp).mount(root1)\n\n    expect(\n      `setup() return property \"_\" should not start with \"$\" or \"_\" which are reserved prefixes for Vue internals.`,\n    ).toHaveBeenWarned()\n  })\n\n  test('return property \"_\" should not overwrite \"ctx._\", __isScriptSetup: true', () => {\n    const Comp = defineComponent({\n      setup() {\n        return {\n          _: ref(0), // return property \"_\" should not overwrite \"ctx._\"\n          __isScriptSetup: true, // mock __isScriptSetup = true\n        }\n      },\n      render() {\n        return h('input', {\n          ref: 'input',\n        })\n      },\n    })\n\n    const root1 = nodeOps.createElement('div')\n    const app = createApp(Comp).mount(root1)\n\n    // trigger\n    app.$refs.input\n\n    expect(\n      `TypeError: Cannot read property '__isScriptSetup' of undefined`,\n    ).not.toHaveBeenWarned()\n  })\n\n  // #10005\n  test('flush order edge case on nested createApp', async () => {\n    const order: string[] = []\n    const App = defineComponent({\n      setup(props) {\n        const message = ref('m1')\n        watch(\n          message,\n          () => {\n            order.push('post watcher')\n          },\n          { flush: 'post' },\n        )\n        onMounted(() => {\n          message.value = 'm2'\n          createApp(() => '').mount(nodeOps.createElement('div'))\n        })\n        return () => {\n          order.push('render')\n          return h('div', [message.value])\n        }\n      },\n    })\n\n    createApp(App).mount(nodeOps.createElement('div'))\n    await nextTick()\n    expect(order).toMatchObject(['render', 'render', 'post watcher'])\n  })\n\n  // #14215\n  test(\"unmount new app should not trigger other app's watcher\", async () => {\n    const compWatcherTriggerFn = vi.fn()\n    const data = ref(true)\n    const foo = ref('')\n\n    const createNewApp = () => {\n      const app = createApp({ render: () => h('new app') })\n      const wrapper = nodeOps.createElement('div')\n      app.mount(wrapper)\n      return function destroy() {\n        app.unmount()\n      }\n    }\n\n    const Comp = defineComponent({\n      setup() {\n        watch(() => foo.value, compWatcherTriggerFn)\n        return () => h('div', 'comp')\n      },\n    })\n\n    const App = defineComponent({\n      setup() {\n        return () => (data.value ? h(Comp) : null)\n      },\n    })\n\n    createApp(App).mount(nodeOps.createElement('div'))\n    await nextTick()\n\n    data.value = false\n    const destroy = createNewApp()\n    foo.value = 'bar'\n    destroy()\n    await nextTick()\n\n    expect(compWatcherTriggerFn).toBeCalledTimes(0)\n  })\n\n  // config.compilerOptions is tested in packages/vue since it is only\n  // supported in the full build.\n})\n"
  },
  {
    "path": "packages/runtime-core/__tests__/apiExpose.spec.ts",
    "content": "import { createApp, nodeOps, render } from '@vue/runtime-test'\nimport { defineComponent, h, ref } from '../src'\n\ndescribe('api: expose', () => {\n  test('via setup context', () => {\n    const Child = defineComponent({\n      render() {},\n      setup(_, { expose }) {\n        expose({\n          foo: 1,\n          bar: ref(2),\n        })\n        return {\n          bar: ref(3),\n          baz: ref(4),\n        }\n      },\n    })\n\n    const childRef = ref()\n    const Parent = {\n      setup() {\n        return () => h(Child, { ref: childRef })\n      },\n    }\n    const root = nodeOps.createElement('div')\n    render(h(Parent), root)\n    expect(childRef.value).toBeTruthy()\n    expect(childRef.value.foo).toBe(1)\n    expect(childRef.value.bar).toBe(2)\n    expect(childRef.value.baz).toBeUndefined()\n  })\n\n  test('via options', () => {\n    const Child = defineComponent({\n      render() {},\n      data() {\n        return {\n          foo: 1,\n        }\n      },\n      setup() {\n        return {\n          bar: ref(2),\n          baz: ref(3),\n        }\n      },\n      expose: ['foo', 'bar'],\n    })\n\n    const childRef = ref()\n    const Parent = {\n      setup() {\n        return () => h(Child, { ref: childRef })\n      },\n    }\n    const root = nodeOps.createElement('div')\n    render(h(Parent), root)\n    expect(childRef.value).toBeTruthy()\n    expect(childRef.value.foo).toBe(1)\n    expect(childRef.value.bar).toBe(2)\n    expect(childRef.value.baz).toBeUndefined()\n  })\n\n  test('options + context', () => {\n    const Child = defineComponent({\n      render() {},\n      expose: ['foo'],\n      data() {\n        return {\n          foo: 1,\n        }\n      },\n      setup(_, { expose }) {\n        expose({\n          bar: ref(2),\n        })\n        return {\n          bar: ref(3),\n          baz: ref(4),\n        }\n      },\n    })\n\n    const childRef = ref()\n    const Parent = {\n      setup() {\n        return () => h(Child, { ref: childRef })\n      },\n    }\n    const root = nodeOps.createElement('div')\n    render(h(Parent), root)\n    expect(childRef.value).toBeTruthy()\n    expect(childRef.value.foo).toBe(1)\n    expect(childRef.value.bar).toBe(2)\n    expect(childRef.value.baz).toBeUndefined()\n  })\n\n  test('options: empty', () => {\n    const Child = defineComponent({\n      render() {},\n      expose: [],\n      data() {\n        return {\n          foo: 1,\n        }\n      },\n    })\n\n    const childRef = ref()\n    const Parent = {\n      setup() {\n        return () => h(Child, { ref: childRef })\n      },\n    }\n    const root = nodeOps.createElement('div')\n    render(h(Parent), root)\n    expect(childRef.value).toBeTruthy()\n    expect('foo' in childRef.value).toBe(false)\n  })\n\n  test('options: empty + setup context', () => {\n    const Child = defineComponent({\n      render() {},\n      expose: [],\n      setup(_, { expose }) {\n        expose({\n          foo: 1,\n        })\n      },\n    })\n\n    const childRef = ref()\n    const Parent = {\n      setup() {\n        return () => h(Child, { ref: childRef })\n      },\n    }\n    const root = nodeOps.createElement('div')\n    render(h(Parent), root)\n    expect(childRef.value).toBeTruthy()\n    expect(childRef.value.foo).toBe(1)\n  })\n\n  test('with $parent/$root', () => {\n    const Child = defineComponent({\n      render() {\n        expect((this.$parent! as any).foo).toBe(1)\n        expect((this.$parent! as any).bar).toBe(undefined)\n        expect((this.$root! as any).foo).toBe(1)\n        expect((this.$root! as any).bar).toBe(undefined)\n      },\n    })\n\n    const Parent = defineComponent({\n      expose: [],\n      setup(_, { expose }) {\n        expose({\n          foo: 1,\n        })\n        return {\n          bar: 2,\n        }\n      },\n      render() {\n        return h(Child)\n      },\n    })\n    const root = nodeOps.createElement('div')\n    render(h(Parent), root)\n  })\n\n  test('with mount', () => {\n    const Component = defineComponent({\n      setup(_, { expose }) {\n        expose({\n          foo: 1,\n        })\n        return {\n          bar: 2,\n        }\n      },\n      render() {\n        return h('div')\n      },\n    })\n    const root = nodeOps.createElement('div')\n    const vm = createApp(Component).mount(root) as any\n    expect(vm.foo).toBe(1)\n    expect(vm.bar).toBe(undefined)\n  })\n\n  test('expose should allow access to built-in instance properties', () => {\n    const GrandChild = defineComponent({\n      render() {\n        return h('div')\n      },\n    })\n\n    const grandChildRef = ref()\n    const Child = defineComponent({\n      render() {\n        return h('div')\n      },\n      setup(_, { expose }) {\n        expose({\n          foo: 42,\n        })\n        return () => h(GrandChild, { ref: grandChildRef })\n      },\n    })\n\n    const childRef = ref()\n    const Parent = {\n      setup() {\n        return () => h(Child, { ref: childRef })\n      },\n    }\n    const root = nodeOps.createElement('div')\n    render(h(Parent), root)\n    expect('$el' in childRef.value).toBe(true)\n    expect(childRef.value.$el.tag).toBe('div')\n    expect('foo' in childRef.value).toBe(true)\n    expect('$parent' in grandChildRef.value).toBe(true)\n    expect(grandChildRef.value.$parent).toBe(childRef.value)\n    expect(grandChildRef.value.$parent.$parent).toBe(grandChildRef.value.$root)\n  })\n\n  test('warning for ref', () => {\n    const Comp = defineComponent({\n      setup(_, { expose }) {\n        expose(ref(1))\n        return () => null\n      },\n    })\n    render(h(Comp), nodeOps.createElement('div'))\n    expect(\n      'expose() should be passed a plain object, received ref',\n    ).toHaveBeenWarned()\n  })\n\n  test('warning for array', () => {\n    const Comp = defineComponent({\n      setup(_, { expose }) {\n        expose(['focus'])\n        return () => null\n      },\n    })\n    render(h(Comp), nodeOps.createElement('div'))\n    expect(\n      'expose() should be passed a plain object, received array',\n    ).toHaveBeenWarned()\n  })\n\n  test('warning for function', () => {\n    const Comp = defineComponent({\n      setup(_, { expose }) {\n        expose(() => null)\n        return () => null\n      },\n    })\n    render(h(Comp), nodeOps.createElement('div'))\n    expect(\n      'expose() should be passed a plain object, received function',\n    ).toHaveBeenWarned()\n  })\n})\n"
  },
  {
    "path": "packages/runtime-core/__tests__/apiInject.spec.ts",
    "content": "import {\n  type InjectionKey,\n  type Ref,\n  defineComponent,\n  h,\n  hasInjectionContext,\n  inject,\n  nextTick,\n  onMounted,\n  provide,\n  reactive,\n  readonly,\n  ref,\n} from '../src/index'\nimport { createApp, nodeOps, render, serialize } from '@vue/runtime-test'\n\ndescribe('api: provide/inject', () => {\n  it('string keys', () => {\n    const Provider = {\n      setup() {\n        provide('foo', 1)\n        return () => h(Middle)\n      },\n    }\n\n    const Middle = {\n      render: () => h(Consumer),\n    }\n\n    const Consumer = {\n      setup() {\n        const foo = inject('foo')\n        return () => foo\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(Provider), root)\n    expect(serialize(root)).toBe(`<div>1</div>`)\n  })\n\n  it('symbol keys', () => {\n    // also verifies InjectionKey type sync\n    const key: InjectionKey<number> = Symbol()\n\n    const Provider = {\n      setup() {\n        provide(key, 1)\n        return () => h(Middle)\n      },\n    }\n\n    const Middle = {\n      render: () => h(Consumer),\n    }\n\n    const Consumer = {\n      setup() {\n        const foo = inject(key) || 1\n        return () => foo + 1\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(Provider), root)\n    expect(serialize(root)).toBe(`<div>2</div>`)\n  })\n\n  it('default values', () => {\n    const Provider = {\n      setup() {\n        provide('foo', 'foo')\n        return () => h(Middle)\n      },\n    }\n\n    const Middle = {\n      render: () => h(Consumer),\n    }\n\n    const Consumer = {\n      setup() {\n        // default value should be ignored if value is provided\n        const foo = inject('foo', 'fooDefault')\n        // default value should be used if value is not provided\n        const bar = inject('bar', 'bar')\n        return () => foo + bar\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(Provider), root)\n    expect(serialize(root)).toBe(`<div>foobar</div>`)\n  })\n\n  it('bound to instance', () => {\n    const Provider = {\n      setup() {\n        return () => h(Consumer)\n      },\n    }\n\n    const Consumer = defineComponent({\n      name: 'Consumer',\n      inject: {\n        foo: {\n          from: 'foo',\n          default() {\n            return this!.$options.name\n          },\n        },\n      },\n      render() {\n        return this.foo\n      },\n    })\n\n    const root = nodeOps.createElement('div')\n    render(h(Provider), root)\n    expect(serialize(root)).toBe(`<div>Consumer</div>`)\n  })\n\n  it('nested providers', () => {\n    const ProviderOne = {\n      setup() {\n        provide('foo', 'foo')\n        provide('bar', 'bar')\n        return () => h(ProviderTwo)\n      },\n    }\n\n    const ProviderTwo = {\n      setup() {\n        // override parent value\n        provide('foo', 'fooOverride')\n        provide('baz', 'baz')\n        return () => h(Consumer)\n      },\n    }\n\n    const Consumer = {\n      setup() {\n        const foo = inject('foo')\n        const bar = inject('bar')\n        const baz = inject('baz')\n        return () => [foo, bar, baz].join(',')\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(ProviderOne), root)\n    expect(serialize(root)).toBe(`<div>fooOverride,bar,baz</div>`)\n  })\n\n  it('reactivity with refs', async () => {\n    const count = ref(1)\n\n    const Provider = {\n      setup() {\n        provide('count', count)\n        return () => h(Middle)\n      },\n    }\n\n    const Middle = {\n      render: () => h(Consumer),\n    }\n\n    const Consumer = {\n      setup() {\n        const count = inject<Ref<number>>('count')!\n        return () => count.value\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(Provider), root)\n    expect(serialize(root)).toBe(`<div>1</div>`)\n\n    count.value++\n    await nextTick()\n    expect(serialize(root)).toBe(`<div>2</div>`)\n  })\n\n  it('reactivity with readonly refs', async () => {\n    const count = ref(1)\n\n    const Provider = {\n      setup() {\n        provide('count', readonly(count))\n        return () => h(Middle)\n      },\n    }\n\n    const Middle = {\n      render: () => h(Consumer),\n    }\n\n    const Consumer = {\n      setup() {\n        const count = inject<Ref<number>>('count')!\n        // should not work\n        count.value++\n        return () => count.value\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(Provider), root)\n    expect(serialize(root)).toBe(`<div>1</div>`)\n\n    expect(\n      `Set operation on key \"value\" failed: target is readonly`,\n    ).toHaveBeenWarned()\n\n    // source mutation should still work\n    count.value++\n    await nextTick()\n    expect(serialize(root)).toBe(`<div>2</div>`)\n  })\n\n  it('reactivity with objects', async () => {\n    const rootState = reactive({ count: 1 })\n\n    const Provider = {\n      setup() {\n        provide('state', rootState)\n        return () => h(Middle)\n      },\n    }\n\n    const Middle = {\n      render: () => h(Consumer),\n    }\n\n    const Consumer = {\n      setup() {\n        const state = inject<typeof rootState>('state')!\n        return () => state.count\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(Provider), root)\n    expect(serialize(root)).toBe(`<div>1</div>`)\n\n    rootState.count++\n    await nextTick()\n    expect(serialize(root)).toBe(`<div>2</div>`)\n  })\n\n  it('reactivity with readonly objects', async () => {\n    const rootState = reactive({ count: 1 })\n\n    const Provider = {\n      setup() {\n        provide('state', readonly(rootState))\n        return () => h(Middle)\n      },\n    }\n\n    const Middle = {\n      render: () => h(Consumer),\n    }\n\n    const Consumer = {\n      setup() {\n        const state = inject<typeof rootState>('state')!\n        // should not work\n        state.count++\n        return () => state.count\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(Provider), root)\n    expect(serialize(root)).toBe(`<div>1</div>`)\n\n    expect(\n      `Set operation on key \"count\" failed: target is readonly`,\n    ).toHaveBeenWarned()\n\n    rootState.count++\n    await nextTick()\n    expect(serialize(root)).toBe(`<div>2</div>`)\n  })\n\n  it('should warn unfound', () => {\n    const Provider = {\n      setup() {\n        return () => h(Middle)\n      },\n    }\n\n    const Middle = {\n      render: () => h(Consumer),\n    }\n\n    const Consumer = {\n      setup() {\n        const foo = inject('foo')\n        expect(foo).toBeUndefined()\n        return () => foo\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(Provider), root)\n    expect(serialize(root)).toBe(`<div><!----></div>`)\n    expect(`injection \"foo\" not found.`).toHaveBeenWarned()\n  })\n\n  it('should not warn when default value is undefined', () => {\n    const Provider = {\n      setup() {\n        return () => h(Middle)\n      },\n    }\n\n    const Middle = {\n      render: () => h(Consumer),\n    }\n\n    const Consumer = {\n      setup() {\n        const foo = inject('foo', undefined)\n        return () => foo\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(Provider), root)\n    expect(`injection \"foo\" not found.`).not.toHaveBeenWarned()\n  })\n\n  // #2400\n  it('should not self-inject', () => {\n    const Comp = {\n      setup() {\n        provide('foo', 'foo')\n        const injection = inject('foo', null)\n        return () => injection\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(Comp), root)\n    expect(serialize(root)).toBe(`<div><!----></div>`)\n  })\n\n  describe('hasInjectionContext', () => {\n    it('should be false outside of setup', () => {\n      expect(hasInjectionContext()).toBe(false)\n    })\n\n    it('should be true within setup', () => {\n      expect.assertions(1)\n      const Comp = {\n        setup() {\n          expect(hasInjectionContext()).toBe(true)\n          return () => null\n        },\n      }\n\n      const root = nodeOps.createElement('div')\n      render(h(Comp), root)\n    })\n\n    it('should be true within app.runWithContext()', () => {\n      expect.assertions(1)\n      createApp({}).runWithContext(() => {\n        expect(hasInjectionContext()).toBe(true)\n      })\n    })\n  })\n\n  describe('warnings for incorrect usage', () => {\n    it('should warn when inject() is called outside setup', () => {\n      inject('foo', 'bar')\n      expect(`inject() can only be used`).toHaveBeenWarned()\n    })\n\n    it('should warn when provide() is called outside setup', () => {\n      provide('foo', 'bar')\n      expect(`provide() can only be used`).toHaveBeenWarned()\n    })\n\n    it('should warn when provide() is called from a render function', () => {\n      const Provider = {\n        setup() {\n          return () => {\n            provide('foo', 'bar')\n          }\n        },\n      }\n\n      const root = nodeOps.createElement('div')\n      render(h(Provider), root)\n      expect(`provide() can only be used`).toHaveBeenWarned()\n    })\n\n    it('should warn when provide() is called from onMounted', () => {\n      const Provider = {\n        setup() {\n          onMounted(() => {\n            provide('foo', 'bar')\n          })\n\n          return () => null\n        },\n      }\n\n      const root = nodeOps.createElement('div')\n      render(h(Provider), root)\n      expect(`provide() can only be used`).toHaveBeenWarned()\n    })\n  })\n})\n"
  },
  {
    "path": "packages/runtime-core/__tests__/apiLifecycle.spec.ts",
    "content": "import {\n  KeepAlive,\n  TrackOpTypes,\n  h,\n  nextTick,\n  nodeOps,\n  onActivated,\n  onBeforeMount,\n  onBeforeUnmount,\n  onBeforeUpdate,\n  onMounted,\n  onRenderTracked,\n  onRenderTriggered,\n  onUnmounted,\n  onUpdated,\n  reactive,\n  ref,\n  render,\n  serializeInner,\n} from '@vue/runtime-test'\nimport {\n  type DebuggerEvent,\n  ITERATE_KEY,\n  TriggerOpTypes,\n} from '@vue/reactivity'\n\ndescribe('api: lifecycle hooks', () => {\n  it('onBeforeMount', () => {\n    const root = nodeOps.createElement('div')\n    const fn = vi.fn(() => {\n      // should be called before inner div is rendered\n      expect(serializeInner(root)).toBe(``)\n    })\n\n    const Comp = {\n      setup() {\n        onBeforeMount(fn)\n        return () => h('div')\n      },\n    }\n    render(h(Comp), root)\n    expect(fn).toHaveBeenCalledTimes(1)\n    // #10863\n    expect(fn).toHaveBeenCalledWith()\n  })\n\n  it('onMounted', () => {\n    const root = nodeOps.createElement('div')\n    const fn = vi.fn(() => {\n      // should be called after inner div is rendered\n      expect(serializeInner(root)).toBe(`<div></div>`)\n    })\n\n    const Comp = {\n      setup() {\n        onMounted(fn)\n        return () => h('div')\n      },\n    }\n    render(h(Comp), root)\n    expect(fn).toHaveBeenCalledTimes(1)\n  })\n\n  it('onBeforeUpdate', async () => {\n    const count = ref(0)\n    const root = nodeOps.createElement('div')\n    const fn = vi.fn(() => {\n      // should be called before inner div is updated\n      expect(serializeInner(root)).toBe(`<div>0</div>`)\n    })\n\n    const Comp = {\n      setup() {\n        onBeforeUpdate(fn)\n        return () => h('div', count.value)\n      },\n    }\n    render(h(Comp), root)\n\n    count.value++\n    await nextTick()\n    expect(fn).toHaveBeenCalledTimes(1)\n    expect(serializeInner(root)).toBe(`<div>1</div>`)\n  })\n\n  it('state mutation in onBeforeUpdate', async () => {\n    const count = ref(0)\n    const root = nodeOps.createElement('div')\n    const fn = vi.fn(() => {\n      // should be called before inner div is updated\n      expect(serializeInner(root)).toBe(`<div>0</div>`)\n      count.value++\n    })\n    const renderSpy = vi.fn()\n\n    const Comp = {\n      setup() {\n        onBeforeUpdate(fn)\n        return () => {\n          renderSpy()\n          return h('div', count.value)\n        }\n      },\n    }\n    render(h(Comp), root)\n    expect(renderSpy).toHaveBeenCalledTimes(1)\n\n    count.value++\n    await nextTick()\n    expect(fn).toHaveBeenCalledTimes(1)\n    expect(renderSpy).toHaveBeenCalledTimes(2)\n    expect(serializeInner(root)).toBe(`<div>2</div>`)\n  })\n\n  it('onUpdated', async () => {\n    const count = ref(0)\n    const root = nodeOps.createElement('div')\n    const fn = vi.fn(() => {\n      // should be called after inner div is updated\n      expect(serializeInner(root)).toBe(`<div>1</div>`)\n    })\n\n    const Comp = {\n      setup() {\n        onUpdated(fn)\n        return () => h('div', count.value)\n      },\n    }\n    render(h(Comp), root)\n\n    count.value++\n    await nextTick()\n    expect(fn).toHaveBeenCalledTimes(1)\n  })\n\n  it('onBeforeUnmount', async () => {\n    const toggle = ref(true)\n    const root = nodeOps.createElement('div')\n    const fn = vi.fn(() => {\n      // should be called before inner div is removed\n      expect(serializeInner(root)).toBe(`<div></div>`)\n    })\n\n    const Comp = {\n      setup() {\n        return () => (toggle.value ? h(Child) : null)\n      },\n    }\n\n    const Child = {\n      setup() {\n        onBeforeUnmount(fn)\n        return () => h('div')\n      },\n    }\n\n    render(h(Comp), root)\n\n    toggle.value = false\n    await nextTick()\n    expect(fn).toHaveBeenCalledTimes(1)\n  })\n\n  it('onUnmounted', async () => {\n    const toggle = ref(true)\n    const root = nodeOps.createElement('div')\n    const fn = vi.fn(() => {\n      // should be called after inner div is removed\n      expect(serializeInner(root)).toBe(`<!---->`)\n    })\n\n    const Comp = {\n      setup() {\n        return () => (toggle.value ? h(Child) : null)\n      },\n    }\n\n    const Child = {\n      setup() {\n        onUnmounted(fn)\n        return () => h('div')\n      },\n    }\n\n    render(h(Comp), root)\n\n    toggle.value = false\n    await nextTick()\n    expect(fn).toHaveBeenCalledTimes(1)\n  })\n\n  it('onBeforeUnmount in onMounted', async () => {\n    const toggle = ref(true)\n    const root = nodeOps.createElement('div')\n    const fn = vi.fn(() => {\n      // should be called before inner div is removed\n      expect(serializeInner(root)).toBe(`<div></div>`)\n    })\n\n    const Comp = {\n      setup() {\n        return () => (toggle.value ? h(Child) : null)\n      },\n    }\n\n    const Child = {\n      setup() {\n        onMounted(() => {\n          onBeforeUnmount(fn)\n        })\n        return () => h('div')\n      },\n    }\n\n    render(h(Comp), root)\n\n    toggle.value = false\n    await nextTick()\n    expect(fn).toHaveBeenCalledTimes(1)\n  })\n\n  it('lifecycle call order', async () => {\n    const count = ref(0)\n    const root = nodeOps.createElement('div')\n    const calls: string[] = []\n\n    const Root = {\n      setup() {\n        onBeforeMount(() => calls.push('root onBeforeMount'))\n        onMounted(() => calls.push('root onMounted'))\n        onBeforeUpdate(() => calls.push('root onBeforeUpdate'))\n        onUpdated(() => calls.push('root onUpdated'))\n        onBeforeUnmount(() => calls.push('root onBeforeUnmount'))\n        onUnmounted(() => calls.push('root onUnmounted'))\n        return () => h(Mid, { count: count.value })\n      },\n    }\n\n    const Mid = {\n      props: ['count'],\n      setup(props: any) {\n        onBeforeMount(() => calls.push('mid onBeforeMount'))\n        onMounted(() => calls.push('mid onMounted'))\n        onBeforeUpdate(() => calls.push('mid onBeforeUpdate'))\n        onUpdated(() => calls.push('mid onUpdated'))\n        onBeforeUnmount(() => calls.push('mid onBeforeUnmount'))\n        onUnmounted(() => calls.push('mid onUnmounted'))\n        return () => h(Child, { count: props.count })\n      },\n    }\n\n    const Child = {\n      props: ['count'],\n      setup(props: any) {\n        onBeforeMount(() => calls.push('child onBeforeMount'))\n        onMounted(() => calls.push('child onMounted'))\n        onBeforeUpdate(() => calls.push('child onBeforeUpdate'))\n        onUpdated(() => calls.push('child onUpdated'))\n        onBeforeUnmount(() => calls.push('child onBeforeUnmount'))\n        onUnmounted(() => calls.push('child onUnmounted'))\n        return () => h('div', props.count)\n      },\n    }\n\n    // mount\n    render(h(Root), root)\n    expect(calls).toEqual([\n      'root onBeforeMount',\n      'mid onBeforeMount',\n      'child onBeforeMount',\n      'child onMounted',\n      'mid onMounted',\n      'root onMounted',\n    ])\n\n    calls.length = 0\n\n    // update\n    count.value++\n    await nextTick()\n    expect(calls).toEqual([\n      'root onBeforeUpdate',\n      'mid onBeforeUpdate',\n      'child onBeforeUpdate',\n      'child onUpdated',\n      'mid onUpdated',\n      'root onUpdated',\n    ])\n\n    calls.length = 0\n\n    // unmount\n    render(null, root)\n    expect(calls).toEqual([\n      'root onBeforeUnmount',\n      'mid onBeforeUnmount',\n      'child onBeforeUnmount',\n      'child onUnmounted',\n      'mid onUnmounted',\n      'root onUnmounted',\n    ])\n  })\n\n  it('onRenderTracked', () => {\n    const events: DebuggerEvent[] = []\n    const onTrack = vi.fn((e: DebuggerEvent) => {\n      events.push(e)\n    })\n    const obj = reactive({ foo: 1, bar: 2 })\n\n    const Comp = {\n      setup() {\n        onRenderTracked(onTrack)\n        return () =>\n          h('div', [obj.foo, 'bar' in obj, Object.keys(obj).join('')])\n      },\n    }\n\n    render(h(Comp), nodeOps.createElement('div'))\n    expect(onTrack).toHaveBeenCalledTimes(3)\n    expect(events).toMatchObject([\n      {\n        target: obj,\n        type: TrackOpTypes.GET,\n        key: 'foo',\n      },\n      {\n        target: obj,\n        type: TrackOpTypes.HAS,\n        key: 'bar',\n      },\n      {\n        target: obj,\n        type: TrackOpTypes.ITERATE,\n        key: ITERATE_KEY,\n      },\n    ])\n  })\n\n  it('onRenderTriggered', async () => {\n    const events: DebuggerEvent[] = []\n    const onTrigger = vi.fn((e: DebuggerEvent) => {\n      events.push(e)\n    })\n    const obj = reactive<{\n      foo: number\n      bar?: number\n    }>({ foo: 1, bar: 2 })\n\n    const Comp = {\n      setup() {\n        onRenderTriggered(onTrigger)\n        return () =>\n          h('div', [obj.foo, 'bar' in obj, Object.keys(obj).join('')])\n      },\n    }\n\n    render(h(Comp), nodeOps.createElement('div'))\n\n    obj.foo++\n    await nextTick()\n    expect(onTrigger).toHaveBeenCalledTimes(1)\n    expect(events[0]).toMatchObject({\n      type: TriggerOpTypes.SET,\n      key: 'foo',\n      oldValue: 1,\n      newValue: 2,\n    })\n\n    delete obj.bar\n    await nextTick()\n    expect(onTrigger).toHaveBeenCalledTimes(2)\n    expect(events[1]).toMatchObject({\n      type: TriggerOpTypes.DELETE,\n      key: 'bar',\n      oldValue: 2,\n    })\n    ;(obj as any).baz = 3\n    await nextTick()\n    expect(onTrigger).toHaveBeenCalledTimes(3)\n    expect(events[2]).toMatchObject({\n      type: TriggerOpTypes.ADD,\n      key: 'baz',\n      newValue: 3,\n    })\n  })\n\n  it('runs shared hook fn for each instance', async () => {\n    const fn = vi.fn()\n    const toggle = ref(true)\n    const Comp = {\n      setup() {\n        return () => (toggle.value ? [h(Child), h(Child)] : null)\n      },\n    }\n    const Child = {\n      setup() {\n        onMounted(fn)\n        onBeforeUnmount(fn)\n        return () => h('div')\n      },\n    }\n\n    render(h(Comp), nodeOps.createElement('div'))\n    expect(fn).toHaveBeenCalledTimes(2)\n    toggle.value = false\n    await nextTick()\n    expect(fn).toHaveBeenCalledTimes(4)\n  })\n\n  it('immediately trigger unmount during rendering', async () => {\n    const fn = vi.fn()\n    const toggle = ref(false)\n\n    const Child = {\n      setup() {\n        onMounted(fn)\n        // trigger unmount immediately\n        toggle.value = false\n        return () => h('div')\n      },\n    }\n\n    const Comp = {\n      setup() {\n        return () => (toggle.value ? [h(Child)] : null)\n      },\n    }\n\n    render(h(Comp), nodeOps.createElement('div'))\n\n    toggle.value = true\n    await nextTick()\n    expect(fn).toHaveBeenCalledTimes(0)\n  })\n\n  it('immediately trigger unmount during rendering(with KeepAlive)', async () => {\n    const mountedSpy = vi.fn()\n    const activeSpy = vi.fn()\n    const toggle = ref(false)\n\n    const Child = {\n      setup() {\n        onMounted(mountedSpy)\n        onActivated(activeSpy)\n\n        // trigger unmount immediately\n        toggle.value = false\n        return () => h('div')\n      },\n    }\n\n    const Comp = {\n      setup() {\n        return () => h(KeepAlive, [toggle.value ? h(Child) : null])\n      },\n    }\n\n    render(h(Comp), nodeOps.createElement('div'))\n\n    toggle.value = true\n    await nextTick()\n    expect(mountedSpy).toHaveBeenCalledTimes(0)\n    expect(activeSpy).toHaveBeenCalledTimes(0)\n  })\n})\n"
  },
  {
    "path": "packages/runtime-core/__tests__/apiOptions.spec.ts",
    "content": "/**\n * @vitest-environment jsdom\n */\nimport type { Mock } from 'vitest'\nimport {\n  type TestElement,\n  computed,\n  createApp,\n  defineComponent,\n  h,\n  nextTick,\n  nodeOps,\n  ref,\n  render,\n  renderToString,\n  serializeInner,\n  triggerEvent,\n} from '@vue/runtime-test'\nimport { render as domRender } from 'vue'\n\ndescribe('api: options', () => {\n  test('data', async () => {\n    const Comp = defineComponent({\n      data() {\n        return {\n          foo: 1,\n        }\n      },\n      render() {\n        return h(\n          'div',\n          {\n            onClick: () => {\n              this.foo++\n            },\n          },\n          this.foo,\n        )\n      },\n    })\n    const root = nodeOps.createElement('div')\n    render(h(Comp), root)\n    expect(serializeInner(root)).toBe(`<div>1</div>`)\n\n    triggerEvent(root.children[0] as TestElement, 'click')\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<div>2</div>`)\n  })\n\n  test('computed', async () => {\n    const Comp = defineComponent({\n      data() {\n        return {\n          foo: 1,\n        }\n      },\n      computed: {\n        bar(): number {\n          return this.foo + 1\n        },\n        baz: (vm: any): number => vm.bar + 1,\n      },\n      render() {\n        return h(\n          'div',\n          {\n            onClick: () => {\n              this.foo++\n            },\n          },\n          this.bar + this.baz,\n        )\n      },\n    })\n    const root = nodeOps.createElement('div')\n    render(h(Comp), root)\n    expect(serializeInner(root)).toBe(`<div>5</div>`)\n\n    triggerEvent(root.children[0] as TestElement, 'click')\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<div>7</div>`)\n  })\n\n  test('methods', async () => {\n    const Comp = defineComponent({\n      data() {\n        // #3300 method on ctx should be overwritable\n        this.incBy = this.incBy.bind(this, 2)\n        return {\n          foo: 1,\n        }\n      },\n      methods: {\n        inc() {\n          this.foo++\n        },\n        incBy(n = 0) {\n          this.foo += n\n        },\n      },\n      render() {\n        return h(\n          'div',\n          {\n            onClick: this.inc,\n            onFoo: this.incBy,\n          },\n          this.foo,\n        )\n      },\n    })\n    const root = nodeOps.createElement('div')\n    render(h(Comp), root)\n    expect(serializeInner(root)).toBe(`<div>1</div>`)\n\n    triggerEvent(root.children[0] as TestElement, 'click')\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<div>2</div>`)\n\n    triggerEvent(root.children[0] as TestElement, 'foo')\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<div>4</div>`)\n  })\n\n  test(\"component's own methods have higher priority than global properties\", async () => {\n    const app = createApp({\n      methods: {\n        foo() {\n          return 'foo'\n        },\n      },\n      render() {\n        return this.foo()\n      },\n    })\n    app.config.globalProperties.foo = () => 'bar'\n\n    const root = nodeOps.createElement('div')\n    app.mount(root)\n    expect(serializeInner(root)).toBe(`foo`)\n  })\n\n  test('watch', async () => {\n    function returnThis(this: any) {\n      return this\n    }\n    const spyA = vi.fn(returnThis)\n    const spyB = vi.fn(returnThis)\n    const spyC = vi.fn(returnThis)\n    const spyD = vi.fn(returnThis)\n    const spyE = vi.fn(returnThis)\n\n    let ctx: any\n    const Comp = {\n      data() {\n        return {\n          foo: 1,\n          bar: 2,\n          baz: {\n            qux: 3,\n          },\n          qux: 4,\n          dot: {\n            path: 5,\n          },\n        }\n      },\n      watch: {\n        // string method name\n        foo: 'onFooChange',\n        // direct function\n        bar: spyB,\n        baz: {\n          handler: spyC,\n          deep: true,\n        },\n        qux: {\n          handler: 'onQuxChange',\n        },\n        'dot.path': spyE,\n      },\n      methods: {\n        onFooChange: spyA,\n        onQuxChange: spyD,\n      },\n      render() {\n        ctx = this\n      },\n    }\n    const root = nodeOps.createElement('div')\n    render(h(Comp), root)\n\n    function assertCall(spy: Mock, callIndex: number, args: any[]) {\n      expect(spy.mock.calls[callIndex].slice(0, 2)).toMatchObject(args)\n      expect(spy.mock.results[callIndex].value).toBe(ctx)\n    }\n\n    ctx.foo++\n    await nextTick()\n    expect(spyA).toHaveBeenCalledTimes(1)\n    assertCall(spyA, 0, [2, 1])\n\n    ctx.bar++\n    await nextTick()\n    expect(spyB).toHaveBeenCalledTimes(1)\n    assertCall(spyB, 0, [3, 2])\n\n    ctx.baz.qux++\n    await nextTick()\n    expect(spyC).toHaveBeenCalledTimes(1)\n    // new and old objects have same identity\n    assertCall(spyC, 0, [{ qux: 4 }, { qux: 4 }])\n\n    ctx.qux++\n    await nextTick()\n    expect(spyD).toHaveBeenCalledTimes(1)\n    assertCall(spyD, 0, [5, 4])\n\n    ctx.dot.path++\n    await nextTick()\n    expect(spyE).toHaveBeenCalledTimes(1)\n    assertCall(spyE, 0, [6, 5])\n  })\n\n  test('watch array', async () => {\n    function returnThis(this: any) {\n      return this\n    }\n    const spyA = vi.fn(returnThis)\n    const spyB = vi.fn(returnThis)\n    const spyC = vi.fn(returnThis)\n\n    let ctx: any\n    const Comp = {\n      data() {\n        return {\n          foo: 1,\n          bar: 2,\n          baz: {\n            qux: 3,\n          },\n        }\n      },\n      watch: {\n        // string method name\n        foo: ['onFooChange'],\n        // direct function\n        bar: [spyB],\n        baz: [\n          {\n            handler: spyC,\n            deep: true,\n          },\n        ],\n      },\n      methods: {\n        onFooChange: spyA,\n      },\n      render() {\n        ctx = this\n      },\n    }\n    const root = nodeOps.createElement('div')\n    render(h(Comp), root)\n\n    function assertCall(spy: Mock, callIndex: number, args: any[]) {\n      expect(spy.mock.calls[callIndex].slice(0, 2)).toMatchObject(args)\n      expect(spy.mock.results[callIndex].value).toBe(ctx)\n    }\n\n    ctx.foo++\n    await nextTick()\n    expect(spyA).toHaveBeenCalledTimes(1)\n    assertCall(spyA, 0, [2, 1])\n\n    ctx.bar++\n    await nextTick()\n    expect(spyB).toHaveBeenCalledTimes(1)\n    assertCall(spyB, 0, [3, 2])\n\n    ctx.baz.qux++\n    await nextTick()\n    expect(spyC).toHaveBeenCalledTimes(1)\n    // new and old objects have same identity\n    assertCall(spyC, 0, [{ qux: 4 }, { qux: 4 }])\n  })\n\n  // #3966\n  test('watch merging from mixins', async () => {\n    const mixinA = {\n      data() {\n        return {\n          fromMixinA: '',\n        }\n      },\n      watch: {\n        obj: {\n          handler(this: any, to: any) {\n            this.fromMixinA = to\n          },\n        },\n      },\n    }\n\n    const mixinB = {\n      data() {\n        return {\n          fromMixinB: '',\n        }\n      },\n      watch: {\n        obj: 'setMixinB',\n      },\n      methods: {\n        setMixinB(this: any, to: any) {\n          this.fromMixinB = to\n        },\n      },\n    }\n\n    let vm: any\n    const Comp = {\n      render() {},\n      mixins: [mixinA, mixinB],\n      data: () => ({\n        obj: 'foo',\n        fromComp: '',\n      }),\n      watch: {\n        obj(this: any, to: any) {\n          this.fromComp = to\n        },\n      },\n      mounted() {\n        vm = this\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(Comp), root)\n\n    vm.obj = 'bar'\n    await nextTick()\n    expect(vm.fromComp).toBe('bar')\n    expect(vm.fromMixinA).toBe('bar')\n    expect(vm.fromMixinB).toBe('bar')\n  })\n\n  test('provide/inject', () => {\n    const symbolKey = Symbol()\n    const Root = defineComponent({\n      data() {\n        return {\n          a: 1,\n        }\n      },\n      provide() {\n        return {\n          a: this.a,\n          [symbolKey]: 2,\n        }\n      },\n      render() {\n        return [\n          h(ChildA),\n          h(ChildB),\n          h(ChildC),\n          h(ChildD),\n          h(ChildE),\n          h(ChildF),\n          h(ChildG),\n          h(ChildH),\n          h(ChildI),\n          h(ChildJ),\n        ]\n      },\n    })\n\n    const defineChild = (injectOptions: any, injectedKey = 'b') =>\n      ({\n        inject: injectOptions,\n        render() {\n          return this[injectedKey]\n        },\n      }) as any\n\n    const ChildA = defineChild(['a'], 'a')\n    const ChildB = defineChild({ b: 'a' })\n    const ChildC = defineChild({\n      b: {\n        from: 'a',\n      },\n    })\n    const ChildD = defineChild(\n      {\n        a: {\n          default: () => 0,\n        },\n      },\n      'a',\n    )\n    const ChildE = defineChild({\n      b: {\n        from: 'c',\n        default: 2,\n      },\n    })\n    const ChildF = defineChild({\n      b: {\n        from: 'c',\n        default: () => 3,\n      },\n    })\n    const ChildG = defineChild({\n      b: {\n        default: 4,\n      },\n    })\n    const ChildH = defineChild({\n      b: {\n        default: () => 5,\n      },\n    })\n    const ChildI = defineChild({\n      b: symbolKey,\n    })\n    const ChildJ = defineChild({\n      b: {\n        from: symbolKey,\n      },\n    })\n    expect(renderToString(h(Root))).toBe(`1111234522`)\n  })\n\n  test('provide/inject refs', async () => {\n    const n = ref(0)\n    const np = computed(() => n.value + 1)\n    const Parent = defineComponent({\n      provide() {\n        return {\n          n,\n          np,\n        }\n      },\n      render: () => h(Child),\n    })\n    const Child = defineComponent({\n      inject: ['n', 'np'],\n      render(this: any) {\n        return this.n + this.np\n      },\n    })\n    const app = createApp(Parent)\n    const root = nodeOps.createElement('div')\n    app.mount(root)\n    expect(serializeInner(root)).toBe(`1`)\n\n    n.value++\n    await nextTick()\n    expect(serializeInner(root)).toBe(`3`)\n  })\n\n  test('provide accessing data in extends', () => {\n    const Base = defineComponent({\n      data() {\n        return {\n          a: 1,\n        }\n      },\n      provide() {\n        return {\n          a: this.a,\n        }\n      },\n    })\n\n    const Child = {\n      inject: ['a'],\n      render() {\n        return (this as any).a\n      },\n    }\n\n    const Root = defineComponent({\n      extends: Base,\n      render() {\n        return h(Child)\n      },\n    })\n    expect(renderToString(h(Root))).toBe(`1`)\n  })\n\n  test('lifecycle', async () => {\n    const count = ref(0)\n    const root = nodeOps.createElement('div')\n    const calls: string[] = []\n\n    const Root = {\n      beforeCreate() {\n        calls.push('root beforeCreate')\n      },\n      created() {\n        calls.push('root created')\n      },\n      beforeMount() {\n        calls.push('root onBeforeMount')\n      },\n      mounted() {\n        calls.push('root onMounted')\n      },\n      beforeUpdate() {\n        calls.push('root onBeforeUpdate')\n      },\n      updated() {\n        calls.push('root onUpdated')\n      },\n      beforeUnmount() {\n        calls.push('root onBeforeUnmount')\n      },\n      unmounted() {\n        calls.push('root onUnmounted')\n      },\n      render() {\n        return h(Mid, { count: count.value })\n      },\n    }\n\n    const Mid = {\n      beforeCreate() {\n        calls.push('mid beforeCreate')\n      },\n      created() {\n        calls.push('mid created')\n      },\n      beforeMount() {\n        calls.push('mid onBeforeMount')\n      },\n      mounted() {\n        calls.push('mid onMounted')\n      },\n      beforeUpdate() {\n        calls.push('mid onBeforeUpdate')\n      },\n      updated() {\n        calls.push('mid onUpdated')\n      },\n      beforeUnmount() {\n        calls.push('mid onBeforeUnmount')\n      },\n      unmounted() {\n        calls.push('mid onUnmounted')\n      },\n      render(this: any) {\n        return h(Child, { count: this.$props.count })\n      },\n    }\n\n    const Child = {\n      beforeCreate() {\n        calls.push('child beforeCreate')\n      },\n      created() {\n        calls.push('child created')\n      },\n      beforeMount() {\n        calls.push('child onBeforeMount')\n      },\n      mounted() {\n        calls.push('child onMounted')\n      },\n      beforeUpdate() {\n        calls.push('child onBeforeUpdate')\n      },\n      updated() {\n        calls.push('child onUpdated')\n      },\n      beforeUnmount() {\n        calls.push('child onBeforeUnmount')\n      },\n      unmounted() {\n        calls.push('child onUnmounted')\n      },\n      render(this: any) {\n        return h('div', this.$props.count)\n      },\n    }\n\n    // mount\n    render(h(Root), root)\n    expect(calls).toEqual([\n      'root beforeCreate',\n      'root created',\n      'root onBeforeMount',\n      'mid beforeCreate',\n      'mid created',\n      'mid onBeforeMount',\n      'child beforeCreate',\n      'child created',\n      'child onBeforeMount',\n      'child onMounted',\n      'mid onMounted',\n      'root onMounted',\n    ])\n\n    calls.length = 0\n\n    // update\n    count.value++\n    await nextTick()\n    expect(calls).toEqual([\n      'root onBeforeUpdate',\n      'mid onBeforeUpdate',\n      'child onBeforeUpdate',\n      'child onUpdated',\n      'mid onUpdated',\n      'root onUpdated',\n    ])\n\n    calls.length = 0\n\n    // unmount\n    render(null, root)\n    expect(calls).toEqual([\n      'root onBeforeUnmount',\n      'mid onBeforeUnmount',\n      'child onBeforeUnmount',\n      'child onUnmounted',\n      'mid onUnmounted',\n      'root onUnmounted',\n    ])\n  })\n\n  test('mixins', () => {\n    const calls: string[] = []\n    const mixinA = defineComponent({\n      data() {\n        return {\n          a: 1,\n        }\n      },\n      created(this: any) {\n        calls.push('mixinA created')\n        expect(this.a).toBe(1)\n        expect(this.b).toBe(2)\n        expect(this.c).toBe(4)\n      },\n      mounted() {\n        calls.push('mixinA mounted')\n      },\n    })\n    const mixinB = defineComponent({\n      props: {\n        bP: {\n          type: String,\n        },\n      },\n      data() {\n        return {\n          b: 2,\n        }\n      },\n      created(this: any) {\n        calls.push('mixinB created')\n        expect(this.a).toBe(1)\n        expect(this.b).toBe(2)\n        expect(this.bP).toBeUndefined()\n        expect(this.c).toBe(4)\n        expect(this.cP1).toBeUndefined()\n      },\n      mounted() {\n        calls.push('mixinB mounted')\n      },\n    })\n    const mixinC = defineComponent({\n      props: ['cP1', 'cP2'],\n      data() {\n        return {\n          c: 3,\n        }\n      },\n      created() {\n        calls.push('mixinC created')\n        // component data() should overwrite mixin field with same key\n        expect(this.c).toBe(4)\n        expect(this.cP1).toBeUndefined()\n      },\n      mounted() {\n        calls.push('mixinC mounted')\n      },\n    })\n    const Comp = defineComponent({\n      props: {\n        aaa: String,\n      },\n      mixins: [mixinA, mixinB, mixinC],\n      data() {\n        return {\n          c: 4,\n          z: 4,\n        }\n      },\n      created() {\n        calls.push('comp created')\n        expect(this.a).toBe(1)\n        expect(this.b).toBe(2)\n        expect(this.bP).toBeUndefined()\n        expect(this.c).toBe(4)\n        expect(this.cP2).toBeUndefined()\n        expect(this.z).toBe(4)\n      },\n      mounted() {\n        calls.push('comp mounted')\n      },\n      render() {\n        return `${this.a}${this.b}${this.c}`\n      },\n    })\n    expect(renderToString(h(Comp))).toBe(`124`)\n    expect(calls).toEqual([\n      'mixinA created',\n      'mixinB created',\n      'mixinC created',\n      'comp created',\n      'mixinA mounted',\n      'mixinB mounted',\n      'mixinC mounted',\n      'comp mounted',\n    ])\n  })\n\n  test('render from mixin', () => {\n    const Comp = {\n      mixins: [\n        {\n          render: () => 'from mixin',\n        },\n      ],\n    }\n    expect(renderToString(h(Comp))).toBe('from mixin')\n  })\n\n  test('chained mixins in extends', () => {\n    const calls: string[] = []\n    const mixinA = {\n      beforeCreate() {\n        calls.push('mixinA beforeCreate')\n      },\n      created() {\n        calls.push('mixinA created')\n      },\n    }\n\n    const extendA = {\n      mixins: [mixinA],\n      beforeCreate() {\n        calls.push('extendA beforeCreate')\n      },\n      created() {\n        calls.push('extendA created')\n      },\n    }\n\n    const Comp = {\n      extends: extendA,\n      render: () => '123',\n      beforeCreate() {\n        calls.push('self beforeCreate')\n      },\n      created() {\n        calls.push('self created')\n      },\n    }\n\n    expect(renderToString(h(Comp))).toBe(`123`)\n    expect(calls).toEqual([\n      'mixinA beforeCreate',\n      'extendA beforeCreate',\n      'self beforeCreate',\n      'mixinA created',\n      'extendA created',\n      'self created',\n    ])\n  })\n\n  test('unlikely mixin usage', () => {\n    const MixinA = {\n      data() {},\n    }\n    const MixinB = {\n      data() {},\n    }\n    defineComponent({\n      // since the user will want to type the mixins themselves.\n      mixins: [defineComponent(MixinA), defineComponent(MixinB)],\n      data() {},\n    })\n  })\n\n  test('chained extends in mixins', () => {\n    const calls: string[] = []\n\n    const extendA = {\n      beforeCreate() {\n        calls.push('extendA beforeCreate')\n      },\n      created() {\n        calls.push('extendA created')\n      },\n    }\n\n    const mixinA = {\n      extends: extendA,\n      beforeCreate() {\n        calls.push('mixinA beforeCreate')\n      },\n      created() {\n        calls.push('mixinA created')\n      },\n    }\n\n    const Comp = {\n      mixins: [mixinA],\n      render: () => '123',\n      beforeCreate() {\n        calls.push('self beforeCreate')\n      },\n      created() {\n        calls.push('self created')\n      },\n    }\n\n    expect(renderToString(h(Comp))).toBe(`123`)\n    expect(calls).toEqual([\n      'extendA beforeCreate',\n      'mixinA beforeCreate',\n      'self beforeCreate',\n      'extendA created',\n      'mixinA created',\n      'self created',\n    ])\n  })\n\n  test('extends', () => {\n    const calls: string[] = []\n    const Base = defineComponent({\n      data() {\n        return {\n          a: 1,\n          b: 1,\n        }\n      },\n      methods: {\n        sayA() {},\n      },\n      mounted(this: any) {\n        expect(this.a).toBe(1)\n        expect(this.b).toBe(2)\n        calls.push('base')\n      },\n    })\n    const Comp = defineComponent({\n      extends: Base,\n      data() {\n        return {\n          b: 2,\n        }\n      },\n      mounted() {\n        calls.push('comp')\n      },\n      render() {\n        return `${this.a}${this.b}`\n      },\n    })\n\n    expect(renderToString(h(Comp))).toBe(`12`)\n    expect(calls).toEqual(['base', 'comp'])\n  })\n\n  test('extends with mixins', () => {\n    const calls: string[] = []\n    const Base = defineComponent({\n      data() {\n        return {\n          a: 1,\n          x: 'base',\n        }\n      },\n      methods: {\n        sayA() {},\n      },\n      mounted(this: any) {\n        expect(this.a).toBe(1)\n        expect(this.b).toBeTruthy()\n        expect(this.c).toBe(2)\n        calls.push('base')\n      },\n    })\n    const Mixin = defineComponent({\n      data() {\n        return {\n          b: true,\n          x: 'mixin',\n        }\n      },\n      mounted(this: any) {\n        expect(this.a).toBe(1)\n        expect(this.b).toBeTruthy()\n        expect(this.c).toBe(2)\n        calls.push('mixin')\n      },\n    })\n    const Comp = defineComponent({\n      extends: Base,\n      mixins: [Mixin],\n      data() {\n        return {\n          c: 2,\n        }\n      },\n      mounted() {\n        calls.push('comp')\n      },\n      render() {\n        return `${this.a}${this.b}${this.c}${this.x}`\n      },\n    })\n\n    expect(renderToString(h(Comp))).toBe(`1true2mixin`)\n    expect(calls).toEqual(['base', 'mixin', 'comp'])\n  })\n\n  test('beforeCreate/created in extends and mixins', () => {\n    const calls: string[] = []\n    const BaseA = {\n      beforeCreate() {\n        calls.push('beforeCreateA')\n      },\n      created() {\n        calls.push('createdA')\n      },\n    }\n    const BaseB = {\n      extends: BaseA,\n      beforeCreate() {\n        calls.push('beforeCreateB')\n      },\n      created() {\n        calls.push('createdB')\n      },\n    }\n\n    const MixinA = {\n      beforeCreate() {\n        calls.push('beforeCreateC')\n      },\n      created() {\n        calls.push('createdC')\n      },\n    }\n    const MixinB = {\n      mixins: [MixinA],\n      beforeCreate() {\n        calls.push('beforeCreateD')\n      },\n      created() {\n        calls.push('createdD')\n      },\n    }\n\n    const Comp = {\n      extends: BaseB,\n      mixins: [MixinB],\n      beforeCreate() {\n        calls.push('selfBeforeCreate')\n      },\n      created() {\n        calls.push('selfCreated')\n      },\n      render() {},\n    }\n\n    renderToString(h(Comp))\n    expect(calls).toEqual([\n      'beforeCreateA',\n      'beforeCreateB',\n      'beforeCreateC',\n      'beforeCreateD',\n      'selfBeforeCreate',\n      'createdA',\n      'createdB',\n      'createdC',\n      'createdD',\n      'selfCreated',\n    ])\n  })\n\n  test('flatten merged options', async () => {\n    const MixinBase = {\n      msg1: 'base',\n    }\n    const ExtendsBase = {\n      msg2: 'base',\n    }\n    const Mixin = {\n      mixins: [MixinBase],\n    }\n    const Extends = {\n      extends: ExtendsBase,\n    }\n    const Comp = defineComponent({\n      extends: defineComponent(Extends),\n      mixins: [defineComponent(Mixin)],\n      render() {\n        return `${this.$options.msg1},${this.$options.msg2}`\n      },\n    })\n\n    expect(renderToString(h(Comp))).toBe('base,base')\n  })\n\n  test('extends template', () => {\n    const Comp = {\n      extends: {\n        template: `<h1>Foo</h1>`,\n      },\n    }\n\n    const root = document.createElement('div') as any\n    domRender(h(Comp), root)\n    expect(root.innerHTML).toBe(`<h1>Foo</h1>`)\n  })\n\n  test('options defined in component have higher priority', async () => {\n    const Mixin = {\n      msg1: 'base',\n    }\n    const Extends = {\n      msg2: 'base',\n    }\n    const Comp = defineComponent({\n      msg1: 'local',\n      msg2: 'local',\n      extends: defineComponent(Extends),\n      mixins: [defineComponent(Mixin)],\n      render() {\n        return `${this.$options.msg1},${this.$options.msg2}`\n      },\n    })\n\n    expect(renderToString(h(Comp))).toBe('local,local')\n  })\n\n  test('accessing setup() state from options', async () => {\n    const Comp = defineComponent({\n      setup() {\n        return {\n          count: ref(0),\n        }\n      },\n      data() {\n        return {\n          plusOne: (this as any).count + 1,\n        }\n      },\n      computed: {\n        plusTwo(): number {\n          return this.count + 2\n        },\n      },\n      methods: {\n        inc() {\n          this.count++\n        },\n      },\n      render() {\n        return h(\n          'div',\n          {\n            onClick: this.inc,\n          },\n          `${this.count},${this.plusOne},${this.plusTwo}`,\n        )\n      },\n    })\n    const root = nodeOps.createElement('div')\n    render(h(Comp), root)\n    expect(serializeInner(root)).toBe(`<div>0,1,2</div>`)\n\n    triggerEvent(root.children[0] as TestElement, 'click')\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<div>1,1,3</div>`)\n  })\n\n  // #1016\n  test('watcher initialization should be deferred in mixins', async () => {\n    const mixin1 = {\n      data() {\n        return {\n          mixin1Data: 'mixin1',\n        }\n      },\n      methods: {},\n    }\n\n    const watchSpy = vi.fn()\n    const mixin2 = {\n      watch: {\n        mixin3Data: watchSpy,\n      },\n    }\n\n    const mixin3 = {\n      data() {\n        return {\n          mixin3Data: 'mixin3',\n        }\n      },\n      methods: {},\n    }\n\n    let vm: any\n    const Comp = {\n      mixins: [mixin1, mixin2, mixin3],\n      render() {},\n      created() {\n        vm = this\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(Comp), root)\n\n    // should have no warnings\n    vm.mixin3Data = 'hello'\n    await nextTick()\n    expect(watchSpy.mock.calls[0].slice(0, 2)).toEqual(['hello', 'mixin3'])\n  })\n\n  test('injection from closest ancestor', () => {\n    const Root = defineComponent({\n      provide: {\n        a: 'root',\n      },\n      render() {\n        return [h(Mid), ' ', h(MidWithProvide), ' ', h(MidWithMixinProvide)]\n      },\n    })\n\n    const Mid = {\n      render() {\n        return h(Child)\n      },\n    } as any\n\n    const MidWithProvide = {\n      provide: {\n        a: 'midWithProvide',\n      },\n      render() {\n        return h(Child)\n      },\n    } as any\n\n    const mixin = {\n      provide: {\n        a: 'midWithMixinProvide',\n      },\n    }\n\n    const MidWithMixinProvide = {\n      mixins: [mixin],\n      render() {\n        return h(Child)\n      },\n    } as any\n\n    const Child = {\n      inject: ['a'],\n      render() {\n        return this.a\n      },\n    } as any\n\n    expect(renderToString(h(Root))).toBe(\n      'root midWithProvide midWithMixinProvide',\n    )\n  })\n\n  describe('options merge strategies', () => {\n    test('this.$options.data', () => {\n      const mixin = {\n        data() {\n          return { foo: 1, bar: 2 }\n        },\n      }\n      createApp({\n        mixins: [mixin],\n        data() {\n          return {\n            foo: 3,\n            baz: 4,\n          }\n        },\n        created() {\n          expect(this.$options.data).toBeInstanceOf(Function)\n          expect(this.$options.data()).toEqual({\n            foo: 3,\n            bar: 2,\n            baz: 4,\n          })\n        },\n        render: () => null,\n      }).mount(nodeOps.createElement('div'))\n    })\n\n    test('this.$options.inject', () => {\n      const mixin = {\n        inject: ['a'],\n      }\n      const app = createApp({\n        mixins: [mixin],\n        inject: { b: 'b', c: { from: 'd' } },\n        created() {\n          expect(this.$options.inject.a).toEqual('a')\n          expect(this.$options.inject.b).toEqual('b')\n          expect(this.$options.inject.c).toEqual({ from: 'd' })\n          expect(this.a).toBe(1)\n          expect(this.b).toBe(2)\n          expect(this.c).toBe(3)\n        },\n        render: () => null,\n      })\n\n      app.provide('a', 1)\n      app.provide('b', 2)\n      app.provide('d', 3)\n      app.mount(nodeOps.createElement('div'))\n    })\n\n    test('this.$options.provide', () => {\n      const mixin = {\n        provide: {\n          a: 1,\n        },\n      }\n      createApp({\n        mixins: [mixin],\n        provide() {\n          return {\n            b: 2,\n          }\n        },\n        created() {\n          expect(this.$options.provide).toBeInstanceOf(Function)\n          expect(this.$options.provide()).toEqual({ a: 1, b: 2 })\n        },\n        render: () => null,\n      }).mount(nodeOps.createElement('div'))\n    })\n\n    test('this.$options[lifecycle-name]', () => {\n      const mixin = {\n        mounted() {},\n        beforeUnmount() {},\n        unmounted() {},\n      }\n      createApp({\n        mixins: [mixin],\n        mounted() {},\n        beforeUnmount() {},\n        unmounted() {},\n        created() {\n          expect(this.$options.mounted).toBeInstanceOf(Array)\n          expect(this.$options.mounted.length).toBe(2)\n          expect(this.$options.beforeUnmount).toBeInstanceOf(Array)\n          expect(this.$options.beforeUnmount.length).toBe(2)\n          expect(this.$options.unmounted).toBeInstanceOf(Array)\n          expect(this.$options.unmounted.length).toBe(2)\n        },\n        render: () => null,\n      }).mount(nodeOps.createElement('div'))\n    })\n\n    test('this.$options[asset-name]', () => {\n      const mixin = {\n        components: {\n          a: {},\n        },\n        directives: {\n          d1: {},\n        },\n      }\n      createApp({\n        mixins: [mixin],\n        components: {\n          b: {},\n        },\n        directives: {\n          d2: {},\n        },\n        created() {\n          expect('a' in this.$options.components).toBe(true)\n          expect('b' in this.$options.components).toBe(true)\n          expect('d1' in this.$options.directives).toBe(true)\n          expect('d2' in this.$options.directives).toBe(true)\n        },\n        render: () => null,\n      }).mount(nodeOps.createElement('div'))\n    })\n\n    test('this.$options.methods', () => {\n      const mixin = {\n        methods: {\n          fn1() {},\n        },\n      }\n      createApp({\n        mixins: [mixin],\n        methods: {\n          fn2() {},\n        },\n        created() {\n          expect(this.$options.methods.fn1).toBeInstanceOf(Function)\n          expect(this.$options.methods.fn2).toBeInstanceOf(Function)\n        },\n        render: () => null,\n      }).mount(nodeOps.createElement('div'))\n    })\n\n    test('this.$options.computed', () => {\n      const mixin = {\n        computed: {\n          c1() {},\n        },\n      }\n      createApp({\n        mixins: [mixin],\n        computed: {\n          c2() {},\n        },\n        created() {\n          expect(this.$options.computed.c1).toBeInstanceOf(Function)\n          expect(this.$options.computed.c2).toBeInstanceOf(Function)\n        },\n        render: () => null,\n      }).mount(nodeOps.createElement('div'))\n    })\n\n    // #2791\n    test('modify $options in the beforeCreate hook', async () => {\n      const count = ref(0)\n      const mixin = {\n        data() {\n          return { foo: 1 }\n        },\n        beforeCreate(this: any) {\n          if (!this.$options.computed) {\n            this.$options.computed = {}\n          }\n          this.$options.computed.value = () => count.value\n        },\n      }\n      const root = nodeOps.createElement('div')\n      createApp({\n        mixins: [mixin],\n        render(this: any) {\n          return this.value\n        },\n      }).mount(root)\n\n      expect(serializeInner(root)).toBe('0')\n\n      count.value++\n      await nextTick()\n      expect(serializeInner(root)).toBe('1')\n    })\n  })\n\n  describe('warnings', () => {\n    test('Expected a function as watch handler', () => {\n      const Comp = {\n        watch: {\n          foo: 'notExistingMethod',\n          foo2: {\n            handler: 'notExistingMethod2',\n          },\n        },\n        render() {},\n      }\n\n      const root = nodeOps.createElement('div')\n      render(h(Comp), root)\n\n      expect(\n        'Invalid watch handler specified by key \"notExistingMethod\"',\n      ).toHaveBeenWarned()\n      expect(\n        'Invalid watch handler specified by key \"notExistingMethod2\"',\n      ).toHaveBeenWarned()\n    })\n\n    test('Invalid watch option', () => {\n      const Comp = {\n        watch: { foo: true },\n        render() {},\n      }\n\n      const root = nodeOps.createElement('div')\n      // @ts-expect-error\n      render(h(Comp), root)\n\n      expect('Invalid watch option: \"foo\"').toHaveBeenWarned()\n    })\n\n    test('computed with setter and no getter', () => {\n      const Comp = {\n        computed: {\n          foo: {\n            set() {},\n          },\n        },\n        render() {},\n      }\n\n      const root = nodeOps.createElement('div')\n      render(h(Comp), root)\n      expect('Computed property \"foo\" has no getter.').toHaveBeenWarned()\n    })\n\n    test('assigning to computed with no setter', () => {\n      let instance: any\n      const Comp = {\n        computed: {\n          foo: {\n            get() {},\n          },\n        },\n        mounted() {\n          instance = this\n        },\n        render() {},\n      }\n\n      const root = nodeOps.createElement('div')\n      render(h(Comp), root)\n      instance.foo = 1\n      expect(\n        'Write operation failed: computed property \"foo\" is readonly',\n      ).toHaveBeenWarned()\n    })\n\n    test('inject property is already declared in props', () => {\n      const Comp = {\n        data() {\n          return {\n            a: 1,\n          }\n        },\n        provide() {\n          return {\n            a: this.a,\n          }\n        },\n        render() {\n          return [h(ChildA)]\n        },\n      } as any\n      const ChildA = {\n        props: { a: Number },\n        inject: ['a'],\n        render() {\n          return this.a\n        },\n      } as any\n\n      const root = nodeOps.createElement('div')\n      render(h(Comp), root)\n      expect(\n        `Inject property \"a\" is already defined in Props.`,\n      ).toHaveBeenWarned()\n    })\n\n    test('methods property is not a function', () => {\n      const Comp = {\n        methods: {\n          foo: 1,\n        },\n        render() {},\n      }\n\n      const root = nodeOps.createElement('div')\n      render(h(Comp), root)\n      expect(\n        `Method \"foo\" has type \"number\" in the component definition. ` +\n          `Did you reference the function correctly?`,\n      ).toHaveBeenWarned()\n    })\n\n    test('methods property is already declared in props', () => {\n      const Comp = {\n        props: {\n          foo: Number,\n        },\n        methods: {\n          foo() {},\n        },\n        render() {},\n      }\n\n      const root = nodeOps.createElement('div')\n      render(h(Comp), root)\n      expect(\n        `Methods property \"foo\" is already defined in Props.`,\n      ).toHaveBeenWarned()\n    })\n\n    test('methods property is already declared in inject', () => {\n      const Comp = {\n        data() {\n          return {\n            a: 1,\n          }\n        },\n        provide() {\n          return {\n            a: this.a,\n          }\n        },\n        render() {\n          return [h(ChildA)]\n        },\n      } as any\n      const ChildA = {\n        methods: {\n          a: () => null,\n        },\n        inject: ['a'],\n        render() {\n          return this.a\n        },\n      } as any\n\n      const root = nodeOps.createElement('div')\n      render(h(Comp), root)\n      expect(\n        `Methods property \"a\" is already defined in Inject.`,\n      ).toHaveBeenWarned()\n    })\n\n    test('data property is already declared in props', () => {\n      const Comp = {\n        props: { foo: Number },\n        data: () => ({\n          foo: 1,\n        }),\n        render() {},\n      }\n\n      const root = nodeOps.createElement('div')\n      render(h(Comp), root)\n      expect(\n        `Data property \"foo\" is already defined in Props.`,\n      ).toHaveBeenWarned()\n    })\n\n    test('data property is already declared in inject', () => {\n      const Comp = {\n        data() {\n          return {\n            a: 1,\n          }\n        },\n        provide() {\n          return {\n            a: this.a,\n          }\n        },\n        render() {\n          return [h(ChildA)]\n        },\n      } as any\n      const ChildA = {\n        data() {\n          return {\n            a: 1,\n          }\n        },\n        inject: ['a'],\n        render() {\n          return this.a\n        },\n      } as any\n\n      const root = nodeOps.createElement('div')\n      render(h(Comp), root)\n      expect(\n        `Data property \"a\" is already defined in Inject.`,\n      ).toHaveBeenWarned()\n    })\n\n    test('data property is already declared in methods', () => {\n      const Comp = {\n        data: () => ({\n          foo: 1,\n        }),\n        methods: {\n          foo() {},\n        },\n        render() {},\n      }\n\n      const root = nodeOps.createElement('div')\n      render(h(Comp), root)\n      expect(\n        `Data property \"foo\" is already defined in Methods.`,\n      ).toHaveBeenWarned()\n    })\n\n    test('computed property is already declared in props', () => {\n      const Comp = {\n        props: { foo: Number },\n        computed: {\n          foo() {},\n        },\n        render() {},\n      }\n\n      const root = nodeOps.createElement('div')\n      render(h(Comp), root)\n      expect(\n        `Computed property \"foo\" is already defined in Props.`,\n      ).toHaveBeenWarned()\n    })\n\n    test('computed property is already declared in inject', () => {\n      const Comp = {\n        data() {\n          return {\n            a: 1,\n          }\n        },\n        provide() {\n          return {\n            a: this.a,\n          }\n        },\n        render() {\n          return [h(ChildA)]\n        },\n      } as any\n      const ChildA = {\n        computed: {\n          a: {\n            get() {},\n            set() {},\n          },\n        },\n        inject: ['a'],\n        render() {\n          return this.a\n        },\n      } as any\n\n      const root = nodeOps.createElement('div')\n      render(h(Comp), root)\n      expect(\n        `Computed property \"a\" is already defined in Inject.`,\n      ).toHaveBeenWarned()\n    })\n\n    test('computed property is already declared in methods', () => {\n      const Comp = {\n        computed: {\n          foo() {},\n        },\n        methods: {\n          foo() {},\n        },\n        render() {},\n      }\n\n      const root = nodeOps.createElement('div')\n      render(h(Comp), root)\n      expect(\n        `Computed property \"foo\" is already defined in Methods.`,\n      ).toHaveBeenWarned()\n    })\n\n    test('computed property is already declared in data', () => {\n      const Comp = {\n        data: () => ({\n          foo: 1,\n        }),\n        computed: {\n          foo() {},\n        },\n        render() {},\n      }\n\n      const root = nodeOps.createElement('div')\n      render(h(Comp), root)\n      expect(\n        `Computed property \"foo\" is already defined in Data.`,\n      ).toHaveBeenWarned()\n    })\n  })\n})\n"
  },
  {
    "path": "packages/runtime-core/__tests__/apiSetupContext.spec.ts",
    "content": "import { reactive, ref } from '@vue/reactivity'\nimport {\n  type TestElement,\n  defineComponent,\n  h,\n  nextTick,\n  nodeOps,\n  render,\n  renderToString,\n  serializeInner,\n  triggerEvent,\n  watchEffect,\n} from '@vue/runtime-test'\n\ndescribe('api: setup context', () => {\n  it('should expose return values to template render context', () => {\n    const Comp = defineComponent({\n      setup() {\n        return {\n          // ref should auto-unwrap\n          ref: ref('foo'),\n          // object exposed as-is\n          object: reactive({ msg: 'bar' }),\n          // primitive value exposed as-is\n          value: 'baz',\n        }\n      },\n      render() {\n        return `${this.ref} ${this.object.msg} ${this.value}`\n      },\n    })\n    expect(renderToString(h(Comp))).toMatch(`foo bar baz`)\n  })\n\n  it('should support returning render function', () => {\n    const Comp = {\n      setup() {\n        return () => {\n          return h('div', 'hello')\n        }\n      },\n    }\n    expect(renderToString(h(Comp))).toMatch(`hello`)\n  })\n\n  it('props', async () => {\n    const count = ref(0)\n    let dummy\n\n    const Parent = {\n      render: () => h(Child, { count: count.value }),\n    }\n\n    const Child = defineComponent({\n      props: { count: Number },\n      setup(props) {\n        watchEffect(() => {\n          dummy = props.count\n        })\n        return () => h('div', props.count)\n      },\n    })\n\n    const root = nodeOps.createElement('div')\n    render(h(Parent), root)\n    expect(serializeInner(root)).toMatch(`<div>0</div>`)\n    expect(dummy).toBe(0)\n\n    // props should be reactive\n    count.value++\n    await nextTick()\n    expect(serializeInner(root)).toMatch(`<div>1</div>`)\n    expect(dummy).toBe(1)\n  })\n\n  it('context.attrs', async () => {\n    const toggle = ref(true)\n\n    const Parent = {\n      render: () => h(Child, toggle.value ? { id: 'foo' } : { class: 'baz' }),\n    }\n\n    const Child = {\n      // explicit empty props declaration\n      // puts everything received in attrs\n      // disable implicit fallthrough\n      inheritAttrs: false,\n      setup(props: any, { attrs }: any) {\n        return () => h('div', attrs)\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(Parent), root)\n    expect(serializeInner(root)).toMatch(`<div id=\"foo\"></div>`)\n\n    // should update even though it's not reactive\n    toggle.value = false\n    await nextTick()\n    expect(serializeInner(root)).toMatch(`<div class=\"baz\"></div>`)\n  })\n\n  // #4161\n  it('context.attrs in child component slots', async () => {\n    const toggle = ref(true)\n\n    const Parent = {\n      render: () => h(Child, toggle.value ? { id: 'foo' } : { class: 'baz' }),\n    }\n\n    const Wrapper = {\n      render(this: any) {\n        return this.$slots.default()\n      },\n    }\n\n    const Child = {\n      inheritAttrs: false,\n      setup(_: any, { attrs }: any) {\n        return () => {\n          const vnode = h(Wrapper, null, {\n            default: () => [h('div', attrs)],\n            _: 1, // mark stable slots\n          })\n          vnode.dynamicChildren = [] // force optimized mode\n          return vnode\n        }\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(Parent), root)\n    expect(serializeInner(root)).toMatch(`<div id=\"foo\"></div>`)\n\n    // should update even though it's not reactive\n    toggle.value = false\n    await nextTick()\n    expect(serializeInner(root)).toMatch(`<div class=\"baz\"></div>`)\n  })\n\n  it('context.slots', async () => {\n    const id = ref('foo')\n\n    const Parent = {\n      render: () =>\n        h(Child, null, {\n          foo: () => id.value,\n          bar: () => 'bar',\n        }),\n    }\n\n    const Child = {\n      setup(props: any, { slots }: any) {\n        return () => h('div', [...slots.foo(), ...slots.bar()])\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(Parent), root)\n    expect(serializeInner(root)).toMatch(`<div>foobar</div>`)\n\n    // should update even though it's not reactive\n    id.value = 'baz'\n    await nextTick()\n    expect(serializeInner(root)).toMatch(`<div>bazbar</div>`)\n  })\n\n  it('context.emit', async () => {\n    const count = ref(0)\n    const spy = vi.fn()\n\n    const Parent = {\n      render: () =>\n        h(Child, {\n          count: count.value,\n          onInc: (newVal: number) => {\n            spy()\n            count.value = newVal\n          },\n        }),\n    }\n\n    const Child = defineComponent({\n      props: {\n        count: {\n          type: Number,\n          default: 1,\n        },\n      },\n      setup(props, { emit }) {\n        return () =>\n          h(\n            'div',\n            {\n              onClick: () => emit('inc', props.count + 1),\n            },\n            props.count,\n          )\n      },\n    })\n\n    const root = nodeOps.createElement('div')\n    render(h(Parent), root)\n    expect(serializeInner(root)).toMatch(`<div>0</div>`)\n\n    // emit should trigger parent handler\n    triggerEvent(root.children[0] as TestElement, 'click')\n    expect(spy).toHaveBeenCalled()\n    await nextTick()\n    expect(serializeInner(root)).toMatch(`<div>1</div>`)\n  })\n})\n"
  },
  {
    "path": "packages/runtime-core/__tests__/apiSetupHelpers.spec.ts",
    "content": "import {\n  type ComponentInternalInstance,\n  type SetupContext,\n  Suspense,\n  computed,\n  createApp,\n  defineComponent,\n  getCurrentInstance,\n  h,\n  nodeOps,\n  onMounted,\n  render,\n  serializeInner,\n  shallowReactive,\n} from '@vue/runtime-test'\nimport {\n  createPropsRestProxy,\n  defineEmits,\n  defineExpose,\n  defineProps,\n  mergeDefaults,\n  mergeModels,\n  useAttrs,\n  useSlots,\n  withAsyncContext,\n  withDefaults,\n} from '../src/apiSetupHelpers'\nimport type { ComputedRefImpl } from '../../reactivity/src/computed'\nimport { EffectFlags, type ReactiveEffectRunner, effect } from '@vue/reactivity'\n\ndescribe('SFC <script setup> helpers', () => {\n  test('should warn runtime usage', () => {\n    defineProps()\n    expect(`defineProps() is a compiler-hint`).toHaveBeenWarned()\n\n    defineEmits()\n    expect(`defineEmits() is a compiler-hint`).toHaveBeenWarned()\n\n    defineExpose()\n    expect(`defineExpose() is a compiler-hint`).toHaveBeenWarned()\n\n    withDefaults({}, {})\n    expect(`withDefaults() is a compiler-hint`).toHaveBeenWarned()\n  })\n\n  test('useSlots / useAttrs (no args)', () => {\n    let slots: SetupContext['slots'] | undefined\n    let attrs: SetupContext['attrs'] | undefined\n    const Comp = {\n      setup() {\n        slots = useSlots()\n        attrs = useAttrs()\n        return () => {}\n      },\n    }\n    const passedAttrs = { id: 'foo' }\n    const passedSlots = {\n      default: () => {},\n      x: () => {},\n    }\n    render(h(Comp, passedAttrs, passedSlots), nodeOps.createElement('div'))\n    expect(typeof slots!.default).toBe('function')\n    expect(typeof slots!.x).toBe('function')\n    expect(attrs).toMatchObject(passedAttrs)\n  })\n\n  test('useSlots / useAttrs (with args)', () => {\n    let slots: SetupContext['slots'] | undefined\n    let attrs: SetupContext['attrs'] | undefined\n    let ctx: SetupContext | undefined\n    const Comp = defineComponent({\n      setup(_, _ctx) {\n        slots = useSlots()\n        attrs = useAttrs()\n        ctx = _ctx\n        return () => {}\n      },\n    })\n    render(h(Comp), nodeOps.createElement('div'))\n    expect(slots).toBe(ctx!.slots)\n    expect(attrs).toBe(ctx!.attrs)\n  })\n\n  describe('mergeDefaults', () => {\n    test('object syntax', () => {\n      const merged = mergeDefaults(\n        {\n          foo: null,\n          bar: { type: String, required: false },\n          baz: String,\n        },\n        {\n          foo: 1,\n          bar: 'baz',\n          baz: 'qux',\n        },\n      )\n      expect(merged).toMatchObject({\n        foo: { default: 1 },\n        bar: { type: String, required: false, default: 'baz' },\n        baz: { type: String, default: 'qux' },\n      })\n    })\n\n    test('array syntax', () => {\n      const merged = mergeDefaults(['foo', 'bar', 'baz'], {\n        foo: 1,\n        bar: 'baz',\n        baz: 'qux',\n      })\n      expect(merged).toMatchObject({\n        foo: { default: 1 },\n        bar: { default: 'baz' },\n        baz: { default: 'qux' },\n      })\n    })\n\n    test('merging with skipFactory', () => {\n      const fn = () => {}\n      const merged = mergeDefaults(['foo', 'bar', 'baz'], {\n        foo: fn,\n        __skip_foo: true,\n      })\n      expect(merged).toMatchObject({\n        foo: { default: fn, skipFactory: true },\n      })\n    })\n\n    test('should warn missing', () => {\n      mergeDefaults({}, { foo: 1 })\n      expect(\n        `props default key \"foo\" has no corresponding declaration`,\n      ).toHaveBeenWarned()\n    })\n  })\n\n  describe('mergeModels', () => {\n    test('array syntax', () => {\n      expect(mergeModels(['foo', 'bar'], ['baz'])).toMatchObject([\n        'foo',\n        'bar',\n        'baz',\n      ])\n    })\n\n    test('object syntax', () => {\n      expect(\n        mergeModels({ foo: null, bar: { required: true } }, ['baz']),\n      ).toMatchObject({\n        foo: null,\n        bar: { required: true },\n        baz: {},\n      })\n\n      expect(\n        mergeModels(['baz'], { foo: null, bar: { required: true } }),\n      ).toMatchObject({\n        foo: null,\n        bar: { required: true },\n        baz: {},\n      })\n    })\n\n    test('overwrite', () => {\n      expect(\n        mergeModels(\n          { foo: null, bar: { required: true } },\n          { bar: {}, baz: {} },\n        ),\n      ).toMatchObject({\n        foo: null,\n        bar: {},\n        baz: {},\n      })\n    })\n  })\n\n  test('createPropsRestProxy', () => {\n    const original = shallowReactive({\n      foo: 1,\n      bar: 2,\n      baz: 3,\n    })\n    const rest = createPropsRestProxy(original, ['foo', 'bar'])\n    expect('foo' in rest).toBe(false)\n    expect('bar' in rest).toBe(false)\n    expect(rest.baz).toBe(3)\n    expect(Object.keys(rest)).toEqual(['baz'])\n\n    original.baz = 4\n    expect(rest.baz).toBe(4)\n  })\n\n  describe('withAsyncContext', () => {\n    // disable options API because applyOptions() also resets currentInstance\n    // and we want to ensure the logic works even with Options API disabled.\n    beforeEach(() => {\n      __FEATURE_OPTIONS_API__ = false\n    })\n\n    afterEach(() => {\n      __FEATURE_OPTIONS_API__ = true\n    })\n\n    test('basic', async () => {\n      const spy = vi.fn()\n\n      let beforeInstance: ComponentInternalInstance | null = null\n      let afterInstance: ComponentInternalInstance | null = null\n      let resolve: (msg: string) => void\n\n      const Comp = defineComponent({\n        async setup() {\n          let __temp: any, __restore: any\n\n          beforeInstance = getCurrentInstance()\n\n          const msg =\n            (([__temp, __restore] = withAsyncContext(\n              () =>\n                new Promise(r => {\n                  resolve = r\n                }),\n            )),\n            (__temp = await __temp),\n            __restore(),\n            __temp)\n\n          // register the lifecycle after an await statement\n          onMounted(spy)\n          afterInstance = getCurrentInstance()\n          return () => msg\n        },\n      })\n\n      const root = nodeOps.createElement('div')\n      render(\n        h(() => h(Suspense, () => h(Comp))),\n        root,\n      )\n\n      expect(spy).not.toHaveBeenCalled()\n      resolve!('hello')\n      // wait a macro task tick for all micro ticks to resolve\n      await new Promise(r => setTimeout(r))\n      // mount hook should have been called\n      expect(spy).toHaveBeenCalled()\n      // should retain same instance before/after the await call\n      expect(beforeInstance).toBe(afterInstance)\n      expect(serializeInner(root)).toBe('hello')\n    })\n\n    test('should not leak instance to user microtasks after restore', async () => {\n      let leakedToUserMicrotask = false\n\n      const Comp = defineComponent({\n        async setup() {\n          let __temp: any, __restore: any\n          ;[__temp, __restore] = withAsyncContext(() => Promise.resolve())\n          __temp = await __temp\n          __restore()\n\n          Promise.resolve().then(() => {\n            leakedToUserMicrotask = getCurrentInstance() !== null\n          })\n\n          return () => ''\n        },\n      })\n\n      const root = nodeOps.createElement('div')\n      render(\n        h(() => h(Suspense, () => h(Comp))),\n        root,\n      )\n\n      await new Promise(r => setTimeout(r))\n      expect(leakedToUserMicrotask).toBe(false)\n    })\n\n    test('should not leak sibling instance in concurrent restores', async () => {\n      let resolveOne: () => void\n      let resolveTwo: () => void\n      let done!: () => void\n      let pending = 2\n      const ready = new Promise<void>(r => {\n        done = r\n      })\n      const seenUid: Record<'one' | 'two', number | null> = {\n        one: null,\n        two: null,\n      }\n\n      const makeComp = (name: 'one' | 'two', wait: Promise<void>) =>\n        defineComponent({\n          async setup() {\n            let __temp: any, __restore: any\n            ;[__temp, __restore] = withAsyncContext(() => wait)\n            __temp = await __temp\n            __restore()\n\n            Promise.resolve().then(() => {\n              seenUid[name] = getCurrentInstance()?.uid ?? null\n              if (--pending === 0) done()\n            })\n\n            return () => ''\n          },\n        })\n\n      const oneReady = new Promise<void>(r => {\n        resolveOne = r\n      })\n      const twoReady = new Promise<void>(r => {\n        resolveTwo = r\n      })\n      const CompOne = makeComp('one', oneReady)\n      const CompTwo = makeComp('two', twoReady)\n\n      const root = nodeOps.createElement('div')\n      render(\n        h(() => h(Suspense, () => h('div', [h(CompOne), h(CompTwo)]))),\n        root,\n      )\n\n      resolveOne!()\n      resolveTwo!()\n      await ready\n      expect(seenUid.one).toBeNull()\n      expect(seenUid.two).toBeNull()\n    })\n\n    test('error handling', async () => {\n      const spy = vi.fn()\n\n      let beforeInstance: ComponentInternalInstance | null = null\n      let afterInstance: ComponentInternalInstance | null = null\n      let reject: () => void\n\n      const Comp = defineComponent({\n        async setup() {\n          let __temp: any, __restore: any\n\n          beforeInstance = getCurrentInstance()\n          try {\n            ;[__temp, __restore] = withAsyncContext(\n              () =>\n                new Promise((_, rj) => {\n                  reject = rj\n                }),\n            )\n            __temp = await __temp\n            __restore()\n          } catch (e: any) {\n            // ignore\n          }\n          // register the lifecycle after an await statement\n          onMounted(spy)\n          afterInstance = getCurrentInstance()\n          return () => ''\n        },\n      })\n\n      const root = nodeOps.createElement('div')\n      render(\n        h(() => h(Suspense, () => h(Comp))),\n        root,\n      )\n\n      expect(spy).not.toHaveBeenCalled()\n      reject!()\n      // wait a macro task tick for all micro ticks to resolve\n      await new Promise(r => setTimeout(r))\n      // mount hook should have been called\n      expect(spy).toHaveBeenCalled()\n      // should retain same instance before/after the await call\n      expect(beforeInstance).toBe(afterInstance)\n      // instance scope should be fully restored/cleaned after async ticks\n      expect((beforeInstance!.scope as any)._on).toBe(0)\n    })\n\n    test('should not leak instance on multiple awaits', async () => {\n      let resolve: (val?: any) => void\n      let beforeInstance: ComponentInternalInstance | null = null\n      let afterInstance: ComponentInternalInstance | null = null\n      let inBandInstance: ComponentInternalInstance | null = null\n      let outOfBandInstance: ComponentInternalInstance | null = null\n\n      const ready = new Promise(r => {\n        resolve = r\n      })\n\n      async function doAsyncWork() {\n        // should still have instance\n        inBandInstance = getCurrentInstance()\n        await Promise.resolve()\n        // should not leak instance\n        outOfBandInstance = getCurrentInstance()\n      }\n\n      const Comp = defineComponent({\n        async setup() {\n          let __temp: any, __restore: any\n\n          beforeInstance = getCurrentInstance()\n\n          // first await\n          ;[__temp, __restore] = withAsyncContext(() => Promise.resolve())\n          __temp = await __temp\n          __restore()\n\n          // setup exit, instance set to null, then resumed\n          ;[__temp, __restore] = withAsyncContext(() => doAsyncWork())\n          __temp = await __temp\n          __restore()\n\n          afterInstance = getCurrentInstance()\n          return () => {\n            resolve()\n            return ''\n          }\n        },\n      })\n\n      const root = nodeOps.createElement('div')\n      render(\n        h(() => h(Suspense, () => h(Comp))),\n        root,\n      )\n\n      await ready\n      expect(inBandInstance).toBe(beforeInstance)\n      expect(outOfBandInstance).toBeNull()\n      expect(afterInstance).toBe(beforeInstance)\n      expect(getCurrentInstance()).toBeNull()\n    })\n\n    test('should not leak on multiple awaits + error', async () => {\n      let resolve: (val?: any) => void\n      const ready = new Promise(r => {\n        resolve = r\n      })\n\n      const Comp = defineComponent({\n        async setup() {\n          let __temp: any, __restore: any\n          ;[__temp, __restore] = withAsyncContext(() => Promise.resolve())\n          __temp = await __temp\n          __restore()\n          ;[__temp, __restore] = withAsyncContext(() => Promise.reject())\n          __temp = await __temp\n          __restore()\n        },\n        render() {},\n      })\n\n      const app = createApp(() => h(Suspense, () => h(Comp)))\n      app.config.errorHandler = () => {\n        resolve()\n        return false\n      }\n\n      const root = nodeOps.createElement('div')\n      app.mount(root)\n\n      await ready\n      expect(getCurrentInstance()).toBeNull()\n    })\n\n    // #4050\n    test('race conditions', async () => {\n      const uids = {\n        one: { before: NaN, after: NaN },\n        two: { before: NaN, after: NaN },\n      }\n\n      const Comp = defineComponent({\n        props: ['name'],\n        async setup(props: { name: 'one' | 'two' }) {\n          let __temp: any, __restore: any\n\n          uids[props.name].before = getCurrentInstance()!.uid\n          ;[__temp, __restore] = withAsyncContext(() => Promise.resolve())\n          __temp = await __temp\n          __restore()\n\n          uids[props.name].after = getCurrentInstance()!.uid\n          return () => ''\n        },\n      })\n\n      const app = createApp(() =>\n        h(Suspense, () =>\n          h('div', [h(Comp, { name: 'one' }), h(Comp, { name: 'two' })]),\n        ),\n      )\n      const root = nodeOps.createElement('div')\n      app.mount(root)\n\n      await new Promise(r => setTimeout(r))\n      expect(uids.one.before).not.toBe(uids.two.before)\n      expect(uids.one.before).toBe(uids.one.after)\n      expect(uids.two.before).toBe(uids.two.after)\n    })\n\n    test('should teardown in-scope effects', async () => {\n      let resolve: (val?: any) => void\n      const ready = new Promise(r => {\n        resolve = r\n      })\n\n      let c: ComputedRefImpl\n      let e: ReactiveEffectRunner\n\n      const Comp = defineComponent({\n        async setup() {\n          let __temp: any, __restore: any\n          ;[__temp, __restore] = withAsyncContext(() => Promise.resolve())\n          __temp = await __temp\n          __restore()\n\n          c = computed(() => {}) as unknown as ComputedRefImpl\n          e = effect(() => c.value)\n          // register the lifecycle after an await statement\n          onMounted(resolve)\n          return () => c.value\n        },\n      })\n\n      const app = createApp(() => h(Suspense, () => h(Comp)))\n      const root = nodeOps.createElement('div')\n      app.mount(root)\n\n      await ready\n      expect(e!.effect.flags & EffectFlags.ACTIVE).toBeTruthy()\n      expect(c!.flags & EffectFlags.TRACKING).toBeTruthy()\n\n      app.unmount()\n      expect(e!.effect.flags & EffectFlags.ACTIVE).toBeFalsy()\n      expect(c!.flags & EffectFlags.TRACKING).toBeFalsy()\n    })\n  })\n})\n"
  },
  {
    "path": "packages/runtime-core/__tests__/apiWatch.bench.ts",
    "content": "import { nextTick, ref, watch, watchEffect } from '../src'\nimport { bench } from 'vitest'\n\nbench('create watcher', () => {\n  const v = ref(100)\n  watch(v, v => {})\n})\n\n{\n  const v = ref(100)\n  watch(v, v => {})\n  let i = 0\n  bench('update ref to trigger watcher (scheduled but not executed)', () => {\n    v.value = i++\n  })\n}\n\n{\n  const v = ref(100)\n  watch(v, v => {})\n  let i = 0\n  bench('update ref to trigger watcher (executed)', async () => {\n    v.value = i++\n    return nextTick()\n  })\n}\n\n{\n  bench('create watchEffect', () => {\n    watchEffect(() => {})\n  })\n}\n\n{\n  const v = ref(100)\n  watchEffect(() => {\n    v.value\n  })\n  let i = 0\n  bench(\n    'update ref to trigger watchEffect (scheduled but not executed)',\n    () => {\n      v.value = i++\n    },\n  )\n}\n\n{\n  const v = ref(100)\n  watchEffect(() => {\n    v.value\n  })\n  let i = 0\n  bench('update ref to trigger watchEffect (executed)', async () => {\n    v.value = i++\n    await nextTick()\n  })\n}\n"
  },
  {
    "path": "packages/runtime-core/__tests__/apiWatch.spec.ts",
    "content": "import {\n  type ComponentInternalInstance,\n  type ComponentPublicInstance,\n  computed,\n  defineComponent,\n  getCurrentInstance,\n  nextTick,\n  onErrorCaptured,\n  onWatcherCleanup,\n  reactive,\n  ref,\n  watch,\n  watchEffect,\n} from '../src/index'\nimport {\n  type TestElement,\n  createApp,\n  h,\n  nodeOps,\n  onMounted,\n  render,\n  serializeInner,\n  watchPostEffect,\n  watchSyncEffect,\n} from '@vue/runtime-test'\nimport {\n  type DebuggerEvent,\n  ITERATE_KEY,\n  type Ref,\n  type ShallowRef,\n  TrackOpTypes,\n  TriggerOpTypes,\n  effectScope,\n  onScopeDispose,\n  shallowReactive,\n  shallowRef,\n  toRef,\n  triggerRef,\n} from '@vue/reactivity'\nimport { renderToString } from '@vue/server-renderer'\n\ndescribe('api: watch', () => {\n  it('effect', async () => {\n    const state = reactive({ count: 0 })\n    let dummy\n    watchEffect(() => {\n      dummy = state.count\n    })\n    expect(dummy).toBe(0)\n\n    state.count++\n    await nextTick()\n    expect(dummy).toBe(1)\n  })\n\n  it('watching single source: getter', async () => {\n    const state = reactive({ count: 0 })\n    let dummy\n    watch(\n      () => state.count,\n      (count, prevCount) => {\n        dummy = [count, prevCount]\n        // assert types\n        count + 1\n        if (prevCount) {\n          prevCount + 1\n        }\n      },\n    )\n    state.count++\n    await nextTick()\n    expect(dummy).toMatchObject([1, 0])\n  })\n\n  it('watching single source: ref', async () => {\n    const count = ref(0)\n    let dummy\n    watch(count, (count, prevCount) => {\n      dummy = [count, prevCount]\n      // assert types\n      count + 1\n      if (prevCount) {\n        prevCount + 1\n      }\n    })\n    count.value++\n    await nextTick()\n    expect(dummy).toMatchObject([1, 0])\n  })\n\n  it('watching single source: array', async () => {\n    const array = reactive([] as number[])\n    const spy = vi.fn()\n    watch(array, spy)\n    array.push(1)\n    await nextTick()\n    expect(spy).toBeCalledTimes(1)\n    expect(spy).toBeCalledWith([1], [1], expect.anything())\n  })\n\n  it('should not call functions inside a reactive source array', () => {\n    const spy1 = vi.fn()\n    const array = reactive([spy1])\n    const spy2 = vi.fn()\n    watch(array, spy2, { immediate: true })\n    expect(spy1).toBeCalledTimes(0)\n    expect(spy2).toBeCalledWith([spy1], undefined, expect.anything())\n  })\n\n  it('should not unwrap refs in a reactive source array', async () => {\n    const val = ref({ foo: 1 })\n    const array = reactive([val])\n    const spy = vi.fn()\n    watch(array, spy, { immediate: true })\n    expect(spy).toBeCalledTimes(1)\n    expect(spy).toBeCalledWith([val], undefined, expect.anything())\n\n    // deep by default\n    val.value.foo++\n    await nextTick()\n    expect(spy).toBeCalledTimes(2)\n    expect(spy).toBeCalledWith([val], [val], expect.anything())\n  })\n\n  it('should not fire if watched getter result did not change', async () => {\n    const spy = vi.fn()\n    const n = ref(0)\n    watch(() => n.value % 2, spy)\n\n    n.value++\n    await nextTick()\n    expect(spy).toBeCalledTimes(1)\n\n    n.value += 2\n    await nextTick()\n    // should not be called again because getter result did not change\n    expect(spy).toBeCalledTimes(1)\n  })\n\n  it('watching single source: computed ref', async () => {\n    const count = ref(0)\n    const plus = computed(() => count.value + 1)\n    let dummy\n    watch(plus, (count, prevCount) => {\n      dummy = [count, prevCount]\n      // assert types\n      count + 1\n      if (prevCount) {\n        prevCount + 1\n      }\n    })\n    count.value++\n    await nextTick()\n    expect(dummy).toMatchObject([2, 1])\n  })\n\n  it('watching primitive with deep: true', async () => {\n    const count = ref(0)\n    let dummy\n    watch(\n      count,\n      (c, prevCount) => {\n        dummy = [c, prevCount]\n      },\n      {\n        deep: true,\n      },\n    )\n    count.value++\n    await nextTick()\n    expect(dummy).toMatchObject([1, 0])\n  })\n\n  it('directly watching reactive object (with automatic deep: true)', async () => {\n    const src = reactive({\n      count: 0,\n    })\n    let dummy\n    watch(src, ({ count }) => {\n      dummy = count\n    })\n    src.count++\n    await nextTick()\n    expect(dummy).toBe(1)\n  })\n\n  it('directly watching reactive object with explicit deep: false', async () => {\n    const src = reactive({\n      state: {\n        count: 0,\n      },\n    })\n    let dummy\n    watch(\n      src,\n      ({ state }) => {\n        dummy = state?.count\n      },\n      {\n        deep: false,\n      },\n    )\n\n    // nested should not trigger\n    src.state.count++\n    await nextTick()\n    expect(dummy).toBe(undefined)\n\n    // root level should trigger\n    src.state = { count: 1 }\n    await nextTick()\n    expect(dummy).toBe(1)\n  })\n\n  it('directly watching reactive array with explicit deep: false', async () => {\n    const val = ref(1)\n    const array: any[] = reactive([val])\n    const spy = vi.fn()\n    watch(array, spy, { immediate: true, deep: false })\n    expect(spy).toBeCalledTimes(1)\n    expect(spy).toBeCalledWith([val], undefined, expect.anything())\n\n    val.value++\n    await nextTick()\n    expect(spy).toBeCalledTimes(1)\n\n    array[1] = 2\n    await nextTick()\n    expect(spy).toBeCalledTimes(2)\n    expect(spy).toBeCalledWith([val, 2], [val, 2], expect.anything())\n  })\n\n  // #9916\n  it('watching shallow reactive array with deep: false', async () => {\n    class foo {\n      prop1: ShallowRef<string> = shallowRef('')\n      prop2: string = ''\n    }\n\n    const obj1 = new foo()\n    const obj2 = new foo()\n\n    const collection = shallowReactive([obj1, obj2])\n    const cb = vi.fn()\n    watch(collection, cb, { deep: false })\n\n    collection[0].prop1.value = 'foo'\n    await nextTick()\n    // should not trigger\n    expect(cb).toBeCalledTimes(0)\n\n    collection.push(new foo())\n    await nextTick()\n    // should trigger on array self mutation\n    expect(cb).toBeCalledTimes(1)\n  })\n\n  it('should still respect deep: true on shallowReactive source', async () => {\n    const obj = reactive({ a: 1 })\n    const arr = shallowReactive([obj])\n\n    let dummy\n    watch(\n      arr,\n      () => {\n        dummy = arr[0].a\n      },\n      { deep: true },\n    )\n\n    obj.a++\n    await nextTick()\n    expect(dummy).toBe(2)\n  })\n\n  it('watching multiple sources', async () => {\n    const state = reactive({ count: 1 })\n    const count = ref(1)\n    const plus = computed(() => count.value + 1)\n\n    let dummy\n    watch([() => state.count, count, plus], (vals, oldVals) => {\n      dummy = [vals, oldVals]\n      // assert types\n      vals.concat(1)\n      oldVals.concat(1)\n    })\n\n    state.count++\n    count.value++\n    await nextTick()\n    expect(dummy).toMatchObject([\n      [2, 2, 3],\n      [1, 1, 2],\n    ])\n  })\n\n  it('watching multiple sources: undefined initial values and immediate: true', async () => {\n    const a = ref()\n    const b = ref()\n    let called = false\n    watch(\n      [a, b],\n      ([newA, newB], [oldA, oldB]) => {\n        called = true\n        expect([newA, newB]).toMatchObject([undefined, undefined])\n        expect([oldA, oldB]).toMatchObject([undefined, undefined])\n      },\n      { immediate: true },\n    )\n    await nextTick()\n    expect(called).toBe(true)\n  })\n\n  it('watching multiple sources: readonly array', async () => {\n    const state = reactive({ count: 1 })\n    const status = ref(false)\n\n    let dummy\n    watch([() => state.count, status] as const, (vals, oldVals) => {\n      dummy = [vals, oldVals]\n      const [count] = vals\n      const [, oldStatus] = oldVals\n      // assert types\n      count + 1\n      oldStatus === true\n    })\n\n    state.count++\n    status.value = true\n    await nextTick()\n    expect(dummy).toMatchObject([\n      [2, true],\n      [1, false],\n    ])\n  })\n\n  it('watching multiple sources: reactive object (with automatic deep: true)', async () => {\n    const src = reactive({ count: 0 })\n    let dummy\n    watch([src], ([state]) => {\n      dummy = state\n      // assert types\n      state.count === 1\n    })\n    src.count++\n    await nextTick()\n    expect(dummy).toMatchObject({ count: 1 })\n  })\n\n  it('warn invalid watch source', () => {\n    // @ts-expect-error\n    watch(1, () => {})\n    expect(`Invalid watch source`).toHaveBeenWarned()\n  })\n\n  it('warn invalid watch source: multiple sources', () => {\n    watch([1], () => {})\n    expect(`Invalid watch source`).toHaveBeenWarned()\n  })\n\n  it('stopping the watcher (effect)', async () => {\n    const state = reactive({ count: 0 })\n    let dummy\n    const stop = watchEffect(() => {\n      dummy = state.count\n    })\n    expect(dummy).toBe(0)\n\n    stop()\n    state.count++\n    await nextTick()\n    // should not update\n    expect(dummy).toBe(0)\n  })\n\n  it('stopping the watcher (SSR)', async () => {\n    let dummy = 0\n    const count = ref<number>(1)\n    const captureValue = (value: number) => {\n      dummy = value\n    }\n    const watchCallback = vi.fn(newValue => {\n      captureValue(newValue)\n    })\n    const Comp = defineComponent({\n      created() {\n        const getter = () => this.count\n        captureValue(getter()) // sets dummy to 1\n        const stop = this.$watch(getter, watchCallback)\n        stop()\n        this.count = 2 // shouldn't trigger side effect\n      },\n      render() {\n        return h('div', this.count)\n      },\n      setup() {\n        return { count }\n      },\n    })\n    let html\n    html = await renderToString(h(Comp))\n    // should not throw here\n    expect(html).toBe(`<div>2</div>`)\n    expect(watchCallback).not.toHaveBeenCalled()\n    expect(dummy).toBe(1)\n    await nextTick()\n    count.value = 3 // shouldn't trigger side effect\n    await nextTick()\n    expect(watchCallback).not.toHaveBeenCalled()\n    expect(dummy).toBe(1)\n  })\n\n  it('stopping the watcher (with source)', async () => {\n    const state = reactive({ count: 0 })\n    let dummy\n    const stop = watch(\n      () => state.count,\n      count => {\n        dummy = count\n      },\n    )\n\n    state.count++\n    await nextTick()\n    expect(dummy).toBe(1)\n\n    stop()\n    state.count++\n    await nextTick()\n    // should not update\n    expect(dummy).toBe(1)\n  })\n\n  it('cleanup registration (effect)', async () => {\n    const state = reactive({ count: 0 })\n    const cleanup = vi.fn()\n    let dummy\n    const stop = watchEffect(onCleanup => {\n      onCleanup(cleanup)\n      dummy = state.count\n    })\n    expect(dummy).toBe(0)\n\n    state.count++\n    await nextTick()\n    expect(cleanup).toHaveBeenCalledTimes(1)\n    expect(dummy).toBe(1)\n\n    stop()\n    expect(cleanup).toHaveBeenCalledTimes(2)\n  })\n\n  it('cleanup registration (with source)', async () => {\n    const count = ref(0)\n    const cleanup = vi.fn()\n    let dummy\n    const stop = watch(count, (count, prevCount, onCleanup) => {\n      onCleanup(cleanup)\n      dummy = count\n    })\n\n    count.value++\n    await nextTick()\n    expect(cleanup).toHaveBeenCalledTimes(0)\n    expect(dummy).toBe(1)\n\n    count.value++\n    await nextTick()\n    expect(cleanup).toHaveBeenCalledTimes(1)\n    expect(dummy).toBe(2)\n\n    stop()\n    expect(cleanup).toHaveBeenCalledTimes(2)\n  })\n\n  it('onWatcherCleanup', async () => {\n    const count = ref(0)\n    const cleanupEffect = vi.fn()\n    const cleanupWatch = vi.fn()\n\n    const stopEffect = watchEffect(() => {\n      onWatcherCleanup(cleanupEffect)\n      count.value\n    })\n    const stopWatch = watch(count, () => {\n      onWatcherCleanup(cleanupWatch)\n    })\n\n    count.value++\n    await nextTick()\n    expect(cleanupEffect).toHaveBeenCalledTimes(1)\n    expect(cleanupWatch).toHaveBeenCalledTimes(0)\n\n    count.value++\n    await nextTick()\n    expect(cleanupEffect).toHaveBeenCalledTimes(2)\n    expect(cleanupWatch).toHaveBeenCalledTimes(1)\n\n    stopEffect()\n    expect(cleanupEffect).toHaveBeenCalledTimes(3)\n    stopWatch()\n    expect(cleanupWatch).toHaveBeenCalledTimes(2)\n  })\n\n  it('flush timing: pre (default)', async () => {\n    const count = ref(0)\n    const count2 = ref(0)\n\n    let callCount = 0\n    let result1\n    let result2\n    const assertion = vi.fn((count, count2Value) => {\n      callCount++\n      // on mount, the watcher callback should be called before DOM render\n      // on update, should be called before the count is updated\n      const expectedDOM = callCount === 1 ? `` : `${count - 1}`\n      result1 = serializeInner(root) === expectedDOM\n\n      // in a pre-flush callback, all state should have been updated\n      const expectedState = callCount - 1\n      result2 = count === expectedState && count2Value === expectedState\n    })\n\n    const Comp = {\n      setup() {\n        watchEffect(() => {\n          assertion(count.value, count2.value)\n        })\n        return () => count.value\n      },\n    }\n    const root = nodeOps.createElement('div')\n    render(h(Comp), root)\n    expect(assertion).toHaveBeenCalledTimes(1)\n    expect(result1).toBe(true)\n    expect(result2).toBe(true)\n\n    count.value++\n    count2.value++\n    await nextTick()\n    // two mutations should result in 1 callback execution\n    expect(assertion).toHaveBeenCalledTimes(2)\n    expect(result1).toBe(true)\n    expect(result2).toBe(true)\n  })\n\n  it('flush timing: post', async () => {\n    const count = ref(0)\n    let result\n    const assertion = vi.fn(count => {\n      result = serializeInner(root) === `${count}`\n    })\n\n    const Comp = {\n      setup() {\n        watchEffect(\n          () => {\n            assertion(count.value)\n          },\n          { flush: 'post' },\n        )\n        return () => count.value\n      },\n    }\n    const root = nodeOps.createElement('div')\n    render(h(Comp), root)\n    expect(assertion).toHaveBeenCalledTimes(1)\n    expect(result).toBe(true)\n\n    count.value++\n    await nextTick()\n    expect(assertion).toHaveBeenCalledTimes(2)\n    expect(result).toBe(true)\n  })\n\n  it('watchPostEffect', async () => {\n    const count = ref(0)\n    let result\n    const assertion = vi.fn(count => {\n      result = serializeInner(root) === `${count}`\n    })\n\n    const Comp = {\n      setup() {\n        watchPostEffect(() => {\n          assertion(count.value)\n        })\n        return () => count.value\n      },\n    }\n    const root = nodeOps.createElement('div')\n    render(h(Comp), root)\n    expect(assertion).toHaveBeenCalledTimes(1)\n    expect(result).toBe(true)\n\n    count.value++\n    await nextTick()\n    expect(assertion).toHaveBeenCalledTimes(2)\n    expect(result).toBe(true)\n  })\n\n  it('flush timing: sync', async () => {\n    const count = ref(0)\n    const count2 = ref(0)\n\n    let callCount = 0\n    let result1\n    let result2\n    const assertion = vi.fn(count => {\n      callCount++\n      // on mount, the watcher callback should be called before DOM render\n      // on update, should be called before the count is updated\n      const expectedDOM = callCount === 1 ? `` : `${count - 1}`\n      result1 = serializeInner(root) === expectedDOM\n\n      // in a sync callback, state mutation on the next line should not have\n      // executed yet on the 2nd call, but will be on the 3rd call.\n      const expectedState = callCount < 3 ? 0 : 1\n      result2 = count2.value === expectedState\n    })\n\n    const Comp = {\n      setup() {\n        watchEffect(\n          () => {\n            assertion(count.value)\n          },\n          {\n            flush: 'sync',\n          },\n        )\n        return () => count.value\n      },\n    }\n    const root = nodeOps.createElement('div')\n    render(h(Comp), root)\n    expect(assertion).toHaveBeenCalledTimes(1)\n    expect(result1).toBe(true)\n    expect(result2).toBe(true)\n\n    count.value++\n    count2.value++\n    await nextTick()\n    expect(assertion).toHaveBeenCalledTimes(3)\n    expect(result1).toBe(true)\n    expect(result2).toBe(true)\n  })\n\n  it('watchSyncEffect', async () => {\n    const count = ref(0)\n    const count2 = ref(0)\n\n    let callCount = 0\n    let result1\n    let result2\n    const assertion = vi.fn(count => {\n      callCount++\n      // on mount, the watcher callback should be called before DOM render\n      // on update, should be called before the count is updated\n      const expectedDOM = callCount === 1 ? `` : `${count - 1}`\n      result1 = serializeInner(root) === expectedDOM\n\n      // in a sync callback, state mutation on the next line should not have\n      // executed yet on the 2nd call, but will be on the 3rd call.\n      const expectedState = callCount < 3 ? 0 : 1\n      result2 = count2.value === expectedState\n    })\n\n    const Comp = {\n      setup() {\n        watchSyncEffect(() => {\n          assertion(count.value)\n        })\n        return () => count.value\n      },\n    }\n    const root = nodeOps.createElement('div')\n    render(h(Comp), root)\n    expect(assertion).toHaveBeenCalledTimes(1)\n    expect(result1).toBe(true)\n    expect(result2).toBe(true)\n\n    count.value++\n    count2.value++\n    await nextTick()\n    expect(assertion).toHaveBeenCalledTimes(3)\n    expect(result1).toBe(true)\n    expect(result2).toBe(true)\n  })\n\n  it('should not fire on component unmount w/ flush: post', async () => {\n    const toggle = ref(true)\n    const cb = vi.fn()\n    const Comp = {\n      setup() {\n        watch(toggle, cb, { flush: 'post' })\n      },\n      render() {},\n    }\n    const App = {\n      render() {\n        return toggle.value ? h(Comp) : null\n      },\n    }\n    render(h(App), nodeOps.createElement('div'))\n    expect(cb).not.toHaveBeenCalled()\n    toggle.value = false\n    await nextTick()\n    expect(cb).not.toHaveBeenCalled()\n  })\n\n  // #2291\n  it('should not fire on component unmount w/ flush: pre', async () => {\n    const toggle = ref(true)\n    const cb = vi.fn()\n    const Comp = {\n      setup() {\n        watch(toggle, cb, { flush: 'pre' })\n      },\n      render() {},\n    }\n    const App = {\n      render() {\n        return toggle.value ? h(Comp) : null\n      },\n    }\n    render(h(App), nodeOps.createElement('div'))\n    expect(cb).not.toHaveBeenCalled()\n    toggle.value = false\n    await nextTick()\n    expect(cb).not.toHaveBeenCalled()\n  })\n\n  // #7030\n  it('should not fire on child component unmount w/ flush: pre', async () => {\n    const visible = ref(true)\n    const cb = vi.fn()\n    const Parent = defineComponent({\n      props: ['visible'],\n      render() {\n        return visible.value ? h(Comp) : null\n      },\n    })\n    const Comp = {\n      setup() {\n        watch(visible, cb, { flush: 'pre' })\n      },\n      render() {},\n    }\n    const App = {\n      render() {\n        return h(Parent, {\n          visible: visible.value,\n        })\n      },\n    }\n    render(h(App), nodeOps.createElement('div'))\n    expect(cb).not.toHaveBeenCalled()\n    visible.value = false\n    await nextTick()\n    expect(cb).not.toHaveBeenCalled()\n  })\n\n  // #7030\n  it('flush: pre watcher in child component should not fire before parent update', async () => {\n    const b = ref(0)\n    const calls: string[] = []\n\n    const Comp = {\n      setup() {\n        watch(\n          () => b.value,\n          val => {\n            calls.push('watcher child')\n          },\n          { flush: 'pre' },\n        )\n        return () => {\n          b.value\n          calls.push('render child')\n        }\n      },\n    }\n\n    const Parent = {\n      props: ['a'],\n      setup() {\n        watch(\n          () => b.value,\n          val => {\n            calls.push('watcher parent')\n          },\n          { flush: 'pre' },\n        )\n        return () => {\n          b.value\n          calls.push('render parent')\n          return h(Comp)\n        }\n      },\n    }\n\n    const App = {\n      render() {\n        return h(Parent, {\n          a: b.value,\n        })\n      },\n    }\n\n    render(h(App), nodeOps.createElement('div'))\n    expect(calls).toEqual(['render parent', 'render child'])\n\n    b.value++\n    await nextTick()\n    expect(calls).toEqual([\n      'render parent',\n      'render child',\n      'watcher parent',\n      'render parent',\n      'watcher child',\n      'render child',\n    ])\n  })\n\n  // #1763\n  it('flush: pre watcher watching props should fire before child update', async () => {\n    const a = ref(0)\n    const b = ref(0)\n    const c = ref(0)\n    const calls: string[] = []\n\n    const Comp = {\n      props: ['a', 'b'],\n      setup(props: any) {\n        watch(\n          () => props.a + props.b,\n          () => {\n            calls.push('watcher 1')\n            c.value++\n          },\n          { flush: 'pre' },\n        )\n\n        // #1777 chained pre-watcher\n        watch(\n          c,\n          () => {\n            calls.push('watcher 2')\n          },\n          { flush: 'pre' },\n        )\n        return () => {\n          c.value\n          calls.push('render')\n        }\n      },\n    }\n\n    const App = {\n      render() {\n        return h(Comp, { a: a.value, b: b.value })\n      },\n    }\n\n    render(h(App), nodeOps.createElement('div'))\n    expect(calls).toEqual(['render'])\n\n    // both props are updated\n    // should trigger pre-flush watcher first and only once\n    // then trigger child render\n    a.value++\n    b.value++\n    await nextTick()\n    expect(calls).toEqual(['render', 'watcher 1', 'watcher 2', 'render'])\n  })\n\n  // #5721\n  it('flush: pre triggered in component setup should be buffered and called before mounted', () => {\n    const count = ref(0)\n    const calls: string[] = []\n    const App = {\n      render() {},\n      setup() {\n        watch(\n          count,\n          () => {\n            calls.push('watch ' + count.value)\n          },\n          { flush: 'pre' },\n        )\n        onMounted(() => {\n          calls.push('mounted')\n        })\n        // mutate multiple times\n        count.value++\n        count.value++\n        count.value++\n      },\n    }\n    render(h(App), nodeOps.createElement('div'))\n    expect(calls).toMatchObject(['watch 3', 'mounted'])\n  })\n\n  // #1852\n  it('flush: post watcher should fire after template refs updated', async () => {\n    const toggle = ref(false)\n    let dom: TestElement | null = null\n\n    const App = {\n      setup() {\n        const domRef = ref<TestElement | null>(null)\n\n        watch(\n          toggle,\n          () => {\n            dom = domRef.value\n          },\n          { flush: 'post' },\n        )\n\n        return () => {\n          return toggle.value ? h('p', { ref: domRef }) : null\n        }\n      },\n    }\n\n    render(h(App), nodeOps.createElement('div'))\n    expect(dom).toBe(null)\n\n    toggle.value = true\n    await nextTick()\n    expect(dom!.tag).toBe('p')\n  })\n\n  it('deep', async () => {\n    const state = reactive({\n      nested: {\n        count: ref(0),\n      },\n      array: [1, 2, 3],\n      map: new Map([\n        ['a', 1],\n        ['b', 2],\n      ]),\n      set: new Set([1, 2, 3]),\n    })\n\n    let dummy\n    watch(\n      () => state,\n      state => {\n        dummy = [\n          state.nested.count,\n          state.array[0],\n          state.map.get('a'),\n          state.set.has(1),\n        ]\n      },\n      { deep: true },\n    )\n\n    state.nested.count++\n    await nextTick()\n    expect(dummy).toEqual([1, 1, 1, true])\n\n    // nested array mutation\n    state.array[0] = 2\n    await nextTick()\n    expect(dummy).toEqual([1, 2, 1, true])\n\n    // nested map mutation\n    state.map.set('a', 2)\n    await nextTick()\n    expect(dummy).toEqual([1, 2, 2, true])\n\n    // nested set mutation\n    state.set.delete(1)\n    await nextTick()\n    expect(dummy).toEqual([1, 2, 2, false])\n  })\n\n  it('watching deep ref', async () => {\n    const count = ref(0)\n    const double = computed(() => count.value * 2)\n    const state = reactive([count, double])\n\n    let dummy\n    watch(\n      () => state,\n      state => {\n        dummy = [state[0].value, state[1].value]\n      },\n      { deep: true },\n    )\n\n    count.value++\n    await nextTick()\n    expect(dummy).toEqual([1, 2])\n  })\n\n  it('deep with symbols', async () => {\n    const symbol1 = Symbol()\n    const symbol2 = Symbol()\n    const symbol3 = Symbol()\n    const symbol4 = Symbol()\n\n    const raw: any = {\n      [symbol1]: {\n        [symbol2]: 1,\n      },\n    }\n\n    Object.defineProperty(raw, symbol3, {\n      writable: true,\n      enumerable: false,\n      value: 1,\n    })\n\n    const state = reactive(raw)\n    const spy = vi.fn()\n\n    watch(() => state, spy, { deep: true })\n\n    await nextTick()\n    expect(spy).toHaveBeenCalledTimes(0)\n\n    state[symbol1][symbol2] = 2\n    await nextTick()\n    expect(spy).toHaveBeenCalledTimes(1)\n\n    // Non-enumerable properties don't trigger deep watchers\n    state[symbol3] = 3\n    await nextTick()\n    expect(spy).toHaveBeenCalledTimes(1)\n\n    // Adding a new symbol property\n    state[symbol4] = 1\n    await nextTick()\n    expect(spy).toHaveBeenCalledTimes(2)\n\n    // Removing a symbol property\n    delete state[symbol4]\n    await nextTick()\n    expect(spy).toHaveBeenCalledTimes(3)\n  })\n\n  it('immediate', async () => {\n    const count = ref(0)\n    const cb = vi.fn()\n    watch(count, cb, { immediate: true })\n    expect(cb).toHaveBeenCalledTimes(1)\n    count.value++\n    await nextTick()\n    expect(cb).toHaveBeenCalledTimes(2)\n  })\n\n  it('immediate: triggers when initial value is null', async () => {\n    const state = ref(null)\n    const spy = vi.fn()\n    watch(() => state.value, spy, { immediate: true })\n    expect(spy).toHaveBeenCalled()\n  })\n\n  it('immediate: triggers when initial value is undefined', async () => {\n    const state = ref()\n    const spy = vi.fn()\n    watch(() => state.value, spy, { immediate: true })\n    expect(spy).toHaveBeenCalledWith(undefined, undefined, expect.any(Function))\n    state.value = 3\n    await nextTick()\n    expect(spy).toHaveBeenCalledTimes(2)\n    // testing if undefined can trigger the watcher\n    state.value = undefined\n    await nextTick()\n    expect(spy).toHaveBeenCalledTimes(3)\n    // it shouldn't trigger if the same value is set\n    state.value = undefined\n    await nextTick()\n    expect(spy).toHaveBeenCalledTimes(3)\n  })\n\n  it('warn immediate option when using effect', async () => {\n    const count = ref(0)\n    let dummy\n    watchEffect(\n      () => {\n        dummy = count.value\n      },\n      // @ts-expect-error\n      { immediate: false },\n    )\n    expect(dummy).toBe(0)\n    expect(`\"immediate\" option is only respected`).toHaveBeenWarned()\n\n    count.value++\n    await nextTick()\n    expect(dummy).toBe(1)\n  })\n\n  it('warn and not respect deep option when using effect', async () => {\n    const arr = ref([1, [2]])\n    const spy = vi.fn()\n    watchEffect(\n      () => {\n        spy()\n        return arr\n      },\n      // @ts-expect-error\n      { deep: true },\n    )\n    expect(spy).toHaveBeenCalledTimes(1)\n    ;(arr.value[1] as Array<number>)[0] = 3\n    await nextTick()\n    expect(spy).toHaveBeenCalledTimes(1)\n    expect(`\"deep\" option is only respected`).toHaveBeenWarned()\n  })\n\n  it('onTrack', async () => {\n    const events: DebuggerEvent[] = []\n    let dummy\n    const onTrack = vi.fn((e: DebuggerEvent) => {\n      events.push(e)\n    })\n    const obj = reactive({ foo: 1, bar: 2 })\n    watchEffect(\n      () => {\n        dummy = [obj.foo, 'bar' in obj, Object.keys(obj)]\n      },\n      { onTrack },\n    )\n    await nextTick()\n    expect(dummy).toEqual([1, true, ['foo', 'bar']])\n    expect(onTrack).toHaveBeenCalledTimes(3)\n    expect(events).toMatchObject([\n      {\n        target: obj,\n        type: TrackOpTypes.GET,\n        key: 'foo',\n      },\n      {\n        target: obj,\n        type: TrackOpTypes.HAS,\n        key: 'bar',\n      },\n      {\n        target: obj,\n        type: TrackOpTypes.ITERATE,\n        key: ITERATE_KEY,\n      },\n    ])\n  })\n\n  it('onTrigger', async () => {\n    const events: DebuggerEvent[] = []\n    let dummy\n    const onTrigger = vi.fn((e: DebuggerEvent) => {\n      events.push(e)\n    })\n    const obj = reactive<{ foo?: number }>({ foo: 1 })\n    watchEffect(\n      () => {\n        dummy = obj.foo\n      },\n      { onTrigger },\n    )\n    await nextTick()\n    expect(dummy).toBe(1)\n\n    obj.foo!++\n    await nextTick()\n    expect(dummy).toBe(2)\n    expect(onTrigger).toHaveBeenCalledTimes(1)\n    expect(events[0]).toMatchObject({\n      type: TriggerOpTypes.SET,\n      key: 'foo',\n      oldValue: 1,\n      newValue: 2,\n    })\n\n    delete obj.foo\n    await nextTick()\n    expect(dummy).toBeUndefined()\n    expect(onTrigger).toHaveBeenCalledTimes(2)\n    expect(events[1]).toMatchObject({\n      type: TriggerOpTypes.DELETE,\n      key: 'foo',\n      oldValue: 2,\n    })\n  })\n\n  it('should work sync', () => {\n    const v = ref(1)\n    let calls = 0\n\n    watch(\n      v,\n      () => {\n        ++calls\n      },\n      {\n        flush: 'sync',\n      },\n    )\n\n    expect(calls).toBe(0)\n    v.value++\n    expect(calls).toBe(1)\n  })\n\n  test('should force trigger on triggerRef when watching a shallow ref', async () => {\n    const v = shallowRef({ a: 1 })\n    let sideEffect = 0\n    watch(v, obj => {\n      sideEffect = obj.a\n    })\n\n    v.value = v.value\n    await nextTick()\n    // should not trigger\n    expect(sideEffect).toBe(0)\n\n    v.value.a++\n    await nextTick()\n    // should not trigger\n    expect(sideEffect).toBe(0)\n\n    triggerRef(v)\n    await nextTick()\n    // should trigger now\n    expect(sideEffect).toBe(2)\n  })\n\n  test('should force trigger on triggerRef when watching multiple sources: shallow ref array', async () => {\n    const v = shallowRef([] as any)\n    const spy = vi.fn()\n    watch([v], () => {\n      spy()\n    })\n\n    v.value.push(1)\n    triggerRef(v)\n\n    await nextTick()\n    // should trigger now\n    expect(spy).toHaveBeenCalledTimes(1)\n  })\n\n  test('should force trigger on triggerRef with toRef from reactive', async () => {\n    const foo = reactive({ bar: 1 })\n    const bar = toRef(foo, 'bar')\n    const spy = vi.fn()\n\n    watchEffect(() => {\n      bar.value\n      spy()\n    })\n\n    expect(spy).toHaveBeenCalledTimes(1)\n\n    triggerRef(bar)\n\n    await nextTick()\n    // should trigger now\n    expect(spy).toHaveBeenCalledTimes(2)\n  })\n\n  // #2125\n  test('watchEffect should not recursively trigger itself', async () => {\n    const spy = vi.fn()\n    const price = ref(10)\n    const history = ref<number[]>([])\n    watchEffect(() => {\n      history.value.push(price.value)\n      spy()\n    })\n    await nextTick()\n    expect(spy).toHaveBeenCalledTimes(1)\n  })\n\n  // #2231\n  test('computed refs should not trigger watch if value has no change', async () => {\n    const spy = vi.fn()\n    const source = ref(0)\n    const price = computed(() => source.value === 0)\n    watch(price, spy)\n    source.value++\n    await nextTick()\n    source.value++\n    await nextTick()\n    expect(spy).toHaveBeenCalledTimes(1)\n  })\n\n  // https://github.com/vuejs/core/issues/2381\n  test('$watch should always register its effects with its own instance', async () => {\n    let instance: ComponentInternalInstance | null\n    let _show: Ref<boolean>\n\n    const Child = defineComponent({\n      render: () => h('div'),\n      mounted() {\n        instance = getCurrentInstance()\n      },\n      unmounted() {},\n    })\n\n    const Comp = defineComponent({\n      setup() {\n        const comp = ref<ComponentPublicInstance | undefined>()\n        const show = ref(true)\n        _show = show\n        return { comp, show }\n      },\n      render() {\n        return this.show\n          ? h(Child, {\n              ref: vm => void (this.comp = vm as ComponentPublicInstance),\n            })\n          : null\n      },\n      mounted() {\n        // this call runs while Comp is currentInstance, but\n        // the effect for this `$watch` should nonetheless be registered with Child\n        this.comp!.$watch(\n          () => this.show,\n          () => void 0,\n        )\n      },\n    })\n\n    render(h(Comp), nodeOps.createElement('div'))\n\n    expect(instance!).toBeDefined()\n    expect(instance!.scope.effects).toBeInstanceOf(Array)\n    // includes the component's own render effect AND the watcher effect\n    expect(instance!.scope.effects.length).toBe(2)\n\n    _show!.value = false\n\n    await nextTick()\n    await nextTick()\n\n    expect(instance!.scope.effects.length).toBe(0)\n  })\n\n  test('this.$watch should pass `this.proxy` to watch source as the first argument ', () => {\n    let instance: any\n    const source = vi.fn()\n\n    const Comp = defineComponent({\n      render() {},\n      created(this: any) {\n        instance = this\n        this.$watch(source, function () {})\n      },\n    })\n\n    const root = nodeOps.createElement('div')\n    createApp(Comp).mount(root)\n\n    expect(instance).toBeDefined()\n    expect(source.mock.calls.some(args => args.includes(instance)))\n  })\n\n  test('should not leak `this.proxy` to setup()', () => {\n    const source = vi.fn()\n\n    const Comp = defineComponent({\n      render() {},\n      setup() {\n        watch(source, () => {})\n      },\n    })\n\n    const root = nodeOps.createElement('div')\n    createApp(Comp).mount(root)\n    // should not have any arguments\n    expect(source.mock.calls[0]).toMatchObject([])\n  })\n\n  // #2728\n  test('pre watcher callbacks should not track dependencies', async () => {\n    const a = ref(0)\n    const b = ref(0)\n    const updated = vi.fn()\n\n    const Child = defineComponent({\n      props: ['a'],\n      updated,\n      watch: {\n        a() {\n          b.value\n        },\n      },\n      render() {\n        return h('div', this.a)\n      },\n    })\n\n    const Parent = defineComponent({\n      render() {\n        return h(Child, { a: a.value })\n      },\n    })\n\n    const root = nodeOps.createElement('div')\n    createApp(Parent).mount(root)\n\n    a.value++\n    await nextTick()\n    expect(updated).toHaveBeenCalledTimes(1)\n\n    b.value++\n    await nextTick()\n    // should not track b as dependency of Child\n    expect(updated).toHaveBeenCalledTimes(1)\n  })\n\n  test('watching keypath', async () => {\n    const spy = vi.fn()\n    const Comp = defineComponent({\n      render() {},\n      data() {\n        return {\n          a: {\n            b: 1,\n          },\n        }\n      },\n      watch: {\n        'a.b': spy,\n      },\n      created(this: any) {\n        this.$watch('a.b', spy)\n      },\n      mounted(this: any) {\n        this.a.b++\n      },\n    })\n\n    const root = nodeOps.createElement('div')\n    createApp(Comp).mount(root)\n\n    await nextTick()\n    expect(spy).toHaveBeenCalledTimes(2)\n  })\n\n  it('watching sources: ref<any[]>', async () => {\n    const foo = ref([1])\n    const spy = vi.fn()\n    watch(foo, () => {\n      spy()\n    })\n    foo.value = foo.value.slice()\n    await nextTick()\n    expect(spy).toBeCalledTimes(1)\n  })\n\n  it('watching multiple sources: computed', async () => {\n    let count = 0\n    const value = ref('1')\n    const plus = computed(() => !!value.value)\n    watch([plus], () => {\n      count++\n    })\n    value.value = '2'\n    await nextTick()\n    expect(plus.value).toBe(true)\n    expect(count).toBe(0)\n  })\n\n  // #4158\n  test('watch should not register in owner component if created inside detached scope', () => {\n    let instance: ComponentInternalInstance\n    const Comp = {\n      setup() {\n        instance = getCurrentInstance()!\n        effectScope(true).run(() => {\n          watch(\n            () => 1,\n            () => {},\n          )\n        })\n        return () => ''\n      },\n    }\n    const root = nodeOps.createElement('div')\n    createApp(Comp).mount(root)\n    // should not record watcher in detached scope and only the instance's\n    // own update effect\n    expect(instance!.scope.effects.length).toBe(1)\n  })\n\n  test('watchEffect should keep running if created in a detached scope', async () => {\n    const trigger = ref(0)\n    let countWE = 0\n    let countW = 0\n    const Comp = {\n      setup() {\n        effectScope(true).run(() => {\n          watchEffect(() => {\n            trigger.value\n            countWE++\n          })\n          watch(trigger, () => countW++)\n        })\n        return () => ''\n      },\n    }\n    const root = nodeOps.createElement('div')\n    render(h(Comp), root)\n    // only watchEffect as ran so far\n    expect(countWE).toBe(1)\n    expect(countW).toBe(0)\n    trigger.value++\n    await nextTick()\n    // both watchers run while component is mounted\n    expect(countWE).toBe(2)\n    expect(countW).toBe(1)\n    render(null, root) // unmount\n    await nextTick()\n    trigger.value++\n    await nextTick()\n    // both watchers run again event though component has been unmounted\n    expect(countWE).toBe(3)\n    expect(countW).toBe(2)\n  })\n\n  const options = [\n    { name: 'only trigger once watch' },\n    {\n      deep: true,\n      name: 'only trigger once watch with deep',\n    },\n    {\n      flush: 'sync',\n      name: 'only trigger once watch with flush: sync',\n    },\n    {\n      flush: 'pre',\n      name: 'only trigger once watch with flush: pre',\n    },\n    {\n      immediate: true,\n      name: 'only trigger once watch with immediate',\n    },\n  ] as const\n  test.each(options)('$name', async option => {\n    const count = ref(0)\n    const cb = vi.fn()\n\n    watch(count, cb, { once: true, ...option })\n\n    count.value++\n    await nextTick()\n\n    expect(count.value).toBe(1)\n    expect(cb).toHaveBeenCalledTimes(1)\n\n    count.value++\n    await nextTick()\n\n    expect(count.value).toBe(2)\n    expect(cb).toHaveBeenCalledTimes(1)\n  })\n\n  // #5151\n  test('OnCleanup also needs to be cleaned，', async () => {\n    const spy1 = vi.fn()\n    const spy2 = vi.fn()\n    const num = ref(0)\n\n    watch(num, (value, oldValue, onCleanup) => {\n      if (value > 1) {\n        return\n      }\n      spy1()\n      onCleanup(() => {\n        // OnCleanup also needs to be cleaned\n        spy2()\n      })\n    })\n\n    num.value++\n    await nextTick()\n    expect(spy1).toHaveBeenCalledTimes(1)\n    expect(spy2).toHaveBeenCalledTimes(0)\n\n    num.value++\n    await nextTick()\n\n    expect(spy1).toHaveBeenCalledTimes(1)\n    expect(spy2).toHaveBeenCalledTimes(1)\n\n    num.value++\n    await nextTick()\n    // would not be called when value>1\n    expect(spy1).toHaveBeenCalledTimes(1)\n    expect(spy2).toHaveBeenCalledTimes(1)\n  })\n\n  it('watching reactive depth', async () => {\n    const state = reactive({\n      a: {\n        b: {\n          c: {\n            d: {\n              e: 1,\n            },\n          },\n        },\n      },\n    })\n\n    const cb = vi.fn()\n\n    watch(state, cb, { deep: 2 })\n\n    state.a.b = { c: { d: { e: 2 } } }\n    await nextTick()\n    expect(cb).toHaveBeenCalledTimes(1)\n\n    state.a.b.c = { d: { e: 3 } }\n\n    await nextTick()\n    expect(cb).toHaveBeenCalledTimes(1)\n\n    state.a.b = { c: { d: { e: 4 } } }\n\n    await nextTick()\n    expect(cb).toHaveBeenCalledTimes(2)\n  })\n\n  it('watching ref depth', async () => {\n    const state = ref({\n      a: {\n        b: 2,\n      },\n    })\n\n    const cb = vi.fn()\n\n    watch(state, cb, { deep: 1 })\n\n    state.value.a.b = 3\n    await nextTick()\n    expect(cb).toHaveBeenCalledTimes(0)\n\n    state.value.a = { b: 3 }\n    await nextTick()\n    expect(cb).toHaveBeenCalledTimes(1)\n  })\n\n  it('watching array depth', async () => {\n    const arr = ref([\n      {\n        a: {\n          b: 2,\n        },\n      },\n      {\n        a: {\n          b: 3,\n        },\n      },\n    ])\n    const cb = vi.fn()\n    watch(arr, cb, { deep: 2 })\n\n    arr.value[0].a.b = 3\n    await nextTick()\n    expect(cb).toHaveBeenCalledTimes(0)\n\n    arr.value[0].a = { b: 3 }\n    await nextTick()\n    expect(cb).toHaveBeenCalledTimes(1)\n\n    arr.value[1].a = { b: 4 }\n    await nextTick()\n    expect(cb).toHaveBeenCalledTimes(2)\n\n    arr.value.push({ a: { b: 5 } })\n    await nextTick()\n    expect(cb).toHaveBeenCalledTimes(3)\n\n    arr.value.pop()\n    await nextTick()\n    expect(cb).toHaveBeenCalledTimes(4)\n  })\n\n  test('watching the same object at different depths', async () => {\n    const arr1: any[] = reactive([[[{ foo: {} }]]])\n    const arr2 = arr1[0]\n    const arr3 = arr2[0]\n    const obj = arr3[0]\n    arr1.push(arr3)\n\n    const cb1 = vi.fn()\n    const cb2 = vi.fn()\n    const cb3 = vi.fn()\n    const cb4 = vi.fn()\n    watch(arr1, cb1, { deep: 1 })\n    watch(arr1, cb2, { deep: 2 })\n    watch(arr1, cb3, { deep: 3 })\n    watch(arr1, cb4, { deep: 4 })\n\n    await nextTick()\n    expect(cb1).toHaveBeenCalledTimes(0)\n    expect(cb2).toHaveBeenCalledTimes(0)\n    expect(cb3).toHaveBeenCalledTimes(0)\n    expect(cb4).toHaveBeenCalledTimes(0)\n\n    obj.foo = {}\n    await nextTick()\n    expect(cb1).toHaveBeenCalledTimes(0)\n    expect(cb2).toHaveBeenCalledTimes(0)\n    expect(cb3).toHaveBeenCalledTimes(1)\n    expect(cb4).toHaveBeenCalledTimes(1)\n\n    obj.foo.bar = 1\n    await nextTick()\n    expect(cb1).toHaveBeenCalledTimes(0)\n    expect(cb2).toHaveBeenCalledTimes(0)\n    expect(cb3).toHaveBeenCalledTimes(1)\n    expect(cb4).toHaveBeenCalledTimes(2)\n\n    arr3.push(obj.foo)\n    await nextTick()\n    expect(cb1).toHaveBeenCalledTimes(0)\n    expect(cb2).toHaveBeenCalledTimes(1)\n    expect(cb3).toHaveBeenCalledTimes(2)\n    expect(cb4).toHaveBeenCalledTimes(3)\n\n    obj.foo.bar = 2\n    await nextTick()\n    expect(cb1).toHaveBeenCalledTimes(0)\n    expect(cb2).toHaveBeenCalledTimes(1)\n    expect(cb3).toHaveBeenCalledTimes(3)\n    expect(cb4).toHaveBeenCalledTimes(4)\n  })\n\n  test('pause / resume', async () => {\n    const count = ref(0)\n    const cb = vi.fn()\n    const { pause, resume } = watch(count, cb)\n\n    count.value++\n    await nextTick()\n    expect(cb).toHaveBeenCalledTimes(1)\n    expect(cb).toHaveBeenLastCalledWith(1, 0, expect.any(Function))\n\n    pause()\n    count.value++\n    await nextTick()\n    expect(cb).toHaveBeenCalledTimes(1)\n    expect(cb).toHaveBeenLastCalledWith(1, 0, expect.any(Function))\n\n    resume()\n    count.value++\n    await nextTick()\n    expect(cb).toHaveBeenCalledTimes(2)\n    expect(cb).toHaveBeenLastCalledWith(3, 1, expect.any(Function))\n\n    count.value++\n    await nextTick()\n    expect(cb).toHaveBeenCalledTimes(3)\n    expect(cb).toHaveBeenLastCalledWith(4, 3, expect.any(Function))\n\n    pause()\n    count.value++\n    await nextTick()\n    expect(cb).toHaveBeenCalledTimes(3)\n    expect(cb).toHaveBeenLastCalledWith(4, 3, expect.any(Function))\n\n    resume()\n    await nextTick()\n    expect(cb).toHaveBeenCalledTimes(4)\n    expect(cb).toHaveBeenLastCalledWith(5, 4, expect.any(Function))\n  })\n\n  it('shallowReactive', async () => {\n    const state = shallowReactive({\n      msg: ref('hello'),\n      foo: {\n        a: ref(1),\n        b: 2,\n      },\n      bar: 'bar',\n    })\n\n    const spy = vi.fn()\n\n    watch(state, spy)\n\n    state.msg.value = 'hi'\n    await nextTick()\n    expect(spy).not.toHaveBeenCalled()\n\n    state.bar = 'bar2'\n    await nextTick()\n    expect(spy).toHaveBeenCalledTimes(1)\n\n    state.foo.a.value++\n    state.foo.b++\n    await nextTick()\n    expect(spy).toHaveBeenCalledTimes(1)\n\n    state.bar = 'bar3'\n    await nextTick()\n    expect(spy).toHaveBeenCalledTimes(2)\n  })\n  it('watching reactive with deep: false', async () => {\n    const state = reactive({\n      foo: {\n        a: 2,\n      },\n      bar: 'bar',\n    })\n\n    const spy = vi.fn()\n\n    watch(state, spy, { deep: false })\n\n    state.foo.a++\n    await nextTick()\n    expect(spy).toHaveBeenCalledTimes(0)\n\n    state.bar = 'bar2'\n    await nextTick()\n    expect(spy).toHaveBeenCalledTimes(1)\n  })\n\n  test(\"effect should be removed from scope's effects after it is stopped\", () => {\n    const num = ref(0)\n    let unwatch: () => void\n\n    let instance: ComponentInternalInstance\n    const Comp = {\n      setup() {\n        instance = getCurrentInstance()!\n        unwatch = watch(num, () => {\n          console.log(num.value)\n        })\n        return () => null\n      },\n    }\n    const root = nodeOps.createElement('div')\n    createApp(Comp).mount(root)\n    expect(instance!.scope.effects.length).toBe(2)\n    unwatch!()\n    expect(instance!.scope.effects.length).toBe(1)\n\n    const scope = effectScope()\n    scope.run(() => {\n      unwatch = watch(num, () => {\n        console.log(num.value)\n      })\n    })\n    expect(scope.effects.length).toBe(1)\n    unwatch!()\n    expect(scope.effects.length).toBe(0)\n\n    scope.run(() => {\n      watch(num, () => {}, { once: true, immediate: true })\n    })\n    expect(scope.effects.length).toBe(0)\n  })\n\n  // simplified case of VueUse syncRef\n  test('sync watcher should not be batched', () => {\n    const a = ref(0)\n    const b = ref(0)\n    let pauseB = false\n    watch(\n      a,\n      () => {\n        pauseB = true\n        b.value = a.value + 1\n        pauseB = false\n      },\n      { flush: 'sync' },\n    )\n    watch(\n      b,\n      () => {\n        if (!pauseB) {\n          throw new Error('should not be called')\n        }\n      },\n      { flush: 'sync' },\n    )\n\n    a.value = 1\n    expect(b.value).toBe(2)\n  })\n\n  test('watchEffect should not fire on computed deps that did not change', async () => {\n    const a = ref(0)\n    const c = computed(() => a.value % 2)\n    const spy = vi.fn()\n    watchEffect(() => {\n      spy()\n      c.value\n    })\n    expect(spy).toHaveBeenCalledTimes(1)\n    a.value += 2\n    await nextTick()\n    expect(spy).toHaveBeenCalledTimes(1)\n  })\n\n  test('circular reference', async () => {\n    const obj = { a: 1 }\n    // @ts-expect-error\n    obj.b = obj\n    const foo = ref(obj)\n    const spy = vi.fn()\n\n    watch(foo, spy, { deep: true })\n\n    // @ts-expect-error\n    foo.value.b.a = 2\n    await nextTick()\n    expect(spy).toHaveBeenCalledTimes(1)\n    expect(foo.value.a).toBe(2)\n  })\n\n  test('watch immediate error in effect scope should be caught by onErrorCaptured', async () => {\n    const warn = vi.spyOn(console, 'warn')\n    warn.mockImplementation(() => {})\n    const ERROR_IN_SCOPE = 'ERROR_IN_SCOPE'\n    const ERROR_OUT_SCOPE = 'ERROR_OUT_SCOPE'\n\n    const errors = ref<string[]>([])\n    const Comp = {\n      setup() {\n        const trigger = ref(0)\n\n        effectScope(true).run(() => {\n          watch(\n            trigger,\n            () => {\n              throw new Error(ERROR_IN_SCOPE)\n            },\n            { immediate: true },\n          )\n        })\n\n        watchEffect(() => {\n          throw new Error(ERROR_OUT_SCOPE)\n        })\n\n        return () => ''\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(\n      h(\n        {\n          setup(_, { slots }) {\n            onErrorCaptured(e => {\n              errors.value.push(e.message)\n              return false\n            })\n\n            return () => h('div', slots.default && slots.default())\n          },\n        },\n        null,\n        () => [h(Comp)],\n      ),\n      root,\n    )\n    await nextTick()\n    // only watchEffect as ran so far\n    expect(errors.value).toHaveLength(2)\n    expect(errors.value[0]).toBe(ERROR_IN_SCOPE)\n    expect(errors.value[1]).toBe(ERROR_OUT_SCOPE)\n\n    warn.mockRestore()\n  })\n\n  test('should be executed correctly', () => {\n    const v = ref(1)\n    let foo = ''\n\n    watch(\n      v,\n      () => {\n        foo += '1'\n      },\n      {\n        flush: 'sync',\n      },\n    )\n    watch(\n      v,\n      () => {\n        foo += '2'\n      },\n      {\n        flush: 'sync',\n      },\n    )\n\n    expect(foo).toBe('')\n    v.value++\n    expect(foo).toBe('12')\n  })\n\n  // 12045\n  test('sync watcher should not break pre watchers', async () => {\n    const count1 = ref(0)\n    const count2 = ref(0)\n\n    watch(\n      count1,\n      () => {\n        count2.value++\n      },\n      { flush: 'sync' },\n    )\n\n    const spy1 = vi.fn()\n    watch([count1, count2], spy1)\n\n    const spy2 = vi.fn()\n    watch(count1, spy2)\n\n    count1.value++\n\n    await nextTick()\n    expect(spy1).toHaveBeenCalled()\n    expect(spy2).toHaveBeenCalled()\n  })\n\n  // #12631\n  test('this.$watch w/ onScopeDispose', () => {\n    const onCleanup = vi.fn()\n    const toggle = ref(true)\n\n    const Comp = defineComponent({\n      render() {},\n      created(this: any) {\n        this.$watch(\n          () => 1,\n          function () {},\n        )\n        onScopeDispose(onCleanup)\n      },\n    })\n\n    const App = defineComponent({\n      render() {\n        return toggle.value ? h(Comp) : null\n      },\n    })\n\n    const root = nodeOps.createElement('div')\n    createApp(App).mount(root)\n    expect(onCleanup).toBeCalledTimes(0)\n  })\n})\n"
  },
  {
    "path": "packages/runtime-core/__tests__/component.spec.ts",
    "content": "import {\n  type ComponentInternalInstance,\n  getCurrentInstance,\n  h,\n  nodeOps,\n  render,\n} from '@vue/runtime-test'\nimport { formatComponentName } from '../src/component'\n\ndescribe('formatComponentName', () => {\n  test('default name', () => {\n    let instance: ComponentInternalInstance | null = null\n    const Comp = {\n      setup() {\n        instance = getCurrentInstance()\n        return () => null\n      },\n    }\n    render(h(Comp), nodeOps.createElement('div'))\n\n    expect(formatComponentName(null, Comp)).toBe('Anonymous')\n    expect(formatComponentName(null, Comp, true)).toBe('App')\n    expect(formatComponentName(instance, Comp)).toBe('Anonymous')\n    expect(formatComponentName(instance, Comp, true)).toBe('App')\n  })\n\n  test('name option', () => {\n    let instance: ComponentInternalInstance | null = null\n    const Comp = {\n      name: 'number-input',\n      setup() {\n        instance = getCurrentInstance()\n        return () => null\n      },\n    }\n    render(h(Comp), nodeOps.createElement('div'))\n\n    expect(formatComponentName(null, Comp)).toBe('NumberInput')\n    expect(formatComponentName(instance, Comp, true)).toBe('NumberInput')\n  })\n\n  test('self recursive name', () => {\n    let instance: ComponentInternalInstance | null = null\n    const Comp = {\n      components: {} as any,\n      setup() {\n        instance = getCurrentInstance()\n        return () => null\n      },\n    }\n    Comp.components.ToggleButton = Comp\n    render(h(Comp), nodeOps.createElement('div'))\n\n    expect(formatComponentName(instance, Comp)).toBe('ToggleButton')\n  })\n\n  test('name from parent', () => {\n    let instance: ComponentInternalInstance | null = null\n    const Comp = {\n      setup() {\n        instance = getCurrentInstance()\n        return () => null\n      },\n    }\n    const Parent = {\n      components: {\n        list_item: Comp,\n      },\n      render() {\n        return h(Comp)\n      },\n    }\n    render(h(Parent), nodeOps.createElement('div'))\n\n    expect(formatComponentName(instance, Comp)).toBe('ListItem')\n  })\n\n  test('functional components', () => {\n    const UserAvatar = () => null\n    expect(formatComponentName(null, UserAvatar)).toBe('UserAvatar')\n    UserAvatar.displayName = 'UserPicture'\n    expect(formatComponentName(null, UserAvatar)).toBe('UserPicture')\n    expect(formatComponentName(null, () => null)).toBe('Anonymous')\n  })\n\n  test('Name from file', () => {\n    const Comp = {\n      __file: './src/locale-dropdown.vue',\n    }\n\n    expect(formatComponentName(null, Comp)).toBe('LocaleDropdown')\n  })\n\n  test('inferred name', () => {\n    const Comp = {\n      __name: 'MainSidebar',\n    }\n\n    expect(formatComponentName(null, Comp)).toBe('MainSidebar')\n  })\n\n  test('global component', () => {\n    let instance: ComponentInternalInstance | null = null\n    const Comp = {\n      setup() {\n        instance = getCurrentInstance()\n        return () => null\n      },\n    }\n    render(h(Comp), nodeOps.createElement('div'))\n\n    instance!.appContext.components.FieldLabel = Comp\n\n    expect(formatComponentName(instance, Comp)).toBe('FieldLabel')\n  })\n\n  test('name precedence', () => {\n    let instance: ComponentInternalInstance | null = null\n    const Dummy = () => null\n    const Comp: Record<string, any> = {\n      components: { Dummy },\n      setup() {\n        instance = getCurrentInstance()\n        return () => null\n      },\n    }\n    const Parent = {\n      components: { Dummy } as any,\n      render() {\n        return h(Comp)\n      },\n    }\n    render(h(Parent), nodeOps.createElement('div'))\n\n    expect(formatComponentName(instance, Comp)).toBe('Anonymous')\n    expect(formatComponentName(instance, Comp, true)).toBe('App')\n\n    instance!.appContext.components.CompA = Comp\n    expect(formatComponentName(instance, Comp)).toBe('CompA')\n    expect(formatComponentName(instance, Comp, true)).toBe('CompA')\n\n    Parent.components.CompB = Comp\n    expect(formatComponentName(instance, Comp)).toBe('CompB')\n\n    Comp.components.CompC = Comp\n    expect(formatComponentName(instance, Comp)).toBe('CompC')\n\n    Comp.__file = './CompD.js'\n    expect(formatComponentName(instance, Comp)).toBe('CompD')\n\n    Comp.__name = 'CompE'\n    expect(formatComponentName(instance, Comp)).toBe('CompE')\n\n    Comp.name = 'CompF'\n    expect(formatComponentName(instance, Comp)).toBe('CompF')\n  })\n})\n"
  },
  {
    "path": "packages/runtime-core/__tests__/componentEmits.spec.ts",
    "content": "// Note: emits and listener fallthrough is tested in\n// ./rendererAttrsFallthrough.spec.ts.\n\nimport {\n  type ComponentPublicInstance,\n  createApp,\n  defineComponent,\n  h,\n  nextTick,\n  nodeOps,\n  render,\n  toHandlers,\n} from '@vue/runtime-test'\nimport { isEmitListener } from '../src/componentEmits'\n\ndescribe('component: emit', () => {\n  test('trigger handlers', () => {\n    const Foo = defineComponent({\n      render() {},\n      created() {\n        // the `emit` function is bound on component instances\n        this.$emit('foo')\n        this.$emit('bar')\n        this.$emit('!baz')\n      },\n    })\n\n    const onfoo = vi.fn()\n    const onBar = vi.fn()\n    const onBaz = vi.fn()\n    const Comp = () => h(Foo, { onfoo, onBar, ['on!baz']: onBaz })\n    render(h(Comp), nodeOps.createElement('div'))\n\n    expect(onfoo).not.toHaveBeenCalled()\n    // only capitalized or special chars are considered event listeners\n    expect(onBar).toHaveBeenCalled()\n    expect(onBaz).toHaveBeenCalled()\n  })\n\n  test('trigger camelCase handler', () => {\n    const Foo = defineComponent({\n      render() {},\n      created() {\n        this.$emit('test-event')\n      },\n    })\n\n    const fooSpy = vi.fn()\n    const Comp = () =>\n      h(Foo, {\n        onTestEvent: fooSpy,\n      })\n    render(h(Comp), nodeOps.createElement('div'))\n\n    expect(fooSpy).toHaveBeenCalledTimes(1)\n  })\n\n  test('trigger kebab-case handler', () => {\n    const Foo = defineComponent({\n      render() {},\n      created() {\n        this.$emit('test-event')\n      },\n    })\n\n    const fooSpy = vi.fn()\n    const Comp = () =>\n      h(Foo, {\n        'onTest-event': fooSpy,\n      })\n    render(h(Comp), nodeOps.createElement('div'))\n\n    expect(fooSpy).toHaveBeenCalledTimes(1)\n  })\n\n  // #3527\n  test('trigger mixed case handlers', () => {\n    const Foo = defineComponent({\n      render() {},\n      created() {\n        this.$emit('test-event')\n        this.$emit('testEvent')\n      },\n    })\n\n    const fooSpy = vi.fn()\n    const barSpy = vi.fn()\n    const Comp = () =>\n      // simulate v-on=\"obj\" usage\n      h(\n        Foo,\n        toHandlers({\n          'test-event': fooSpy,\n          testEvent: barSpy,\n        }),\n      )\n    render(h(Comp), nodeOps.createElement('div'))\n\n    expect(fooSpy).toHaveBeenCalledTimes(1)\n    expect(barSpy).toHaveBeenCalledTimes(1)\n  })\n\n  // for v-model:foo-bar usage in DOM templates\n  test('trigger hyphenated events for update:xxx events', () => {\n    const Foo = defineComponent({\n      render() {},\n      created() {\n        this.$emit('update:fooProp')\n        this.$emit('update:barProp')\n      },\n    })\n\n    const fooSpy = vi.fn()\n    const barSpy = vi.fn()\n    const Comp = () =>\n      h(Foo, {\n        'onUpdate:fooProp': fooSpy,\n        'onUpdate:bar-prop': barSpy,\n      })\n    render(h(Comp), nodeOps.createElement('div'))\n\n    expect(fooSpy).toHaveBeenCalled()\n    expect(barSpy).toHaveBeenCalled()\n  })\n\n  test('should trigger array of listeners', async () => {\n    const Child = defineComponent({\n      setup(_, { emit }) {\n        emit('foo', 1)\n        return () => h('div')\n      },\n    })\n\n    const fn1 = vi.fn()\n    const fn2 = vi.fn()\n\n    const App = {\n      setup() {\n        return () =>\n          h(Child, {\n            onFoo: [fn1, fn2],\n          })\n      },\n    }\n\n    render(h(App), nodeOps.createElement('div'))\n    expect(fn1).toHaveBeenCalledTimes(1)\n    expect(fn1).toHaveBeenCalledWith(1)\n    expect(fn2).toHaveBeenCalledTimes(1)\n    expect(fn2).toHaveBeenCalledWith(1)\n  })\n\n  test('warning for undeclared event (array)', () => {\n    const Foo = defineComponent({\n      emits: ['foo'],\n      render() {},\n      created() {\n        // @ts-expect-error\n        this.$emit('bar-baz')\n      },\n    })\n    render(h(Foo), nodeOps.createElement('div'))\n    expect(\n      `Component emitted event \"bar-baz\" but it is neither declared in the emits option nor as an \"onBarBaz\" prop`,\n    ).toHaveBeenWarned()\n  })\n\n  test('warning for undeclared event (object)', () => {\n    const Foo = defineComponent({\n      emits: {\n        foo: null,\n      },\n      render() {},\n      created() {\n        // @ts-expect-error\n        this.$emit('bar-baz')\n      },\n    })\n    render(h(Foo), nodeOps.createElement('div'))\n    expect(\n      `Component emitted event \"bar-baz\" but it is neither declared in the emits option nor as an \"onBarBaz\" prop`,\n    ).toHaveBeenWarned()\n  })\n\n  test('should not warn if has equivalent onXXX prop', () => {\n    const Foo = defineComponent({\n      props: ['onFoo'],\n      emits: [],\n      render() {},\n      created() {\n        // @ts-expect-error\n        this.$emit('foo')\n      },\n    })\n    render(h(Foo), nodeOps.createElement('div'))\n    expect(\n      `Component emitted event \"foo\" but it is neither declared`,\n    ).not.toHaveBeenWarned()\n  })\n\n  test('should not warn if has equivalent onXXX prop with kebab-cased event', () => {\n    const Foo = defineComponent({\n      props: ['onFooBar'],\n      emits: [],\n      render() {},\n      created() {\n        // @ts-expect-error\n        this.$emit('foo-bar')\n      },\n    })\n    render(h(Foo), nodeOps.createElement('div'))\n    expect(\n      `Component emitted event \"foo-bar\" but it is neither declared`,\n    ).not.toHaveBeenWarned()\n  })\n\n  test('validator warning', () => {\n    const Foo = defineComponent({\n      emits: {\n        foo: (arg: number) => arg > 0,\n      },\n      render() {},\n      created() {\n        this.$emit('foo', -1)\n      },\n    })\n    render(h(Foo), nodeOps.createElement('div'))\n    expect(`event validation failed for event \"foo\"`).toHaveBeenWarned()\n  })\n\n  test('merging from mixins', () => {\n    const mixin = {\n      emits: {\n        foo: (arg: number) => arg > 0,\n      },\n    }\n    const Foo = defineComponent({\n      mixins: [mixin],\n      render() {},\n      created() {\n        this.$emit('foo', -1)\n      },\n    })\n    render(h(Foo), nodeOps.createElement('div'))\n    expect(`event validation failed for event \"foo\"`).toHaveBeenWarned()\n  })\n\n  // #2651\n  test('should not attach normalized object when mixins do not contain emits', () => {\n    const Foo = defineComponent({\n      mixins: [{}],\n      render() {},\n      created() {\n        this.$emit('foo')\n      },\n    })\n    render(h(Foo), nodeOps.createElement('div'))\n    expect(\n      `Component emitted event \"foo\" but it is neither declared`,\n    ).not.toHaveBeenWarned()\n  })\n\n  test('.once', () => {\n    const Foo = defineComponent({\n      render() {},\n      emits: {\n        foo: null,\n        bar: null,\n      },\n      created() {\n        this.$emit('foo')\n        this.$emit('foo')\n        this.$emit('bar')\n        this.$emit('bar')\n      },\n    })\n    const fn = vi.fn()\n    const barFn = vi.fn()\n    render(\n      h(Foo, {\n        onFooOnce: fn,\n        onBarOnce: barFn,\n      }),\n      nodeOps.createElement('div'),\n    )\n    expect(fn).toHaveBeenCalledTimes(1)\n    expect(barFn).toHaveBeenCalledTimes(1)\n  })\n\n  test('.once with normal listener of the same name', () => {\n    const Foo = defineComponent({\n      render() {},\n      emits: {\n        foo: null,\n      },\n      created() {\n        this.$emit('foo')\n        this.$emit('foo')\n      },\n    })\n    const onFoo = vi.fn()\n    const onFooOnce = vi.fn()\n    render(\n      h(Foo, {\n        onFoo,\n        onFooOnce,\n      }),\n      nodeOps.createElement('div'),\n    )\n    expect(onFoo).toHaveBeenCalledTimes(2)\n    expect(onFooOnce).toHaveBeenCalledTimes(1)\n  })\n\n  test('.number modifier should work with v-model on component', () => {\n    const Foo = defineComponent({\n      render() {},\n      created() {\n        this.$emit('update:modelValue', '1')\n        this.$emit('update:foo', '2')\n      },\n    })\n\n    const fn1 = vi.fn()\n    const fn2 = vi.fn()\n\n    const Comp = () =>\n      h(Foo, {\n        modelValue: null,\n        modelModifiers: { number: true },\n        'onUpdate:modelValue': fn1,\n\n        foo: null,\n        fooModifiers: { number: true },\n        'onUpdate:foo': fn2,\n      })\n\n    render(h(Comp), nodeOps.createElement('div'))\n\n    expect(fn1).toHaveBeenCalledTimes(1)\n    expect(fn1).toHaveBeenCalledWith(1)\n    expect(fn2).toHaveBeenCalledTimes(1)\n    expect(fn2).toHaveBeenCalledWith(2)\n  })\n\n  test('.trim modifier should work with v-model on component', () => {\n    const Foo = defineComponent({\n      render() {},\n      created() {\n        this.$emit('update:modelValue', ' one ')\n        this.$emit('update:foo', '  two  ')\n      },\n    })\n\n    const fn1 = vi.fn()\n    const fn2 = vi.fn()\n\n    const Comp = () =>\n      h(Foo, {\n        modelValue: null,\n        modelModifiers: { trim: true },\n        'onUpdate:modelValue': fn1,\n\n        foo: null,\n        fooModifiers: { trim: true },\n        'onUpdate:foo': fn2,\n      })\n\n    render(h(Comp), nodeOps.createElement('div'))\n\n    expect(fn1).toHaveBeenCalledTimes(1)\n    expect(fn1).toHaveBeenCalledWith('one')\n    expect(fn2).toHaveBeenCalledTimes(1)\n    expect(fn2).toHaveBeenCalledWith('two')\n  })\n\n  test('.trim modifier should work with v-model on component for kebab-cased props and camelCased emit', () => {\n    const Foo = defineComponent({\n      render() {},\n      created() {\n        this.$emit('update:firstName', ' one ')\n      },\n    })\n\n    const fn1 = vi.fn()\n\n    const Comp = () =>\n      h(Foo, {\n        'first-name': null,\n        'first-nameModifiers': { trim: true },\n        'onUpdate:first-name': fn1,\n      })\n\n    render(h(Comp), nodeOps.createElement('div'))\n\n    expect(fn1).toHaveBeenCalledTimes(1)\n    expect(fn1).toHaveBeenCalledWith('one')\n  })\n\n  test('.trim modifier should work with v-model on component for camelCased props and kebab-cased emit', () => {\n    const Foo = defineComponent({\n      render() {},\n      created() {\n        this.$emit('update:model-value', ' one ')\n        this.$emit('update:first-name', ' two ')\n      },\n    })\n\n    const fn1 = vi.fn()\n    const fn2 = vi.fn()\n\n    const Comp = () =>\n      h(Foo, {\n        modelValue: null,\n        modelModifiers: { trim: true },\n        'onUpdate:modelValue': fn1,\n\n        firstName: null,\n        firstNameModifiers: { trim: true },\n        'onUpdate:firstName': fn2,\n      })\n\n    render(h(Comp), nodeOps.createElement('div'))\n\n    expect(fn1).toHaveBeenCalledTimes(1)\n    expect(fn1).toHaveBeenCalledWith('one')\n    expect(fn2).toHaveBeenCalledTimes(1)\n    expect(fn2).toHaveBeenCalledWith('two')\n  })\n\n  test('.trim modifier should work with v-model on component for mixed cased props and emit', () => {\n    const Foo = defineComponent({\n      render() {},\n      created() {\n        this.$emit('update:base-URL', ' one ')\n      },\n    })\n\n    const fn1 = vi.fn()\n\n    const Comp = () =>\n      h(Foo, {\n        'base-URL': null,\n        'base-URLModifiers': { trim: true },\n        'onUpdate:base-URL': fn1,\n      })\n\n    render(h(Comp), nodeOps.createElement('div'))\n\n    expect(fn1).toHaveBeenCalledTimes(1)\n    expect(fn1).toHaveBeenCalledWith('one')\n  })\n\n  test('.trim and .number modifiers should work with v-model on component', () => {\n    const Foo = defineComponent({\n      render() {},\n      created() {\n        this.$emit('update:modelValue', '    +01.2    ')\n        this.$emit('update:foo', '    1    ')\n      },\n    })\n\n    const fn1 = vi.fn()\n    const fn2 = vi.fn()\n\n    const Comp = () =>\n      h(Foo, {\n        modelValue: null,\n        modelModifiers: { trim: true, number: true },\n        'onUpdate:modelValue': fn1,\n\n        foo: null,\n        fooModifiers: { trim: true, number: true },\n        'onUpdate:foo': fn2,\n      })\n\n    render(h(Comp), nodeOps.createElement('div'))\n\n    expect(fn1).toHaveBeenCalledTimes(1)\n    expect(fn1).toHaveBeenCalledWith(1.2)\n    expect(fn2).toHaveBeenCalledTimes(1)\n    expect(fn2).toHaveBeenCalledWith(1)\n  })\n\n  test('only trim string parameter when work with v-model on component', () => {\n    const Foo = defineComponent({\n      render() {},\n      created() {\n        this.$emit('update:modelValue', ' foo ', { bar: ' bar ' })\n      },\n    })\n\n    const fn = vi.fn()\n    const Comp = () =>\n      h(Foo, {\n        modelValue: null,\n        modelModifiers: { trim: true },\n        'onUpdate:modelValue': fn,\n      })\n\n    render(h(Comp), nodeOps.createElement('div'))\n\n    expect(fn).toHaveBeenCalledTimes(1)\n    expect(fn).toHaveBeenCalledWith('foo', { bar: ' bar ' })\n  })\n\n  test('isEmitListener', () => {\n    const options = {\n      click: null,\n      'test-event': null,\n      fooBar: null,\n      FooBaz: null,\n    }\n    expect(isEmitListener(options, 'onClick')).toBe(true)\n    expect(isEmitListener(options, 'onclick')).toBe(false)\n    expect(isEmitListener(options, 'onBlick')).toBe(false)\n    // .once listeners\n    expect(isEmitListener(options, 'onClickOnce')).toBe(true)\n    expect(isEmitListener(options, 'onclickOnce')).toBe(false)\n    // kebab-case option\n    expect(isEmitListener(options, 'onTestEvent')).toBe(true)\n    // camelCase option\n    expect(isEmitListener(options, 'onFooBar')).toBe(true)\n    // PascalCase option\n    expect(isEmitListener(options, 'onFooBaz')).toBe(true)\n  })\n\n  test('does not emit after unmount', async () => {\n    const fn = vi.fn()\n    const Foo = defineComponent({\n      emits: ['closing'],\n      async beforeUnmount() {\n        await this.$nextTick()\n        this.$emit('closing', true)\n      },\n      render() {\n        return h('div')\n      },\n    })\n    const Comp = () =>\n      h(Foo, {\n        onClosing: fn,\n      })\n\n    const el = nodeOps.createElement('div')\n    render(h(Comp), el)\n    await nextTick()\n    render(null, el)\n    await nextTick()\n    expect(fn).not.toHaveBeenCalled()\n  })\n\n  test('merge string array emits', async () => {\n    const ComponentA = defineComponent({\n      emits: ['one', 'two'],\n    })\n    const ComponentB = defineComponent({\n      emits: ['three'],\n    })\n    const renderFn = vi.fn(function (this: ComponentPublicInstance) {\n      expect(this.$options.emits).toEqual(['one', 'two', 'three'])\n      return h('div')\n    })\n    const ComponentC = defineComponent({\n      render: renderFn,\n      mixins: [ComponentA, ComponentB],\n    })\n    const el = nodeOps.createElement('div')\n    expect(renderFn).toHaveBeenCalledTimes(0)\n    render(h(ComponentC), el)\n    expect(renderFn).toHaveBeenCalledTimes(1)\n  })\n\n  test('merge object emits', async () => {\n    const twoFn = vi.fn((v: unknown) => !v)\n    const ComponentA = defineComponent({\n      emits: {\n        one: null,\n        two: twoFn,\n      },\n    })\n    const ComponentB = defineComponent({\n      emits: ['three'],\n    })\n    const renderFn = vi.fn(function (this: ComponentPublicInstance) {\n      expect(this.$options.emits).toEqual({\n        one: null,\n        two: twoFn,\n        three: null,\n      })\n      expect(this.$options.emits.two).toBe(twoFn)\n      return h('div')\n    })\n    const ComponentC = defineComponent({\n      render: renderFn,\n      mixins: [ComponentA, ComponentB],\n    })\n    const el = nodeOps.createElement('div')\n    expect(renderFn).toHaveBeenCalledTimes(0)\n    render(h(ComponentC), el)\n    expect(renderFn).toHaveBeenCalledTimes(1)\n  })\n\n  test('merging emits for a component that is also used as a mixin', () => {\n    const render = () => h('div')\n    const CompA = {\n      render,\n    }\n    const validateByMixin = vi.fn(() => true)\n    const validateByGlobalMixin = vi.fn(() => true)\n\n    const mixin = {\n      emits: {\n        one: validateByMixin,\n      },\n    }\n\n    const CompB = defineComponent({\n      mixins: [mixin, CompA],\n      created(this) {\n        this.$emit('one', 1)\n      },\n      render,\n    })\n\n    const app = createApp({\n      render() {\n        return [h(CompA), h(CompB)]\n      },\n    })\n\n    app.mixin({\n      emits: {\n        one: validateByGlobalMixin,\n        two: null,\n      },\n    })\n\n    const root = nodeOps.createElement('div')\n    app.mount(root)\n    expect(validateByMixin).toHaveBeenCalledTimes(1)\n    expect(validateByGlobalMixin).not.toHaveBeenCalled()\n  })\n})\n"
  },
  {
    "path": "packages/runtime-core/__tests__/componentProps.spec.ts",
    "content": "/**\n * @vitest-environment jsdom\n */\n\nimport {\n  type ComponentInternalInstance,\n  type FunctionalComponent,\n  type SetupContext,\n  createApp,\n  defineComponent,\n  getCurrentInstance,\n  h,\n  inject,\n  nextTick,\n  nodeOps,\n  provide,\n  ref,\n  render,\n  serializeInner,\n  toRefs,\n  watch,\n} from '@vue/runtime-test'\nimport { render as domRender } from 'vue'\n\ndescribe('component props', () => {\n  test('stateful', () => {\n    let props: any\n    let attrs: any\n    let proxy: any\n\n    const Comp = defineComponent({\n      props: ['fooBar', 'barBaz'],\n      render() {\n        props = this.$props\n        attrs = this.$attrs\n        proxy = this\n      },\n    })\n\n    const root = nodeOps.createElement('div')\n    render(h(Comp, { fooBar: 1, bar: 2 }), root)\n    expect(proxy.fooBar).toBe(1)\n    expect(props).toEqual({ fooBar: 1 })\n    expect(attrs).toEqual({ bar: 2 })\n\n    // test passing kebab-case and resolving to camelCase\n    render(h(Comp, { 'foo-bar': 2, bar: 3, baz: 4 }), root)\n    expect(proxy.fooBar).toBe(2)\n    expect(props).toEqual({ fooBar: 2 })\n    expect(attrs).toEqual({ bar: 3, baz: 4 })\n\n    // test updating kebab-case should not delete it (#955)\n    render(h(Comp, { 'foo-bar': 3, bar: 3, baz: 4, barBaz: 5 }), root)\n    expect(proxy.fooBar).toBe(3)\n    expect(proxy.barBaz).toBe(5)\n    expect(props).toEqual({ fooBar: 3, barBaz: 5 })\n    expect(attrs).toEqual({ bar: 3, baz: 4 })\n\n    render(h(Comp, { qux: 5 }), root)\n    expect(proxy.fooBar).toBeUndefined()\n    // remove the props with camelCase key (#1412)\n    expect(proxy.barBaz).toBeUndefined()\n    expect(props).toEqual({})\n    expect(attrs).toEqual({ qux: 5 })\n  })\n\n  test('stateful with setup', () => {\n    let props: any\n    let attrs: any\n\n    const Comp = defineComponent({\n      props: ['foo'],\n      setup(_props, { attrs: _attrs }) {\n        return () => {\n          props = _props\n          attrs = _attrs\n        }\n      },\n    })\n\n    const root = nodeOps.createElement('div')\n    render(h(Comp, { foo: 1, bar: 2 }), root)\n    expect(props).toEqual({ foo: 1 })\n    expect(attrs).toEqual({ bar: 2 })\n\n    render(h(Comp, { foo: 2, bar: 3, baz: 4 }), root)\n    expect(props).toEqual({ foo: 2 })\n    expect(attrs).toEqual({ bar: 3, baz: 4 })\n\n    render(h(Comp, { qux: 5 }), root)\n    expect(props).toEqual({})\n    expect(attrs).toEqual({ qux: 5 })\n  })\n\n  test('functional with declaration', () => {\n    let props: any\n    let attrs: any\n\n    const Comp: FunctionalComponent = (_props, { attrs: _attrs }) => {\n      props = _props\n      attrs = _attrs\n    }\n    Comp.props = ['foo']\n\n    const root = nodeOps.createElement('div')\n    render(h(Comp, { foo: 1, bar: 2 }), root)\n    expect(props).toEqual({ foo: 1 })\n    expect(attrs).toEqual({ bar: 2 })\n\n    render(h(Comp, { foo: 2, bar: 3, baz: 4 }), root)\n    expect(props).toEqual({ foo: 2 })\n    expect(attrs).toEqual({ bar: 3, baz: 4 })\n\n    render(h(Comp, { qux: 5 }), root)\n    expect(props).toEqual({})\n    expect(attrs).toEqual({ qux: 5 })\n  })\n\n  test('functional without declaration', () => {\n    let props: any\n    let attrs: any\n    const Comp: FunctionalComponent = (_props, { attrs: _attrs }) => {\n      props = _props\n      attrs = _attrs\n    }\n    const root = nodeOps.createElement('div')\n\n    render(h(Comp, { foo: 1 }), root)\n    expect(props).toEqual({ foo: 1 })\n    expect(attrs).toEqual({ foo: 1 })\n    expect(props).toBe(attrs)\n\n    render(h(Comp, { bar: 2 }), root)\n    expect(props).toEqual({ bar: 2 })\n    expect(attrs).toEqual({ bar: 2 })\n    expect(props).toBe(attrs)\n  })\n\n  test('boolean casting', () => {\n    let proxy: any\n    const Comp = {\n      props: {\n        foo: Boolean,\n        bar: Boolean,\n        baz: Boolean,\n        qux: Boolean,\n      },\n      render() {\n        proxy = this\n      },\n    }\n    render(\n      h(Comp, {\n        // absent should cast to false\n        bar: '', // empty string should cast to true\n        baz: 'baz', // same string should cast to true\n        qux: 'ok', // other values should be left in-tact (but raise warning)\n      }),\n      nodeOps.createElement('div'),\n    )\n\n    expect(proxy.foo).toBe(false)\n    expect(proxy.bar).toBe(true)\n    expect(proxy.baz).toBe(true)\n    expect(proxy.qux).toBe('ok')\n    expect('type check failed for prop \"qux\"').toHaveBeenWarned()\n  })\n\n  test('default value', () => {\n    let proxy: any\n    const defaultFn = vi.fn(() => ({ a: 1 }))\n    const defaultBaz = vi.fn(() => ({ b: 1 }))\n\n    const Comp = {\n      props: {\n        foo: {\n          default: 1,\n        },\n        bar: {\n          default: defaultFn,\n        },\n        baz: {\n          type: Function,\n          default: defaultBaz,\n        },\n      },\n      render() {\n        proxy = this\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(Comp, { foo: 2 }), root)\n    expect(proxy.foo).toBe(2)\n    const prevBar = proxy.bar\n    expect(proxy.bar).toEqual({ a: 1 })\n    expect(proxy.baz).toEqual(defaultBaz)\n    expect(defaultFn).toHaveBeenCalledTimes(1)\n    expect(defaultBaz).toHaveBeenCalledTimes(0)\n\n    // #999: updates should not cause default factory of unchanged prop to be\n    // called again\n    render(h(Comp, { foo: 3 }), root)\n    expect(proxy.foo).toBe(3)\n    expect(proxy.bar).toEqual({ a: 1 })\n    expect(proxy.bar).toBe(prevBar)\n    expect(defaultFn).toHaveBeenCalledTimes(1)\n\n    render(h(Comp, { bar: { b: 2 } }), root)\n    expect(proxy.foo).toBe(1)\n    expect(proxy.bar).toEqual({ b: 2 })\n    expect(defaultFn).toHaveBeenCalledTimes(1)\n\n    render(h(Comp, { foo: 3, bar: { b: 3 } }), root)\n    expect(proxy.foo).toBe(3)\n    expect(proxy.bar).toEqual({ b: 3 })\n    expect(defaultFn).toHaveBeenCalledTimes(1)\n\n    render(h(Comp, { bar: { b: 4 } }), root)\n    expect(proxy.foo).toBe(1)\n    expect(proxy.bar).toEqual({ b: 4 })\n    expect(defaultFn).toHaveBeenCalledTimes(1)\n  })\n\n  test('using inject in default value factory', () => {\n    const Child = defineComponent({\n      props: {\n        test: {\n          default: () => inject('test', 'default'),\n        },\n      },\n      setup(props) {\n        return () => {\n          return h('div', props.test)\n        }\n      },\n    })\n\n    const Comp = {\n      setup() {\n        provide('test', 'injected')\n        return () => h(Child)\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(Comp), root)\n    expect(serializeInner(root)).toBe(`<div>injected</div>`)\n  })\n\n  test('optimized props updates', async () => {\n    const Child = defineComponent({\n      props: ['foo'],\n      template: `<div>{{ foo }}</div>`,\n    })\n\n    const foo = ref(1)\n    const id = ref('a')\n\n    const Comp = defineComponent({\n      setup() {\n        return {\n          foo,\n          id,\n        }\n      },\n      components: { Child },\n      template: `<Child :foo=\"foo\" :id=\"id\"/>`,\n    })\n\n    // Note this one is using the main Vue render so it can compile template\n    // on the fly\n    const root = document.createElement('div')\n    domRender(h(Comp), root)\n    expect(root.innerHTML).toBe('<div id=\"a\">1</div>')\n\n    foo.value++\n    await nextTick()\n    expect(root.innerHTML).toBe('<div id=\"a\">2</div>')\n\n    id.value = 'b'\n    await nextTick()\n    expect(root.innerHTML).toBe('<div id=\"b\">2</div>')\n  })\n\n  describe('validator', () => {\n    test('validator should be called with two arguments', async () => {\n      const mockFn = vi.fn((...args: any[]) => true)\n      const Comp = defineComponent({\n        props: {\n          foo: {\n            type: Number,\n            validator: (value, props) => mockFn(value, props),\n          },\n          bar: {\n            type: Number,\n          },\n        },\n        template: `<div />`,\n      })\n\n      // Note this one is using the main Vue render so it can compile template\n      // on the fly\n      const root = document.createElement('div')\n      domRender(h(Comp, { foo: 1, bar: 2 }), root)\n      expect(mockFn).toHaveBeenCalledWith(1, { foo: 1, bar: 2 })\n    })\n\n    test('validator should not be able to mutate other props', async () => {\n      const mockFn = vi.fn((...args: any[]) => true)\n      const Comp = defineComponent({\n        props: {\n          foo: {\n            type: Number,\n            validator: (value, props) => !!(props.bar = 1),\n          },\n          bar: {\n            type: Number,\n            validator: value => mockFn(value),\n          },\n        },\n        template: `<div />`,\n      })\n\n      // Note this one is using the main Vue render so it can compile template\n      // on the fly\n      const root = document.createElement('div')\n      domRender(h(Comp, { foo: 1, bar: 2 }), root)\n      expect(\n        `Set operation on key \"bar\" failed: target is readonly.`,\n      ).toHaveBeenWarnedLast()\n      expect(mockFn).toHaveBeenCalledWith(2)\n    })\n  })\n\n  //#12011\n  test('replace camelize with hyphenate to handle props key', () => {\n    const Comp = {\n      props: {\n        hasB4BProp: { type: Boolean, required: true },\n      },\n      setup() {\n        return () => null\n      },\n    }\n    render(\n      h('div', {}, [\n        h(Comp, {\n          'has-b-4-b-prop': true,\n        }),\n        h(Comp, {\n          'has-b4-b-prop': true,\n        }),\n      ]),\n      nodeOps.createElement('div'),\n    )\n    expect(`Missing required prop: \"hasB4BProp\"`).not.toHaveBeenWarned()\n  })\n\n  test('warn props mutation', () => {\n    let instance: ComponentInternalInstance\n    let setupProps: any\n    const Comp = {\n      props: ['foo'],\n      setup(props: any) {\n        instance = getCurrentInstance()!\n        setupProps = props\n        return () => null\n      },\n    }\n    render(h(Comp, { foo: 1 }), nodeOps.createElement('div'))\n    expect(setupProps.foo).toBe(1)\n    expect(instance!.props.foo).toBe(1)\n    setupProps.foo = 2\n    expect(`Set operation on key \"foo\" failed`).toHaveBeenWarned()\n    expect(() => {\n      ;(instance!.proxy as any).foo = 2\n    }).toThrow(TypeError)\n    expect(`Attempting to mutate prop \"foo\"`).toHaveBeenWarned()\n    // should not throw when overriding properties other than props\n    expect(() => {\n      ;(instance!.proxy as any).hasOwnProperty = () => {}\n    }).not.toThrow(TypeError)\n  })\n\n  test('warn absent required props', () => {\n    const Comp = {\n      props: {\n        bool: { type: Boolean, required: true },\n        str: { type: String, required: true },\n        num: { type: Number, required: true },\n      },\n      setup() {\n        return () => null\n      },\n    }\n    render(h(Comp), nodeOps.createElement('div'))\n    expect(`Missing required prop: \"bool\"`).toHaveBeenWarned()\n    expect(`Missing required prop: \"str\"`).toHaveBeenWarned()\n    expect(`Missing required prop: \"num\"`).toHaveBeenWarned()\n  })\n\n  test('warn on type mismatch', () => {\n    class MyClass {}\n    const Comp = {\n      props: {\n        bool: { type: Boolean },\n        str: { type: String },\n        num: { type: Number },\n        arr: { type: Array },\n        obj: { type: Object },\n        cls: { type: MyClass },\n        fn: { type: Function },\n        skipCheck: { type: [Boolean, Function], skipCheck: true },\n        empty: { type: [] },\n      },\n      setup() {\n        return () => null\n      },\n    }\n    render(\n      h(Comp, {\n        bool: 'true',\n        str: 100,\n        num: '100',\n        arr: {},\n        obj: 'false',\n        cls: {},\n        fn: true,\n        skipCheck: 'foo',\n        empty: [1, 2, 3],\n      }),\n      nodeOps.createElement('div'),\n    )\n    expect(\n      `Invalid prop: type check failed for prop \"bool\". Expected Boolean, got String`,\n    ).toHaveBeenWarned()\n    expect(\n      `Invalid prop: type check failed for prop \"str\". Expected String with value \"100\", got Number with value 100.`,\n    ).toHaveBeenWarned()\n    expect(\n      `Invalid prop: type check failed for prop \"num\". Expected Number with value 100, got String with value \"100\".`,\n    ).toHaveBeenWarned()\n    expect(\n      `Invalid prop: type check failed for prop \"arr\". Expected Array, got Object`,\n    ).toHaveBeenWarned()\n    expect(\n      `Invalid prop: type check failed for prop \"obj\". Expected Object, got String with value \"false\"`,\n    ).toHaveBeenWarned()\n    expect(\n      `Invalid prop: type check failed for prop \"fn\". Expected Function, got Boolean with value true.`,\n    ).toHaveBeenWarned()\n    expect(\n      `Invalid prop: type check failed for prop \"cls\". Expected MyClass, got Object`,\n    ).toHaveBeenWarned()\n    expect(\n      `Invalid prop: type check failed for prop \"skipCheck\". Expected Boolean | Function, got String with value \"foo\".`,\n    ).not.toHaveBeenWarned()\n    expect(\n      `Prop type [] for prop \"empty\" won't match anything. Did you mean to use type Array instead?`,\n    ).toHaveBeenWarned()\n  })\n\n  // #3495\n  test('should not warn required props using kebab-case', async () => {\n    const Comp = {\n      props: {\n        fooBar: { type: String, required: true },\n      },\n      setup() {\n        return () => null\n      },\n    }\n    render(\n      h(Comp, {\n        'foo-bar': 'hello',\n      }),\n      nodeOps.createElement('div'),\n    )\n    expect(`Missing required prop: \"fooBar\"`).not.toHaveBeenWarned()\n  })\n\n  test('merging props from mixins and extends', () => {\n    let setupProps: any\n    let renderProxy: any\n\n    const E = {\n      props: ['base'],\n    }\n    const M1 = {\n      props: ['m1'],\n    }\n    const M2 = {\n      props: { m2: null },\n    }\n    const Comp = {\n      props: ['self'],\n      mixins: [M1, M2],\n      extends: E,\n      setup(props: any) {\n        setupProps = props\n      },\n      render(this: any) {\n        renderProxy = this\n        return h('div', [this.self, this.base, this.m1, this.m2])\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    const props = {\n      self: 'from self, ',\n      base: 'from base, ',\n      m1: 'from mixin 1, ',\n      m2: 'from mixin 2',\n    }\n    render(h(Comp, props), root)\n\n    expect(serializeInner(root)).toMatch(\n      `from self, from base, from mixin 1, from mixin 2`,\n    )\n    expect(setupProps).toMatchObject(props)\n    expect(renderProxy.$props).toMatchObject(props)\n  })\n\n  test('merging props from global mixins', () => {\n    let setupProps: any\n    let renderProxy: any\n\n    const M1 = {\n      props: ['m1'],\n    }\n    const M2 = {\n      props: { m2: null },\n    }\n    const Comp = {\n      props: ['self'],\n      setup(props: any) {\n        setupProps = props\n      },\n      render(this: any) {\n        renderProxy = this\n        return h('div', [this.self, this.m1, this.m2])\n      },\n    }\n\n    const props = {\n      self: 'from self, ',\n      m1: 'from mixin 1, ',\n      m2: 'from mixin 2',\n    }\n    const app = createApp(Comp, props)\n    app.mixin(M1)\n    app.mixin(M2)\n\n    const root = nodeOps.createElement('div')\n    app.mount(root)\n\n    expect(serializeInner(root)).toMatch(\n      `from self, from mixin 1, from mixin 2`,\n    )\n    expect(setupProps).toMatchObject(props)\n    expect(renderProxy.$props).toMatchObject(props)\n  })\n\n  test('merging props from global mixins and extends', () => {\n    let renderProxy: any\n    let extendedRenderProxy: any\n\n    const defaultProp = ' from global'\n    const props = {\n      globalProp: {\n        type: String,\n        default: defaultProp,\n      },\n    }\n    const globalMixin = {\n      props,\n    }\n    const Comp = {\n      render(this: any) {\n        renderProxy = this\n        return h('div', ['Comp', this.globalProp])\n      },\n    }\n    const ExtendedComp = {\n      extends: Comp,\n      render(this: any) {\n        extendedRenderProxy = this\n        return h('div', ['ExtendedComp', this.globalProp])\n      },\n    }\n\n    const app = createApp(\n      {\n        render: () => [h(ExtendedComp), h(Comp)],\n      },\n      {},\n    )\n    app.mixin(globalMixin)\n\n    const root = nodeOps.createElement('div')\n    app.mount(root)\n\n    expect(serializeInner(root)).toMatch(\n      `<div>ExtendedComp from global</div><div>Comp from global</div>`,\n    )\n    expect(renderProxy.$props).toMatchObject({ globalProp: defaultProp })\n    expect(extendedRenderProxy.$props).toMatchObject({\n      globalProp: defaultProp,\n    })\n  })\n\n  test('merging props for a component that is also used as a mixin', () => {\n    const CompA = {\n      render(this: any) {\n        return this.foo\n      },\n    }\n\n    const mixin = {\n      props: {\n        foo: {\n          default: 'from mixin',\n        },\n      },\n    }\n\n    const CompB = {\n      mixins: [mixin, CompA],\n      render(this: any) {\n        return this.foo\n      },\n    }\n\n    const app = createApp({\n      render() {\n        return [h(CompA), ', ', h(CompB)]\n      },\n    })\n\n    app.mixin({\n      props: {\n        foo: {\n          default: 'from global mixin',\n        },\n      },\n    })\n\n    const root = nodeOps.createElement('div')\n    app.mount(root)\n\n    expect(serializeInner(root)).toMatch(`from global mixin, from mixin`)\n  })\n\n  test('props type support BigInt', () => {\n    const Comp = {\n      props: {\n        foo: BigInt,\n      },\n      render(this: any) {\n        return h('div', [this.foo])\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(\n      h(Comp, {\n        foo: BigInt(BigInt(100000111)) + BigInt(2000000000) * BigInt(30000000),\n      }),\n      root,\n    )\n\n    expect(serializeInner(root)).toMatch('<div>60000000100000111</div>')\n  })\n\n  // #3474\n  test('should cache the value returned from the default factory to avoid unnecessary watcher trigger', async () => {\n    let count = 0\n    const Comp = {\n      props: {\n        foo: {\n          type: Object,\n          default: () => ({ val: 1 }),\n        },\n        bar: Number,\n      },\n      setup(props: any) {\n        watch(\n          () => props.foo,\n          () => {\n            count++\n          },\n        )\n        return () => h('h1', [props.foo.val, props.bar])\n      },\n    }\n\n    const foo = ref()\n    const bar = ref(0)\n    const app = createApp({\n      render: () => h(Comp, { foo: foo.value, bar: bar.value }),\n    })\n\n    const root = nodeOps.createElement('div')\n    app.mount(root)\n    expect(serializeInner(root)).toMatch(`<h1>10</h1>`)\n    expect(count).toBe(0)\n\n    bar.value++\n    await nextTick()\n    expect(serializeInner(root)).toMatch(`<h1>11</h1>`)\n    expect(count).toBe(0)\n  })\n\n  // #3288\n  test('declared prop key should be present even if not passed', async () => {\n    let initialKeys: string[] = []\n    const changeSpy = vi.fn()\n    const passFoo = ref(false)\n\n    const Comp = {\n      render() {},\n      props: {\n        foo: String,\n      },\n      setup(props: any) {\n        initialKeys = Object.keys(props)\n        const { foo } = toRefs(props)\n        watch(foo, changeSpy)\n      },\n    }\n\n    const Parent = () => (passFoo.value ? h(Comp, { foo: 'ok' }) : h(Comp))\n    const root = nodeOps.createElement('div')\n    createApp(Parent).mount(root)\n\n    expect(initialKeys).toMatchObject(['foo'])\n    passFoo.value = true\n    await nextTick()\n    expect(changeSpy).toHaveBeenCalledTimes(1)\n  })\n\n  // #3371\n  test(`avoid double-setting props when casting`, async () => {\n    const Parent = {\n      setup(props: any, { slots }: SetupContext) {\n        const childProps = ref()\n        const registerChildProps = (props: any) => {\n          childProps.value = props\n        }\n        provide('register', registerChildProps)\n\n        return () => {\n          // access the child component's props\n          childProps.value && childProps.value.foo\n          return slots.default!()\n        }\n      },\n    }\n\n    const Child = {\n      props: {\n        foo: {\n          type: Boolean,\n          required: false,\n        },\n      },\n      setup(props: { foo: boolean }) {\n        const register = inject('register') as any\n        // 1. change the reactivity data of the parent component\n        // 2. register its own props to the parent component\n        register(props)\n\n        return () => 'foo'\n      },\n    }\n\n    const App = {\n      setup() {\n        return () => h(Parent, () => h(Child as any, { foo: '' }, () => null))\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(App), root)\n    await nextTick()\n    expect(serializeInner(root)).toBe(`foo`)\n  })\n\n  test('support null in required + multiple-type declarations', () => {\n    const Comp = {\n      props: {\n        foo: { type: [Function, null], required: true },\n      },\n      render() {},\n    }\n    const root = nodeOps.createElement('div')\n    expect(() => {\n      render(h(Comp, { foo: () => {} }), root)\n    }).not.toThrow()\n\n    expect(() => {\n      render(h(Comp, { foo: null }), root)\n    }).not.toThrow()\n  })\n\n  // #5016\n  test('handling attr with undefined value', () => {\n    const Comp = {\n      render(this: any) {\n        return JSON.stringify(this.$attrs) + Object.keys(this.$attrs)\n      },\n    }\n    const root = nodeOps.createElement('div')\n\n    let attrs: any = { foo: undefined }\n\n    render(h(Comp, attrs), root)\n    expect(serializeInner(root)).toBe(\n      JSON.stringify(attrs) + Object.keys(attrs),\n    )\n\n    render(h(Comp, (attrs = { foo: 'bar' })), root)\n    expect(serializeInner(root)).toBe(\n      JSON.stringify(attrs) + Object.keys(attrs),\n    )\n  })\n\n  // #691ef\n  test('should not mutate original props long-form definition object', () => {\n    const props = {\n      msg: {\n        type: String,\n      },\n    }\n    const Comp = defineComponent({\n      props,\n      render() {},\n    })\n\n    const root = nodeOps.createElement('div')\n\n    render(h(Comp, { msg: 'test' }), root)\n\n    expect(Object.keys(props.msg).length).toBe(1)\n  })\n\n  test('should warn against reserved prop names', () => {\n    const Comp = defineComponent({\n      props: {\n        key: String,\n        ref: String,\n        $foo: String,\n      },\n      render() {},\n    })\n\n    const root = nodeOps.createElement('div')\n\n    render(h(Comp, { msg: 'test' }), root)\n\n    expect(`Invalid prop name: \"key\"`).toHaveBeenWarned()\n    expect(`Invalid prop name: \"ref\"`).toHaveBeenWarned()\n    expect(`Invalid prop name: \"$foo\"`).toHaveBeenWarned()\n  })\n\n  // #5517\n  test('events should not be props when component updating', async () => {\n    let props: any\n    function eventHandler() {}\n    const foo = ref(1)\n\n    const Child = defineComponent({\n      setup(_props) {\n        props = _props\n      },\n      emits: ['event'],\n      props: ['foo'],\n      template: `<div>{{ foo }}</div>`,\n    })\n\n    const Comp = defineComponent({\n      setup() {\n        return {\n          foo,\n          eventHandler,\n        }\n      },\n      components: { Child },\n      template: `<Child @event=\"eventHandler\" :foo=\"foo\" />`,\n    })\n\n    const root = document.createElement('div')\n    domRender(h(Comp), root)\n    expect(props).not.toHaveProperty('onEvent')\n\n    foo.value++\n    await nextTick()\n    expect(props).not.toHaveProperty('onEvent')\n  })\n})\n"
  },
  {
    "path": "packages/runtime-core/__tests__/componentPublicInstance.spec.ts",
    "content": "import {\n  createApp,\n  defineComponent,\n  getCurrentInstance,\n  h,\n  nodeOps,\n  render,\n  shallowReadonly,\n} from '@vue/runtime-test'\nimport type {\n  ComponentInternalInstance,\n  ComponentOptions,\n} from '../src/component'\n\ndescribe('component: proxy', () => {\n  test('data', () => {\n    let instance: ComponentInternalInstance\n    let instanceProxy: any\n    const Comp = {\n      data() {\n        return {\n          foo: 1,\n        }\n      },\n      mounted() {\n        instance = getCurrentInstance()!\n        instanceProxy = this\n      },\n      render() {\n        return null\n      },\n    }\n    render(h(Comp), nodeOps.createElement('div'))\n    expect(instanceProxy.foo).toBe(1)\n    instanceProxy.foo = 2\n    expect(instance!.data.foo).toBe(2)\n  })\n\n  test('setupState', () => {\n    let instance: ComponentInternalInstance\n    let instanceProxy: any\n    const Comp = {\n      setup() {\n        return {\n          foo: 1,\n        }\n      },\n      mounted() {\n        instance = getCurrentInstance()!\n        instanceProxy = this\n      },\n      render() {\n        return null\n      },\n    }\n    render(h(Comp), nodeOps.createElement('div'))\n    expect(instanceProxy.foo).toBe(1)\n    instanceProxy.foo = 2\n    expect(instance!.setupState.foo).toBe(2)\n  })\n\n  test('should not expose non-declared props', () => {\n    let instanceProxy: any\n    const Comp = {\n      setup() {\n        return () => null\n      },\n      mounted() {\n        instanceProxy = this\n      },\n    }\n    render(h(Comp, { count: 1 }), nodeOps.createElement('div'))\n    expect('count' in instanceProxy).toBe(false)\n  })\n\n  test('public properties', async () => {\n    let instance: ComponentInternalInstance\n    let instanceProxy: any\n    const Comp = {\n      setup() {\n        return () => null\n      },\n      mounted() {\n        instance = getCurrentInstance()!\n        instanceProxy = this\n      },\n    }\n    render(h(Comp), nodeOps.createElement('div'))\n    expect(instanceProxy.$data).toBe(instance!.data)\n    expect(instanceProxy.$props).toBe(shallowReadonly(instance!.props))\n    expect(instanceProxy.$attrs).toBe(shallowReadonly(instance!.attrs))\n    expect(instanceProxy.$slots).toBe(shallowReadonly(instance!.slots))\n    expect(instanceProxy.$refs).toBe(shallowReadonly(instance!.refs))\n    expect(instanceProxy.$parent).toBe(\n      instance!.parent && instance!.parent.proxy,\n    )\n    expect(instanceProxy.$root).toBe(instance!.root.proxy)\n    expect(instanceProxy.$emit).toBe(instance!.emit)\n    expect(instanceProxy.$el).toBe(instance!.vnode.el)\n    expect(instanceProxy.$options).toBe(instance!.type as ComponentOptions)\n    expect(() => (instanceProxy.$data = {})).toThrow(TypeError)\n    expect(`Attempting to mutate public property \"$data\"`).toHaveBeenWarned()\n\n    const nextTickThis = await instanceProxy.$nextTick(function (this: any) {\n      return this\n    })\n    expect(nextTickThis).toBe(instanceProxy)\n  })\n\n  test('user attached properties', async () => {\n    let instance: ComponentInternalInstance\n    let instanceProxy: any\n    const Comp = {\n      setup() {\n        return () => null\n      },\n      mounted() {\n        instance = getCurrentInstance()!\n        instanceProxy = this\n      },\n    }\n    render(h(Comp), nodeOps.createElement('div'))\n    instanceProxy.foo = 1\n    expect(instanceProxy.foo).toBe(1)\n    expect(instance!.ctx.foo).toBe(1)\n\n    // should also allow properties that start with $\n    const obj = (instanceProxy.$store = {})\n    expect(instanceProxy.$store).toBe(obj)\n    expect(instance!.ctx.$store).toBe(obj)\n  })\n\n  test('globalProperties', () => {\n    let instance: ComponentInternalInstance\n    let instanceProxy: any\n    const Comp = {\n      setup() {\n        return () => null\n      },\n      mounted() {\n        instance = getCurrentInstance()!\n        instanceProxy = this\n      },\n    }\n\n    const app = createApp(Comp)\n    app.config.globalProperties.foo = 1\n    app.mount(nodeOps.createElement('div'))\n\n    expect(instanceProxy.foo).toBe(1)\n\n    // set should overwrite globalProperties with local\n    instanceProxy.foo = 2\n    // expect(instanceProxy.foo).toBe(2)\n    expect(instance!.ctx.foo).toBe(2)\n    // should not affect global\n    expect(app.config.globalProperties.foo).toBe(1)\n  })\n\n  test('has check', () => {\n    let instanceProxy: any\n    const Comp = {\n      render() {},\n      props: {\n        msg: String,\n      },\n      data() {\n        return {\n          foo: 0,\n          $foo: 0,\n        }\n      },\n      computed: {\n        cmp: () => {\n          throw new Error('value of cmp should not be accessed')\n        },\n        $cmp: () => {\n          throw new Error('value of $cmp should not be read')\n        },\n      },\n      setup() {\n        return {\n          bar: 1,\n        }\n      },\n      __cssModules: {\n        $style: {},\n        cssStyles: {},\n      },\n      mounted() {\n        instanceProxy = this\n      },\n    }\n\n    const app = createApp(Comp, { msg: 'hello' })\n    app.config.globalProperties.global = 1\n    app.config.globalProperties.$global = 1\n\n    app.mount(nodeOps.createElement('div'))\n\n    // props\n    expect('msg' in instanceProxy).toBe(true)\n    // data\n    expect('foo' in instanceProxy).toBe(true)\n    expect('$foo' in instanceProxy).toBe(false)\n    // setupState\n    expect('bar' in instanceProxy).toBe(true)\n    // ctx\n    expect('cmp' in instanceProxy).toBe(true)\n    expect('$cmp' in instanceProxy).toBe(true)\n    // public properties\n    expect('$el' in instanceProxy).toBe(true)\n    // CSS modules\n    expect('$style' in instanceProxy).toBe(true)\n    expect('cssStyles' in instanceProxy).toBe(true)\n    // global properties\n    expect('global' in instanceProxy).toBe(true)\n    expect('$global' in instanceProxy).toBe(true)\n\n    // non-existent\n    expect('$foobar' in instanceProxy).toBe(false)\n    expect('baz' in instanceProxy).toBe(false)\n\n    // #4962 triggering getter should not cause non-existent property to\n    // pass the has check\n    instanceProxy.baz\n    instanceProxy.$baz\n    expect('baz' in instanceProxy).toBe(false)\n    expect('$baz' in instanceProxy).toBe(false)\n\n    // set non-existent (goes into proxyTarget sink)\n    instanceProxy.baz = 1\n    expect('baz' in instanceProxy).toBe(true)\n    instanceProxy.$baz = 1\n    expect('$baz' in instanceProxy).toBe(true)\n\n    // dev mode ownKeys check for console inspection\n    // should only expose own keys\n    expect(Object.keys(instanceProxy)).toMatchObject([\n      'msg',\n      'bar',\n      'foo',\n      'cmp',\n      '$cmp',\n      'baz',\n      '$baz',\n    ])\n  })\n\n  test('allow updating proxy with Object.defineProperty', () => {\n    let instanceProxy: any\n    const Comp = {\n      render() {},\n      setup() {\n        return {\n          isDisplayed: true,\n        }\n      },\n      mounted() {\n        instanceProxy = this\n      },\n    }\n\n    const app = createApp(Comp)\n\n    app.mount(nodeOps.createElement('div'))\n\n    Object.defineProperty(instanceProxy, 'isDisplayed', { value: false })\n\n    expect(instanceProxy.isDisplayed).toBe(false)\n\n    Object.defineProperty(instanceProxy, 'isDisplayed', { value: true })\n\n    expect(instanceProxy.isDisplayed).toBe(true)\n\n    Object.defineProperty(instanceProxy, 'isDisplayed', {\n      get() {\n        return false\n      },\n    })\n\n    expect(instanceProxy.isDisplayed).toBe(false)\n\n    Object.defineProperty(instanceProxy, 'isDisplayed', {\n      get() {\n        return true\n      },\n    })\n\n    expect(instanceProxy.isDisplayed).toBe(true)\n  })\n\n  test('allow test runner spying on proxy methods with Object.defineProperty', () => {\n    // #5417\n    let instanceProxy: any\n    const Comp = {\n      render() {},\n      setup() {\n        return {\n          toggle() {\n            return 'a'\n          },\n        }\n      },\n      mounted() {\n        instanceProxy = this\n      },\n    }\n\n    const app = createApp(Comp)\n\n    app.mount(nodeOps.createElement('div'))\n\n    // access 'toggle' to ensure key is cached\n    const v1 = instanceProxy.toggle()\n    expect(v1).toEqual('a')\n\n    // reconfigure \"toggle\" to be getter based.\n    let getCalledTimes = 0\n    Object.defineProperty(instanceProxy, 'toggle', {\n      get() {\n        getCalledTimes++\n        return () => 'b'\n      },\n    })\n\n    // getter should not be evaluated on initial definition\n    expect(getCalledTimes).toEqual(0)\n\n    // invoke \"toggle\" after \"defineProperty\"\n    const v2 = instanceProxy.toggle()\n    expect(v2).toEqual('b')\n    expect(getCalledTimes).toEqual(1)\n\n    // expect toggle getter not to be cached. it can't be\n    instanceProxy.toggle()\n    expect(getCalledTimes).toEqual(2)\n\n    // attaching spy, triggers the getter once, and override the property.\n    // also uses Object.defineProperty\n    const spy = vi.spyOn(instanceProxy, 'toggle')\n    expect(getCalledTimes).toEqual(3)\n\n    const v3 = instanceProxy.toggle()\n    expect(v3).toEqual('b')\n    expect(spy).toHaveBeenCalled()\n    expect(getCalledTimes).toEqual(3)\n  })\n\n  test('defineProperty on proxy property with value descriptor', () => {\n    // #5417\n    let instanceProxy: any\n    const Comp = {\n      render() {},\n      setup() {\n        return {\n          toggle: 'a',\n        }\n      },\n      mounted() {\n        instanceProxy = this\n      },\n    }\n\n    const app = createApp(Comp)\n\n    app.mount(nodeOps.createElement('div'))\n\n    const v1 = instanceProxy.toggle\n    expect(v1).toEqual('a')\n\n    Object.defineProperty(instanceProxy, 'toggle', {\n      value: 'b',\n    })\n    const v2 = instanceProxy.toggle\n    expect(v2).toEqual('b')\n\n    // expect null to be a settable value\n    Object.defineProperty(instanceProxy, 'toggle', {\n      value: null,\n    })\n    const v3 = instanceProxy.toggle\n    expect(v3).toBeNull()\n  })\n\n  test('defineProperty on public instance proxy should work with SETUP,DATA,CONTEXT,PROPS', () => {\n    // #5417\n    let instanceProxy: any\n    const Comp = {\n      props: ['fromProp'],\n      data() {\n        return { name: 'data.name' }\n      },\n      computed: {\n        greet() {\n          return 'Hi ' + (this as any).name\n        },\n      },\n      render() {},\n      setup() {\n        return {\n          fromSetup: true,\n        }\n      },\n      mounted() {\n        instanceProxy = this\n      },\n    }\n\n    const app = createApp(Comp, {\n      fromProp: true,\n    })\n\n    app.mount(nodeOps.createElement('div'))\n    expect(instanceProxy.greet).toEqual('Hi data.name')\n\n    // define property on data\n    Object.defineProperty(instanceProxy, 'name', {\n      get() {\n        return 'getter.name'\n      },\n    })\n\n    // computed is same still cached\n    expect(instanceProxy.greet).toEqual('Hi data.name')\n\n    // trigger computed\n    instanceProxy.name = ''\n\n    // expect \"greet\" to evaluated and use name from context getter\n    expect(instanceProxy.greet).toEqual('Hi getter.name')\n\n    // defineProperty on computed ( context )\n    Object.defineProperty(instanceProxy, 'greet', {\n      get() {\n        return 'Hi greet.getter.computed'\n      },\n    })\n    expect(instanceProxy.greet).toEqual('Hi greet.getter.computed')\n\n    // defineProperty on setupState\n    expect(instanceProxy.fromSetup).toBe(true)\n    Object.defineProperty(instanceProxy, 'fromSetup', {\n      get() {\n        return false\n      },\n    })\n    expect(instanceProxy.fromSetup).toBe(false)\n\n    // defineProperty on Props\n    expect(instanceProxy.fromProp).toBe(true)\n    Object.defineProperty(instanceProxy, 'fromProp', {\n      get() {\n        return false\n      },\n    })\n    expect(instanceProxy.fromProp).toBe(false)\n  })\n\n  // #864\n  test('should not warn declared but absent props', () => {\n    const Comp = {\n      props: ['test'],\n      render(this: any) {\n        return this.test\n      },\n    }\n    render(h(Comp), nodeOps.createElement('div'))\n    expect(\n      `was accessed during render but is not defined`,\n    ).not.toHaveBeenWarned()\n  })\n\n  test('should allow symbol to access on render', () => {\n    const Comp = {\n      render() {\n        if ((this as any)[Symbol.unscopables]) {\n          return '1'\n        }\n        return '2'\n      },\n    }\n\n    const app = createApp(Comp)\n    app.mount(nodeOps.createElement('div'))\n\n    expect(\n      `Property ${JSON.stringify(\n        Symbol.unscopables,\n      )} was accessed during render ` + `but is not defined on instance.`,\n    ).toHaveBeenWarned()\n  })\n\n  test('should prevent mutating script setup bindings', () => {\n    const Comp = defineComponent({\n      render() {},\n      setup() {\n        return {\n          __isScriptSetup: true,\n          foo: 1,\n        }\n      },\n      mounted() {\n        expect('foo' in this).toBe(false)\n        try {\n          this.foo = 123\n        } catch (e) {}\n      },\n    })\n    render(h(Comp), nodeOps.createElement('div'))\n    expect(`Cannot mutate <script setup> binding \"foo\"`).toHaveBeenWarned()\n  })\n})\n"
  },
  {
    "path": "packages/runtime-core/__tests__/componentSlots.spec.ts",
    "content": "import {\n  createApp,\n  getCurrentInstance,\n  h,\n  nextTick,\n  nodeOps,\n  ref,\n  render,\n  serializeInner,\n  useSlots,\n} from '@vue/runtime-test'\nimport { createBlock, normalizeVNode } from '../src/vnode'\nimport { createSlots } from '../src/helpers/createSlots'\n\ndescribe('component: slots', () => {\n  function renderWithSlots(slots: any): any {\n    let instance: any\n    const Comp = {\n      render() {\n        instance = getCurrentInstance()\n        return h('div')\n      },\n    }\n\n    render(h(Comp, null, slots), nodeOps.createElement('div'))\n    return instance\n  }\n\n  test('initSlots: instance.slots should be set correctly', () => {\n    let instance: any\n    const Comp = {\n      render() {\n        instance = getCurrentInstance()\n        return h('div')\n      },\n    }\n    const slots = { foo: () => {}, _: 1 }\n    render(createBlock(Comp, null, slots), nodeOps.createElement('div'))\n    expect(instance.slots).toMatchObject(slots)\n  })\n\n  test('initSlots: instance.slots should remove compiler marker if parent is using manual render function', () => {\n    const { slots } = renderWithSlots({ _: 1 })\n    expect(slots).toMatchObject({})\n  })\n\n  test('initSlots: ensure compiler marker non-enumerable', () => {\n    const Comp = {\n      render() {\n        const slots = useSlots()\n        // Only user-defined slots should be enumerable\n        expect(Object.keys(slots)).toEqual(['foo'])\n\n        // Internal compiler markers must still exist but be non-enumerable\n        expect(slots).toHaveProperty('_')\n        expect(Object.getOwnPropertyDescriptor(slots, '_')!.enumerable).toBe(\n          false,\n        )\n        return h('div')\n      },\n    }\n    const slots = { foo: () => {}, _: 1 }\n    render(createBlock(Comp, null, slots), nodeOps.createElement('div'))\n  })\n\n  test('initSlots: should normalize object slots (when value is null, string, array)', () => {\n    const { slots } = renderWithSlots({\n      _inner: '_inner',\n      foo: null,\n      header: 'header',\n      footer: ['f1', 'f2'],\n    })\n\n    expect(\n      '[Vue warn]: Non-function value encountered for slot \"_inner\". Prefer function slots for better performance.',\n    ).toHaveBeenWarned()\n\n    expect(\n      '[Vue warn]: Non-function value encountered for slot \"header\". Prefer function slots for better performance.',\n    ).toHaveBeenWarned()\n\n    expect(\n      '[Vue warn]: Non-function value encountered for slot \"footer\". Prefer function slots for better performance.',\n    ).toHaveBeenWarned()\n\n    expect(slots).not.toHaveProperty('foo')\n    expect(slots._inner()).toMatchObject([normalizeVNode('_inner')])\n    expect(slots.header()).toMatchObject([normalizeVNode('header')])\n    expect(slots.footer()).toMatchObject([\n      normalizeVNode('f1'),\n      normalizeVNode('f2'),\n    ])\n  })\n\n  test('initSlots: should normalize object slots (when value is function)', () => {\n    let proxy: any\n    const Comp = {\n      render() {\n        proxy = getCurrentInstance()\n        return h('div')\n      },\n    }\n\n    render(\n      h(Comp, null, {\n        header: () => 'header',\n      }),\n      nodeOps.createElement('div'),\n    )\n\n    expect(proxy.slots.header()).toMatchObject([normalizeVNode('header')])\n  })\n\n  test('initSlots: instance.slots should be set correctly (when vnode.shapeFlag is not SLOTS_CHILDREN)', () => {\n    const { slots } = renderWithSlots([h('span')])\n\n    expect(\n      '[Vue warn]: Non-function value encountered for default slot. Prefer function slots for better performance.',\n    ).toHaveBeenWarned()\n\n    expect(slots.default()).toMatchObject([normalizeVNode(h('span'))])\n  })\n\n  test('updateSlots: instance.slots should be updated correctly (when slotType is number)', async () => {\n    const flag1 = ref(true)\n\n    let instance: any\n    const Child = () => {\n      instance = getCurrentInstance()\n      return 'child'\n    }\n\n    const Comp = {\n      setup() {\n        return () => [\n          h(\n            Child,\n            null,\n            createSlots({ _: 2 as any }, [\n              flag1.value\n                ? {\n                    name: 'one',\n                    fn: () => [h('span')],\n                  }\n                : {\n                    name: 'two',\n                    fn: () => [h('div')],\n                  },\n            ]),\n          ),\n        ]\n      },\n    }\n    render(h(Comp), nodeOps.createElement('div'))\n\n    expect(instance.slots).toHaveProperty('one')\n    expect(instance.slots).not.toHaveProperty('two')\n\n    flag1.value = false\n    await nextTick()\n\n    expect(instance.slots).not.toHaveProperty('one')\n    expect(instance.slots).toHaveProperty('two')\n  })\n\n  test('updateSlots: instance.slots should be updated correctly (when slotType is null)', async () => {\n    const flag1 = ref(true)\n\n    let instance: any\n    const Child = () => {\n      instance = getCurrentInstance()\n      return 'child'\n    }\n\n    const oldSlots = {\n      header: 'header',\n      footer: undefined,\n    }\n    const newSlots = {\n      header: undefined,\n      footer: 'footer',\n    }\n\n    const Comp = {\n      setup() {\n        return () => [\n          h(Child, { n: flag1.value }, flag1.value ? oldSlots : newSlots),\n        ]\n      },\n    }\n    render(h(Comp), nodeOps.createElement('div'))\n\n    expect(instance.slots).toHaveProperty('header')\n    expect(instance.slots).not.toHaveProperty('footer')\n\n    flag1.value = false\n    await nextTick()\n\n    expect(\n      '[Vue warn]: Non-function value encountered for slot \"header\". Prefer function slots for better performance.',\n    ).toHaveBeenWarned()\n\n    expect(\n      '[Vue warn]: Non-function value encountered for slot \"footer\". Prefer function slots for better performance.',\n    ).toHaveBeenWarned()\n\n    expect(instance.slots).not.toHaveProperty('header')\n    expect(instance.slots.footer()).toMatchObject([normalizeVNode('footer')])\n  })\n\n  test('updateSlots: instance.slots should be update correctly (when vnode.shapeFlag is not SLOTS_CHILDREN)', async () => {\n    const flag1 = ref(true)\n\n    let instance: any\n    const Child = () => {\n      instance = getCurrentInstance()\n      return 'child'\n    }\n\n    const Comp = {\n      setup() {\n        return () => [\n          h(Child, { n: flag1.value }, flag1.value ? ['header'] : ['footer']),\n        ]\n      },\n    }\n    render(h(Comp), nodeOps.createElement('div'))\n\n    expect(instance.slots.default()).toMatchObject([normalizeVNode('header')])\n\n    flag1.value = false\n    await nextTick()\n\n    expect(\n      '[Vue warn]: Non-function value encountered for default slot. Prefer function slots for better performance.',\n    ).toHaveBeenWarned()\n\n    expect(instance.slots.default()).toMatchObject([normalizeVNode('footer')])\n  })\n\n  test('should respect $stable flag with a value of true', async () => {\n    const flag1 = ref(1)\n    const flag2 = ref(2)\n    const spy = vi.fn()\n\n    const Child = () => {\n      spy()\n      return 'child'\n    }\n\n    const App = {\n      setup() {\n        return () => [\n          flag1.value,\n          h(\n            Child,\n            { n: flag2.value },\n            {\n              foo: () => 'foo',\n              $stable: true,\n            },\n          ),\n        ]\n      },\n    }\n\n    render(h(App), nodeOps.createElement('div'))\n    expect(spy).toHaveBeenCalledTimes(1)\n\n    // parent re-render, props didn't change, slots are stable\n    // -> child should not update\n    flag1.value++\n    await nextTick()\n    expect(spy).toHaveBeenCalledTimes(1)\n\n    // parent re-render, props changed\n    // -> child should update\n    flag2.value++\n    await nextTick()\n    expect(spy).toHaveBeenCalledTimes(2)\n  })\n\n  test('should respect $stable flag with a value of false', async () => {\n    const flag1 = ref(1)\n    const flag2 = ref(2)\n    const spy = vi.fn()\n\n    const Child = () => {\n      spy()\n      return 'child'\n    }\n\n    const App = {\n      setup() {\n        return () => [\n          flag1.value,\n          h(\n            Child,\n            { n: flag2.value },\n            {\n              foo: () => 'foo',\n              $stable: false,\n            },\n          ),\n        ]\n      },\n    }\n\n    render(h(App), nodeOps.createElement('div'))\n    expect(spy).toHaveBeenCalledTimes(1)\n\n    // parent re-render, props didn't change, slots are not stable\n    // -> child should update\n    flag1.value++\n    await nextTick()\n    expect(spy).toHaveBeenCalledTimes(2)\n\n    // parent re-render, props changed\n    // -> child should update\n    flag2.value++\n    await nextTick()\n    expect(spy).toHaveBeenCalledTimes(3)\n  })\n\n  test('should not warn when mounting another app in setup', () => {\n    const Comp = {\n      setup(_: any, { slots }: any) {\n        return () => slots.default?.()\n      },\n    }\n\n    const mountComp = () => {\n      createApp({\n        setup() {\n          return () => h(Comp, () => 'msg')\n        },\n      }).mount(nodeOps.createElement('div'))\n    }\n\n    const App = {\n      setup() {\n        mountComp()\n        return () => null\n      },\n    }\n\n    createApp(App).mount(nodeOps.createElement('div'))\n    expect(\n      'Slot \"default\" invoked outside of the render function',\n    ).not.toHaveBeenWarned()\n  })\n\n  test('basic warn', () => {\n    const Comp = {\n      setup(_: any, { slots }: any) {\n        slots.default && slots.default()\n        return () => null\n      },\n    }\n\n    const App = {\n      setup() {\n        return () => h(Comp, () => h('div'))\n      },\n    }\n\n    createApp(App).mount(nodeOps.createElement('div'))\n    expect(\n      'Slot \"default\" invoked outside of the render function',\n    ).toHaveBeenWarned()\n  })\n\n  test('basic warn when mounting another app in setup', () => {\n    const Comp = {\n      setup(_: any, { slots }: any) {\n        slots.default?.()\n        return () => null\n      },\n    }\n\n    const mountComp = () => {\n      createApp({\n        setup() {\n          return () => h(Comp, () => 'msg')\n        },\n      }).mount(nodeOps.createElement('div'))\n    }\n\n    const App = {\n      setup() {\n        mountComp()\n        return () => null\n      },\n    }\n\n    createApp(App).mount(nodeOps.createElement('div'))\n    expect(\n      'Slot \"default\" invoked outside of the render function',\n    ).toHaveBeenWarned()\n  })\n\n  test('should not warn when render in setup', () => {\n    const container = {\n      setup(_: any, { slots }: any) {\n        return () => slots.default && slots.default()\n      },\n    }\n\n    const comp = h(container, null, () => h('div'))\n\n    const App = {\n      setup() {\n        render(h(comp), nodeOps.createElement('div'))\n        return () => null\n      },\n    }\n\n    createApp(App).mount(nodeOps.createElement('div'))\n    expect(\n      'Slot \"default\" invoked outside of the render function',\n    ).not.toHaveBeenWarned()\n  })\n\n  test('basic warn when render in setup', () => {\n    const container = {\n      setup(_: any, { slots }: any) {\n        slots.default && slots.default()\n        return () => null\n      },\n    }\n\n    const comp = h(container, null, () => h('div'))\n\n    const App = {\n      setup() {\n        render(h(comp), nodeOps.createElement('div'))\n        return () => null\n      },\n    }\n\n    createApp(App).mount(nodeOps.createElement('div'))\n    expect(\n      'Slot \"default\" invoked outside of the render function',\n    ).toHaveBeenWarned()\n  })\n\n  test('slot name starts with underscore', () => {\n    const Comp = {\n      setup(_: any, { slots }: any) {\n        return () => slots._foo()\n      },\n    }\n\n    const App = {\n      setup() {\n        return () => h(Comp, null, { _foo: () => 'foo' })\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    createApp(App).mount(root)\n    expect(serializeInner(root)).toBe('foo')\n  })\n})\n"
  },
  {
    "path": "packages/runtime-core/__tests__/components/BaseTransition.spec.ts",
    "content": "import {\n  BaseTransition,\n  type BaseTransitionProps,\n  KeepAlive,\n  type TestElement,\n  type VNodeProps,\n  h,\n  nextTick,\n  nodeOps,\n  ref,\n  render,\n  serialize,\n  serializeInner,\n} from '@vue/runtime-test'\n\nfunction mount(\n  props: BaseTransitionProps<TestElement>,\n  slot: () => any,\n  withKeepAlive = false,\n) {\n  const root = nodeOps.createElement('div')\n  const show = ref(true)\n  const unmount = () => (show.value = false)\n  const App = {\n    render() {\n      return show.value\n        ? h(BaseTransition, props, () => {\n            return withKeepAlive ? h(KeepAlive, null, slot()) : slot()\n          })\n        : null\n    },\n  }\n  render(h(App), root)\n\n  return { root, unmount }\n}\n\nfunction mockProps(\n  extra: BaseTransitionProps<TestElement> = {},\n  withKeepAlive = false,\n) {\n  const cbs: {\n    doneEnter: Record<string, () => void>\n    doneLeave: Record<string, () => void>\n  } = {\n    doneEnter: {},\n    doneLeave: {},\n  }\n  const props: BaseTransitionProps<TestElement> = {\n    onBeforeEnter: vi.fn(el => {\n      if (!extra.persisted && !withKeepAlive) {\n        expect(el.parentNode).toBeNull()\n      }\n    }),\n    onEnter: vi.fn((el, done) => {\n      cbs.doneEnter[serialize(el as TestElement)] = done\n    }),\n    onAfterEnter: vi.fn<(el: TestElement) => void>(),\n    onEnterCancelled: vi.fn<(el: TestElement) => void>(),\n    onBeforeLeave: vi.fn<(el: TestElement) => void>(),\n    onLeave: vi.fn((el, done) => {\n      cbs.doneLeave[serialize(el as TestElement)] = done\n    }),\n    onAfterLeave: vi.fn<(el: TestElement) => void>(),\n    onLeaveCancelled: vi.fn<(el: TestElement) => void>(),\n    onBeforeAppear: vi.fn<(el: TestElement) => void>(),\n    onAppear: vi.fn((el, done) => {\n      cbs.doneEnter[serialize(el as TestElement)] = done\n    }),\n    onAfterAppear: vi.fn<(el: TestElement) => void>(),\n    onAppearCancelled: vi.fn<(el: TestElement) => void>(),\n    ...extra,\n  }\n  return {\n    props,\n    cbs,\n  }\n}\n\nfunction assertCalls(\n  props: BaseTransitionProps<TestElement>,\n  calls: Record<string, number>,\n) {\n  Object.keys(calls).forEach(key => {\n    expect(props[key as keyof BaseTransitionProps]).toHaveBeenCalledTimes(\n      calls[key],\n    )\n  })\n}\n\nfunction assertCalledWithEl(fn: any, expected: string, callIndex = 0) {\n  expect(serialize(fn.mock.calls[callIndex][0])).toBe(expected)\n}\n\ninterface ToggleOptions {\n  trueBranch: () => any\n  falseBranch: () => any\n  trueSerialized: string\n  falseSerialized: string\n}\n\ntype TestFn = (o: ToggleOptions, withKeepAlive?: boolean) => void\n\nfunction runTestWithElements(tester: TestFn) {\n  return tester({\n    trueBranch: () => h('div'),\n    falseBranch: () => h('span'),\n    trueSerialized: `<div></div>`,\n    falseSerialized: `<span></span>`,\n  })\n}\n\nfunction runTestWithComponents(tester: TestFn) {\n  const CompA = ({ msg }: { msg: string }) => h('div', msg)\n  // test HOC\n  const CompB = ({ msg }: { msg: string }) => h(CompC, { msg })\n  const CompC = ({ msg }: { msg: string }) => h('span', msg)\n  return tester({\n    trueBranch: () => h(CompA, { msg: 'foo' }),\n    falseBranch: () => h(CompB, { msg: 'bar' }),\n    trueSerialized: `<div>foo</div>`,\n    falseSerialized: `<span>bar</span>`,\n  })\n}\n\nfunction runTestWithKeepAlive(tester: TestFn) {\n  const trueComp = {\n    setup() {\n      const count = ref(0)\n      return () => h('div', count.value)\n    },\n  }\n  const falseComp = {\n    setup() {\n      const count = ref(0)\n      return () => h('span', count.value)\n    },\n  }\n  return tester(\n    {\n      trueBranch: () => h(trueComp),\n      falseBranch: () => h(falseComp),\n      trueSerialized: `<div>0</div>`,\n      falseSerialized: `<span>0</span>`,\n    },\n    true /* withKeepAlive: true */,\n  )\n}\n\ndescribe('BaseTransition', () => {\n  test('appear: true w/ appear hooks', () => {\n    const { props, cbs } = mockProps({\n      appear: true,\n    })\n    mount(props, () => h('div'))\n    expect(props.onBeforeAppear).toHaveBeenCalledTimes(1)\n    expect(props.onAppear).toHaveBeenCalledTimes(1)\n    expect(props.onAfterAppear).not.toHaveBeenCalled()\n\n    // enter should not be called\n    expect(props.onBeforeEnter).not.toHaveBeenCalled()\n    expect(props.onEnter).not.toHaveBeenCalled()\n    expect(props.onAfterEnter).not.toHaveBeenCalled()\n\n    cbs.doneEnter[`<div></div>`]()\n    expect(props.onAfterAppear).toHaveBeenCalledTimes(1)\n    expect(props.onAfterEnter).not.toHaveBeenCalled()\n  })\n\n  test('appear: true w/ fallback to enter hooks', () => {\n    const { props, cbs } = mockProps({\n      appear: true,\n      onBeforeAppear: undefined,\n      onAppear: undefined,\n      onAfterAppear: undefined,\n      onAppearCancelled: undefined,\n    })\n    mount(props, () => h('div'))\n    expect(props.onBeforeEnter).toHaveBeenCalledTimes(1)\n    expect(props.onEnter).toHaveBeenCalledTimes(1)\n    expect(props.onAfterEnter).not.toHaveBeenCalled()\n    cbs.doneEnter[`<div></div>`]()\n    expect(props.onAfterEnter).toHaveBeenCalledTimes(1)\n  })\n\n  describe('persisted: true', () => {\n    // this is pretty much how v-show is implemented\n    // (but using the directive API instead)\n    function mockPersistedHooks() {\n      const state = { show: true }\n      const toggle = ref(true)\n      const hooks: VNodeProps = {\n        onVnodeBeforeMount(vnode) {\n          vnode.transition!.beforeEnter(vnode.el!)\n        },\n        onVnodeMounted(vnode) {\n          vnode.transition!.enter(vnode.el!)\n        },\n        onVnodeUpdated(vnode, oldVnode) {\n          if (oldVnode.props!.id !== vnode.props!.id) {\n            if (vnode.props!.id) {\n              vnode.transition!.beforeEnter(vnode.el!)\n              state.show = true\n              vnode.transition!.enter(vnode.el!)\n            } else {\n              vnode.transition!.leave(vnode.el!, () => {\n                state.show = false\n              })\n            }\n          }\n        },\n      }\n      return { state, toggle, hooks }\n    }\n\n    test('w/ appear: false', async () => {\n      const { props, cbs } = mockProps({ persisted: true })\n      const { toggle, state, hooks } = mockPersistedHooks()\n\n      mount(props, () => h('div', { id: toggle.value, ...hooks }))\n      // without appear: true, enter hooks should not be called on mount\n      expect(props.onBeforeEnter).not.toHaveBeenCalled()\n      expect(props.onEnter).not.toHaveBeenCalled()\n      expect(props.onAfterEnter).not.toHaveBeenCalled()\n\n      toggle.value = false\n      await nextTick()\n      expect(props.onBeforeLeave).toHaveBeenCalledTimes(1)\n      expect(props.onLeave).toHaveBeenCalledTimes(1)\n      expect(props.onAfterLeave).not.toHaveBeenCalled()\n      expect(state.show).toBe(true) // should still be shown\n      cbs.doneLeave[`<div id=false></div>`]()\n      expect(state.show).toBe(false) // should be hidden now\n      expect(props.onAfterLeave).toHaveBeenCalledTimes(1)\n\n      toggle.value = true\n      await nextTick()\n      expect(props.onBeforeEnter).toHaveBeenCalledTimes(1)\n      expect(props.onEnter).toHaveBeenCalledTimes(1)\n      expect(props.onAfterEnter).not.toHaveBeenCalled()\n      expect(state.show).toBe(true) // should be shown now\n      cbs.doneEnter[`<div id=true></div>`]()\n      expect(props.onAfterEnter).toHaveBeenCalledTimes(1)\n    })\n\n    test('w/ appear: true', () => {\n      const { props, cbs } = mockProps({ persisted: true, appear: true })\n      const { hooks } = mockPersistedHooks()\n      mount(props, () => h('div', hooks))\n\n      expect(props.onBeforeAppear).toHaveBeenCalledTimes(1)\n      expect(props.onAppear).toHaveBeenCalledTimes(1)\n      expect(props.onAfterAppear).not.toHaveBeenCalled()\n      cbs.doneEnter[`<div></div>`]()\n      expect(props.onAfterAppear).toHaveBeenCalledTimes(1)\n    })\n  })\n\n  describe('toggle on-off', () => {\n    async function testToggleOnOff(\n      {\n        trueBranch,\n        trueSerialized,\n        falseBranch,\n        falseSerialized,\n      }: ToggleOptions,\n      mode?: BaseTransitionProps['mode'],\n    ) {\n      const toggle = ref(true)\n      const { props, cbs } = mockProps({ mode })\n      const { root } = mount(props, () =>\n        toggle.value ? trueBranch() : falseBranch(),\n      )\n\n      // without appear: true, enter hooks should not be called on mount\n      expect(props.onBeforeEnter).not.toHaveBeenCalled()\n      expect(props.onEnter).not.toHaveBeenCalled()\n      expect(props.onAfterEnter).not.toHaveBeenCalled()\n\n      toggle.value = false\n      await nextTick()\n      // comment placeholder enters immediately\n      expect(serializeInner(root)).toBe(`${trueSerialized}${falseSerialized}`)\n      expect(props.onBeforeLeave).toHaveBeenCalledTimes(1)\n      assertCalledWithEl(props.onBeforeLeave, trueSerialized)\n      expect(props.onLeave).toHaveBeenCalledTimes(1)\n      assertCalledWithEl(props.onLeave, trueSerialized)\n      expect(props.onAfterLeave).not.toHaveBeenCalled()\n      cbs.doneLeave[trueSerialized]()\n      expect(serializeInner(root)).toBe(falseSerialized)\n      expect(props.onAfterLeave).toHaveBeenCalledTimes(1)\n      assertCalledWithEl(props.onAfterLeave, trueSerialized)\n\n      toggle.value = true\n      await nextTick()\n      expect(serializeInner(root)).toBe(trueSerialized)\n      // before enter spy asserts node has no parent when it's called\n      expect(props.onBeforeEnter).toHaveBeenCalledTimes(1)\n      assertCalledWithEl(props.onBeforeEnter, trueSerialized)\n      expect(props.onEnter).toHaveBeenCalledTimes(1)\n      assertCalledWithEl(props.onEnter, trueSerialized)\n      expect(props.onAfterEnter).not.toHaveBeenCalled()\n      cbs.doneEnter[trueSerialized]()\n      expect(props.onAfterEnter).toHaveBeenCalledTimes(1)\n      assertCalledWithEl(props.onAfterEnter, trueSerialized)\n\n      assertCalls(props, {\n        onBeforeEnter: 1,\n        onEnter: 1,\n        onAfterEnter: 1,\n        onEnterCancelled: 0,\n        onBeforeLeave: 1,\n        onLeave: 1,\n        onAfterLeave: 1,\n        onLeaveCancelled: 0,\n      })\n    }\n\n    test('w/ element', async () => {\n      await testToggleOnOff({\n        trueBranch: () => h('div'),\n        trueSerialized: `<div></div>`,\n        falseBranch: () => null,\n        falseSerialized: `<!---->`,\n      })\n    })\n\n    test('w/ component', async () => {\n      const Comp = ({ msg }: { msg: string }) => h('div', msg)\n      await testToggleOnOff({\n        trueBranch: () => h(Comp, { msg: 'hello' }),\n        trueSerialized: `<div>hello</div>`,\n        falseBranch: () => null,\n        falseSerialized: `<!---->`,\n      })\n    })\n\n    test('w/ mode: \"in-out', async () => {\n      await testToggleOnOff(\n        {\n          trueBranch: () => h('div'),\n          trueSerialized: `<div></div>`,\n          falseBranch: () => null,\n          falseSerialized: `<!---->`,\n        },\n        'in-out',\n      )\n    })\n  })\n\n  describe('toggle on-off before finish', () => {\n    async function testToggleOnOffBeforeFinish({\n      trueBranch,\n      trueSerialized,\n      falseBranch = () => null,\n      falseSerialized = `<!---->`,\n    }: ToggleOptions) {\n      const toggle = ref(false)\n      const { props, cbs } = mockProps()\n      const { root } = mount(props, () =>\n        toggle.value ? trueBranch() : falseBranch(),\n      )\n\n      // start enter\n      toggle.value = true\n      await nextTick()\n      expect(serializeInner(root)).toBe(trueSerialized)\n      expect(props.onBeforeEnter).toHaveBeenCalledTimes(1)\n      expect(props.onEnter).toHaveBeenCalledTimes(1)\n\n      // leave before enter finishes\n      toggle.value = false\n      await nextTick()\n      expect(serializeInner(root)).toBe(`${trueSerialized}${falseSerialized}`)\n      expect(props.onEnterCancelled).toHaveBeenCalled()\n      expect(props.onBeforeLeave).toHaveBeenCalledTimes(1)\n      expect(props.onLeave).toHaveBeenCalledTimes(1)\n      expect(props.onAfterLeave).not.toHaveBeenCalled()\n      // calling doneEnter now should have no effect\n      cbs.doneEnter[trueSerialized]()\n      expect(props.onAfterEnter).not.toHaveBeenCalled()\n\n      // enter again before leave finishes\n      toggle.value = true\n      await nextTick()\n      expect(props.onBeforeEnter).toHaveBeenCalledTimes(2)\n      expect(props.onEnter).toHaveBeenCalledTimes(2)\n      // 1. should remove the previous leaving <div> so there is only one <div>\n      // 2. should remove the comment placeholder for the off branch\n      expect(serializeInner(root)).toBe(trueSerialized)\n      // note onLeaveCancelled is NOT called because it was a forced early\n      // removal instead of a cancel. Instead, onAfterLeave should be called.\n      expect(props.onAfterLeave).toHaveBeenCalledTimes(1)\n      // calling doneLeave again should have no effect now\n      cbs.doneLeave[trueSerialized]()\n      expect(props.onAfterLeave).toHaveBeenCalledTimes(1)\n      cbs.doneEnter[trueSerialized]()\n      expect(props.onAfterEnter).toHaveBeenCalledTimes(1)\n\n      assertCalls(props, {\n        onBeforeEnter: 2,\n        onEnter: 2,\n        onAfterEnter: 1,\n        onEnterCancelled: 1,\n        onBeforeLeave: 1,\n        onLeave: 1,\n        onAfterLeave: 1,\n        onLeaveCancelled: 0,\n      })\n    }\n\n    test('w/ element', async () => {\n      await testToggleOnOffBeforeFinish({\n        trueBranch: () => h('div'),\n        trueSerialized: `<div></div>`,\n        falseBranch: () => null,\n        falseSerialized: `<!---->`,\n      })\n    })\n\n    test('w/ component', async () => {\n      const Comp = ({ msg }: { msg: string }) => h('div', msg)\n      await testToggleOnOffBeforeFinish({\n        trueBranch: () => h(Comp, { msg: 'hello' }),\n        trueSerialized: `<div>hello</div>`,\n        falseBranch: () => null,\n        falseSerialized: `<!---->`,\n      })\n    })\n  })\n\n  describe('toggle between branches', () => {\n    async function testToggleBranches(\n      {\n        trueBranch,\n        falseBranch,\n        trueSerialized,\n        falseSerialized,\n      }: ToggleOptions,\n      withKeepAlive = false,\n    ) {\n      const toggle = ref(true)\n      const { props, cbs } = mockProps({}, withKeepAlive)\n      const { root } = mount(\n        props,\n        () => (toggle.value ? trueBranch() : falseBranch()),\n        withKeepAlive,\n      )\n\n      // without appear: true, enter hooks should not be called on mount\n      expect(props.onBeforeEnter).not.toHaveBeenCalled()\n      expect(props.onEnter).not.toHaveBeenCalled()\n      expect(props.onAfterEnter).not.toHaveBeenCalled()\n\n      // start toggle\n      toggle.value = false\n      await nextTick()\n      expect(serializeInner(root)).toBe(`${trueSerialized}${falseSerialized}`)\n      // leave should be triggered\n      expect(props.onBeforeLeave).toHaveBeenCalledTimes(1)\n      assertCalledWithEl(props.onBeforeLeave, trueSerialized)\n      expect(props.onLeave).toHaveBeenCalledTimes(1)\n      assertCalledWithEl(props.onLeave, trueSerialized)\n      expect(props.onAfterLeave).not.toHaveBeenCalled()\n      // enter should also be triggered\n      expect(props.onBeforeEnter).toHaveBeenCalledTimes(1)\n      assertCalledWithEl(props.onBeforeEnter, falseSerialized)\n      expect(props.onEnter).toHaveBeenCalledTimes(1)\n      assertCalledWithEl(props.onEnter, falseSerialized)\n      expect(props.onAfterEnter).not.toHaveBeenCalled()\n\n      // finish enter\n      cbs.doneEnter[falseSerialized]()\n      expect(serializeInner(root)).toBe(`${trueSerialized}${falseSerialized}`)\n      expect(props.onAfterEnter).toHaveBeenCalledTimes(1)\n      assertCalledWithEl(props.onAfterEnter, falseSerialized)\n      expect(props.onAfterLeave).not.toHaveBeenCalled()\n      // finish leave\n      cbs.doneLeave[trueSerialized]()\n      expect(serializeInner(root)).toBe(`${falseSerialized}`)\n      expect(props.onAfterLeave).toHaveBeenCalledTimes(1)\n      assertCalledWithEl(props.onAfterLeave, trueSerialized)\n\n      // toggle again\n      toggle.value = true\n      await nextTick()\n      expect(serializeInner(root)).toBe(`${falseSerialized}${trueSerialized}`)\n      // leave should be triggered\n      expect(props.onBeforeLeave).toHaveBeenCalledTimes(2)\n      assertCalledWithEl(props.onBeforeLeave, falseSerialized, 1)\n      expect(props.onLeave).toHaveBeenCalledTimes(2)\n      assertCalledWithEl(props.onLeave, falseSerialized, 1)\n      expect(props.onAfterLeave).toHaveBeenCalledTimes(1)\n      // enter should also be triggered\n      expect(props.onBeforeEnter).toHaveBeenCalledTimes(2)\n      assertCalledWithEl(props.onBeforeEnter, trueSerialized, 1)\n      expect(props.onEnter).toHaveBeenCalledTimes(2)\n      assertCalledWithEl(props.onEnter, trueSerialized, 1)\n      expect(props.onAfterEnter).toHaveBeenCalledTimes(1)\n\n      // finish leave first\n      cbs.doneLeave[falseSerialized]()\n      expect(serializeInner(root)).toBe(`${trueSerialized}`)\n      expect(props.onAfterLeave).toHaveBeenCalledTimes(2)\n      assertCalledWithEl(props.onAfterLeave, falseSerialized, 1)\n      expect(props.onAfterEnter).toHaveBeenCalledTimes(1)\n      // finish enter\n      cbs.doneEnter[trueSerialized]()\n      expect(serializeInner(root)).toBe(`${trueSerialized}`)\n      expect(props.onAfterEnter).toHaveBeenCalledTimes(2)\n      assertCalledWithEl(props.onAfterEnter, trueSerialized, 1)\n\n      assertCalls(props, {\n        onBeforeEnter: 2,\n        onEnter: 2,\n        onAfterEnter: 2,\n        onBeforeLeave: 2,\n        onLeave: 2,\n        onAfterLeave: 2,\n        onEnterCancelled: 0,\n        onLeaveCancelled: 0,\n      })\n    }\n\n    test('w/ elements', async () => {\n      await runTestWithElements(testToggleBranches)\n    })\n\n    test('w/ components', async () => {\n      await runTestWithComponents(testToggleBranches)\n    })\n\n    test('w/ KeepAlive', async () => {\n      await runTestWithKeepAlive(testToggleBranches)\n    })\n  })\n\n  describe('toggle between branches before finish', () => {\n    async function testToggleBranchesBeforeFinish(\n      {\n        trueBranch,\n        falseBranch,\n        trueSerialized,\n        falseSerialized,\n      }: ToggleOptions,\n      withKeepAlive = false,\n    ) {\n      const toggle = ref(true)\n      const { props, cbs } = mockProps({}, withKeepAlive)\n      const { root } = mount(\n        props,\n        () => (toggle.value ? trueBranch() : falseBranch()),\n        withKeepAlive,\n      )\n\n      // start toggle\n      toggle.value = false\n      await nextTick()\n      expect(serializeInner(root)).toBe(`${trueSerialized}${falseSerialized}`)\n      // leave should be triggered\n      expect(props.onBeforeLeave).toHaveBeenCalledTimes(1)\n      assertCalledWithEl(props.onBeforeLeave, trueSerialized)\n      expect(props.onLeave).toHaveBeenCalledTimes(1)\n      assertCalledWithEl(props.onLeave, trueSerialized)\n      expect(props.onAfterLeave).not.toHaveBeenCalled()\n      // enter should also be triggered\n      expect(props.onBeforeEnter).toHaveBeenCalledTimes(1)\n      assertCalledWithEl(props.onBeforeEnter, falseSerialized)\n      expect(props.onEnter).toHaveBeenCalledTimes(1)\n      assertCalledWithEl(props.onEnter, falseSerialized)\n      expect(props.onAfterEnter).not.toHaveBeenCalled()\n\n      // toggle again before transition finishes\n      toggle.value = true\n      await nextTick()\n      // the previous leaving true branch should have been force-removed\n      expect(serializeInner(root)).toBe(`${falseSerialized}${trueSerialized}`)\n      if (!withKeepAlive) {\n        expect(props.onAfterLeave).toHaveBeenCalledTimes(1)\n        assertCalledWithEl(props.onAfterLeave, trueSerialized)\n      } else {\n        expect(props.onLeaveCancelled).toHaveBeenCalledTimes(1)\n        assertCalledWithEl(props.onLeaveCancelled, trueSerialized)\n      }\n      // false branch enter is cancelled\n      expect(props.onEnterCancelled).toHaveBeenCalledTimes(1)\n      assertCalledWithEl(props.onEnterCancelled, falseSerialized)\n      // calling false branch done should have no effect now\n      cbs.doneEnter[falseSerialized]()\n      expect(props.onAfterEnter).not.toHaveBeenCalled()\n      // false branch leave triggered\n      expect(props.onBeforeLeave).toHaveBeenCalledTimes(2)\n      assertCalledWithEl(props.onBeforeLeave, falseSerialized, 1)\n      expect(props.onLeave).toHaveBeenCalledTimes(2)\n      assertCalledWithEl(props.onLeave, falseSerialized, 1)\n      // true branch enter triggered\n      expect(props.onBeforeEnter).toHaveBeenCalledTimes(2)\n      assertCalledWithEl(props.onBeforeEnter, trueSerialized, 1)\n      expect(props.onEnter).toHaveBeenCalledTimes(2)\n      assertCalledWithEl(props.onEnter, trueSerialized, 1)\n      expect(props.onAfterEnter).not.toHaveBeenCalled()\n\n      // toggle again\n      toggle.value = false\n      await nextTick()\n      // the previous leaving false branch should have been force-removed\n      expect(serializeInner(root)).toBe(`${trueSerialized}${falseSerialized}`)\n      if (!withKeepAlive) {\n        expect(props.onAfterLeave).toHaveBeenCalledTimes(2)\n        assertCalledWithEl(props.onAfterLeave, falseSerialized, 1)\n      } else {\n        expect(props.onLeaveCancelled).toHaveBeenCalledTimes(2)\n        assertCalledWithEl(props.onLeaveCancelled, falseSerialized, 1)\n      }\n      // true branch enter is cancelled\n      expect(props.onEnterCancelled).toHaveBeenCalledTimes(2)\n      assertCalledWithEl(props.onEnterCancelled, trueSerialized, 1)\n      // calling true branch enter done should have no effect\n      cbs.doneEnter[trueSerialized]()\n      expect(props.onAfterEnter).not.toHaveBeenCalled()\n      // true branch leave triggered (again)\n      expect(props.onBeforeLeave).toHaveBeenCalledTimes(3)\n      assertCalledWithEl(props.onBeforeLeave, trueSerialized, 2)\n      expect(props.onLeave).toHaveBeenCalledTimes(3)\n      assertCalledWithEl(props.onLeave, trueSerialized, 2)\n      // false branch enter triggered (again)\n      expect(props.onBeforeEnter).toHaveBeenCalledTimes(3)\n      assertCalledWithEl(props.onBeforeEnter, falseSerialized, 2)\n      expect(props.onEnter).toHaveBeenCalledTimes(3)\n      assertCalledWithEl(props.onEnter, falseSerialized, 2)\n      expect(props.onAfterEnter).not.toHaveBeenCalled()\n\n      cbs.doneEnter[falseSerialized]()\n      expect(props.onAfterEnter).toHaveBeenCalledTimes(1)\n      assertCalledWithEl(props.onAfterEnter, falseSerialized)\n\n      cbs.doneLeave[trueSerialized]()\n      if (!withKeepAlive) {\n        expect(props.onAfterLeave).toHaveBeenCalledTimes(3)\n        assertCalledWithEl(props.onAfterLeave, trueSerialized, 2)\n      } else {\n        expect(props.onAfterLeave).toHaveBeenCalledTimes(1)\n        assertCalledWithEl(props.onAfterLeave, trueSerialized)\n      }\n\n      assertCalls(props, {\n        onBeforeEnter: 3,\n        onEnter: 3,\n        onAfterEnter: 1,\n        onEnterCancelled: 2,\n        onBeforeLeave: 3,\n        onLeave: 3,\n        onAfterLeave: withKeepAlive ? 1 : 3,\n        onLeaveCancelled: withKeepAlive ? 2 : 0,\n      })\n    }\n\n    test('w/ elements', async () => {\n      await runTestWithElements(testToggleBranchesBeforeFinish)\n    })\n\n    test('w/ components', async () => {\n      await runTestWithComponents(testToggleBranchesBeforeFinish)\n    })\n\n    test('w/ KeepAlive', async () => {\n      await runTestWithKeepAlive(testToggleBranchesBeforeFinish)\n    })\n  })\n\n  describe('mode: \"out-in\"', () => {\n    async function testOutIn(\n      {\n        trueBranch,\n        falseBranch,\n        trueSerialized,\n        falseSerialized,\n      }: ToggleOptions,\n      withKeepAlive = false,\n    ) {\n      const toggle = ref(true)\n      const { props, cbs } = mockProps({ mode: 'out-in' }, withKeepAlive)\n      const { root } = mount(\n        props,\n        () => (toggle.value ? trueBranch() : falseBranch()),\n        withKeepAlive,\n      )\n\n      // trigger toggle\n      toggle.value = false\n      await nextTick()\n      // a placeholder is injected until the leave finishes\n      expect(serializeInner(root)).toBe(`${trueSerialized}<!---->`)\n      expect(props.onBeforeLeave).toHaveBeenCalledTimes(1)\n      assertCalledWithEl(props.onBeforeLeave, trueSerialized)\n      expect(props.onLeave).toHaveBeenCalledTimes(1)\n      assertCalledWithEl(props.onLeave, trueSerialized)\n      expect(props.onAfterLeave).not.toHaveBeenCalled()\n      // enter should not have started\n      expect(props.onBeforeEnter).not.toHaveBeenCalled()\n      expect(props.onEnter).not.toHaveBeenCalled()\n      expect(props.onAfterEnter).not.toHaveBeenCalled()\n\n      cbs.doneLeave[trueSerialized]()\n      expect(props.onAfterLeave).toHaveBeenCalledTimes(1)\n      assertCalledWithEl(props.onAfterLeave, trueSerialized)\n      // have to wait for a tick because this triggers an update\n      await nextTick()\n      expect(serializeInner(root)).toBe(falseSerialized)\n      // enter should start\n      expect(props.onBeforeEnter).toHaveBeenCalledTimes(1)\n      assertCalledWithEl(props.onBeforeEnter, falseSerialized)\n      expect(props.onEnter).toHaveBeenCalledTimes(1)\n      assertCalledWithEl(props.onEnter, falseSerialized)\n      expect(props.onAfterEnter).not.toHaveBeenCalled()\n      // finish enter\n      cbs.doneEnter[falseSerialized]()\n      expect(props.onAfterEnter).toHaveBeenCalledTimes(1)\n      assertCalledWithEl(props.onAfterEnter, falseSerialized)\n\n      // toggle again\n      toggle.value = true\n      await nextTick()\n      expect(serializeInner(root)).toBe(`${falseSerialized}<!---->`)\n      expect(props.onBeforeLeave).toHaveBeenCalledTimes(2)\n      assertCalledWithEl(props.onBeforeLeave, falseSerialized, 1)\n      expect(props.onLeave).toHaveBeenCalledTimes(2)\n      assertCalledWithEl(props.onLeave, falseSerialized, 1)\n      expect(props.onAfterLeave).toHaveBeenCalledTimes(1)\n      // enter should not have started\n      expect(props.onBeforeEnter).toHaveBeenCalledTimes(1)\n      expect(props.onEnter).toHaveBeenCalledTimes(1)\n      expect(props.onAfterEnter).toHaveBeenCalledTimes(1)\n\n      cbs.doneLeave[falseSerialized]()\n      expect(props.onAfterLeave).toHaveBeenCalledTimes(2)\n      assertCalledWithEl(props.onAfterLeave, falseSerialized, 1)\n      await nextTick()\n      expect(serializeInner(root)).toBe(trueSerialized)\n      // enter should start\n      expect(props.onBeforeEnter).toHaveBeenCalledTimes(2)\n      assertCalledWithEl(props.onBeforeEnter, trueSerialized, 1)\n      expect(props.onEnter).toHaveBeenCalledTimes(2)\n      assertCalledWithEl(props.onEnter, trueSerialized, 1)\n      expect(props.onAfterEnter).toHaveBeenCalledTimes(1)\n      // finish enter\n      cbs.doneEnter[trueSerialized]()\n      expect(props.onAfterEnter).toHaveBeenCalledTimes(2)\n      assertCalledWithEl(props.onAfterEnter, trueSerialized, 1)\n\n      assertCalls(props, {\n        onBeforeEnter: 2,\n        onEnter: 2,\n        onAfterEnter: 2,\n        onEnterCancelled: 0,\n        onBeforeLeave: 2,\n        onLeave: 2,\n        onAfterLeave: 2,\n        onLeaveCancelled: 0,\n      })\n    }\n\n    test('w/ elements', async () => {\n      await runTestWithElements(testOutIn)\n    })\n\n    test('w/ components', async () => {\n      await runTestWithComponents(testOutIn)\n    })\n\n    test('w/ KeepAlive', async () => {\n      await runTestWithKeepAlive(testOutIn)\n    })\n  })\n\n  // #6835\n  describe('mode: \"out-in\" toggle again after unmounted', () => {\n    async function testOutIn(\n      {\n        trueBranch,\n        falseBranch,\n        trueSerialized,\n        falseSerialized,\n      }: ToggleOptions,\n      withKeepAlive = false,\n    ) {\n      const toggle = ref(true)\n      const { props, cbs } = mockProps({ mode: 'out-in' }, withKeepAlive)\n      const { root, unmount } = mount(\n        props,\n        () => (toggle.value ? trueBranch() : falseBranch()),\n        withKeepAlive,\n      )\n\n      // trigger toggle\n      toggle.value = false\n      await nextTick()\n      // a placeholder is injected until the leave finishes\n      expect(serializeInner(root)).toBe(`${trueSerialized}<!---->`)\n      expect(props.onBeforeLeave).toHaveBeenCalledTimes(1)\n      assertCalledWithEl(props.onBeforeLeave, trueSerialized)\n      expect(props.onLeave).toHaveBeenCalledTimes(1)\n      assertCalledWithEl(props.onLeave, trueSerialized)\n      expect(props.onAfterLeave).not.toHaveBeenCalled()\n      // enter should not have started\n      expect(props.onBeforeEnter).not.toHaveBeenCalled()\n      expect(props.onEnter).not.toHaveBeenCalled()\n      expect(props.onAfterEnter).not.toHaveBeenCalled()\n\n      cbs.doneLeave[trueSerialized]()\n      expect(props.onAfterLeave).toHaveBeenCalledTimes(1)\n      assertCalledWithEl(props.onAfterLeave, trueSerialized)\n      // have to wait for a tick because this triggers an update\n      await nextTick()\n      expect(serializeInner(root)).toBe(falseSerialized)\n      // enter should start\n      expect(props.onBeforeEnter).toHaveBeenCalledTimes(1)\n      assertCalledWithEl(props.onBeforeEnter, falseSerialized)\n      expect(props.onEnter).toHaveBeenCalledTimes(1)\n      assertCalledWithEl(props.onEnter, falseSerialized)\n      expect(props.onAfterEnter).not.toHaveBeenCalled()\n      // finish enter\n      cbs.doneEnter[falseSerialized]()\n      expect(props.onAfterEnter).toHaveBeenCalledTimes(1)\n      assertCalledWithEl(props.onAfterEnter, falseSerialized)\n\n      unmount()\n      // toggle again after unmounted should not throw error\n      toggle.value = true\n      await nextTick()\n      expect(serializeInner(root)).toBe(`<!---->`)\n\n      assertCalls(props, {\n        onBeforeEnter: 1,\n        onEnter: 1,\n        onAfterEnter: 1,\n        onEnterCancelled: 0,\n        onBeforeLeave: 1,\n        onLeave: 1,\n        onAfterLeave: 1,\n        onLeaveCancelled: 0,\n      })\n    }\n\n    test('w/ elements', async () => {\n      await runTestWithElements(testOutIn)\n    })\n\n    test('w/ components', async () => {\n      await runTestWithComponents(testOutIn)\n    })\n\n    test('w/ KeepAlive', async () => {\n      await runTestWithKeepAlive(testOutIn)\n    })\n  })\n\n  describe('mode: \"out-in\" toggle before finish', () => {\n    async function testOutInBeforeFinish(\n      { trueBranch, falseBranch, trueSerialized }: ToggleOptions,\n      withKeepAlive = false,\n    ) {\n      const toggle = ref(true)\n      const { props, cbs } = mockProps({ mode: 'out-in' }, withKeepAlive)\n      const { root } = mount(\n        props,\n        () => (toggle.value ? trueBranch() : falseBranch()),\n        withKeepAlive,\n      )\n\n      // trigger toggle\n      toggle.value = false\n      await nextTick()\n      // toggle again before finish\n      toggle.value = true\n      await nextTick()\n      // expected behavior: the previous true branch is preserved,\n      // and a placeholder is injected for the replacement.\n      // the leaving node is replaced with the replace node (of the same branch)\n      // when it finishes leaving\n      expect(serializeInner(root)).toBe(`${trueSerialized}<!---->`)\n      // enter hooks should never be called (for neither branch)\n      expect(props.onBeforeEnter).not.toHaveBeenCalled()\n      expect(props.onEnter).not.toHaveBeenCalled()\n      expect(props.onAfterEnter).not.toHaveBeenCalled()\n\n      // finish leave\n      cbs.doneLeave[trueSerialized]()\n      expect(props.onAfterLeave).toHaveBeenCalledTimes(1)\n      assertCalledWithEl(props.onAfterLeave, trueSerialized)\n      await nextTick()\n      // leaving node and placeholder removed, enter node injected\n      expect(serializeInner(root)).toBe(trueSerialized)\n      // enter should start\n      expect(props.onBeforeEnter).toHaveBeenCalledTimes(1)\n      assertCalledWithEl(props.onBeforeEnter, trueSerialized)\n      expect(props.onEnter).toHaveBeenCalledTimes(1)\n      assertCalledWithEl(props.onEnter, trueSerialized)\n      expect(props.onAfterEnter).not.toHaveBeenCalled()\n      // finish enter\n      cbs.doneEnter[trueSerialized]()\n      expect(props.onAfterEnter).toHaveBeenCalledTimes(1)\n      assertCalledWithEl(props.onAfterEnter, trueSerialized)\n\n      assertCalls(props, {\n        onBeforeEnter: 1,\n        onEnter: 1,\n        onAfterEnter: 1,\n        onEnterCancelled: 0,\n        onBeforeLeave: 1,\n        onLeave: 1,\n        onAfterLeave: 1,\n        onLeaveCancelled: 0,\n      })\n    }\n\n    test('w/ elements', async () => {\n      await runTestWithElements(testOutInBeforeFinish)\n    })\n\n    test('w/ components', async () => {\n      await runTestWithComponents(testOutInBeforeFinish)\n    })\n\n    test('w/ KeepAlive', async () => {\n      await runTestWithKeepAlive(testOutInBeforeFinish)\n    })\n  })\n\n  describe('mode: \"out-in\" double quick toggle', () => {\n    async function testOutInDoubleToggle(\n      {\n        trueBranch,\n        falseBranch,\n        trueSerialized,\n        falseSerialized,\n      }: ToggleOptions,\n      withKeepAlive = false,\n    ) {\n      const toggle = ref(true)\n      const { props, cbs } = mockProps({ mode: 'out-in' }, withKeepAlive)\n      const { root } = mount(\n        props,\n        () => (toggle.value ? trueBranch() : falseBranch()),\n        withKeepAlive,\n      )\n\n      // double quick toggle\n      toggle.value = false\n      await nextTick()\n      toggle.value = true\n      await nextTick()\n      toggle.value = false\n      await nextTick()\n\n      // expected behavior: the leaving true branch is preserved no matter\n      // how many times the state is toggled as long as the leave isn't finished\n      // yet. A placeholder is injected for the replacement.\n      expect(serializeInner(root)).toBe(`${trueSerialized}<!---->`)\n      // enter hooks should never be called (for neither branch)\n      expect(props.onBeforeEnter).not.toHaveBeenCalled()\n      expect(props.onEnter).not.toHaveBeenCalled()\n      expect(props.onAfterEnter).not.toHaveBeenCalled()\n\n      // finish leave\n      cbs.doneLeave[trueSerialized]()\n      expect(props.onAfterLeave).toHaveBeenCalledTimes(1)\n      assertCalledWithEl(props.onAfterLeave, trueSerialized)\n      await nextTick()\n      // leaving node and placeholder removed, enter node injected\n      expect(serializeInner(root)).toBe(falseSerialized)\n      // enter should start\n      expect(props.onBeforeEnter).toHaveBeenCalledTimes(1)\n      assertCalledWithEl(props.onBeforeEnter, falseSerialized)\n      expect(props.onEnter).toHaveBeenCalledTimes(1)\n      assertCalledWithEl(props.onEnter, falseSerialized)\n      expect(props.onAfterEnter).not.toHaveBeenCalled()\n      // finish enter\n      cbs.doneEnter[falseSerialized]()\n      expect(props.onAfterEnter).toHaveBeenCalledTimes(1)\n      assertCalledWithEl(props.onAfterEnter, falseSerialized)\n\n      assertCalls(props, {\n        onBeforeEnter: 1,\n        onEnter: 1,\n        onAfterEnter: 1,\n        onEnterCancelled: 0,\n        onBeforeLeave: 1,\n        onLeave: 1,\n        onAfterLeave: 1,\n        onLeaveCancelled: 0,\n      })\n    }\n\n    test('w/ elements', async () => {\n      await runTestWithElements(testOutInDoubleToggle)\n    })\n\n    test('w/ components', async () => {\n      await runTestWithComponents(testOutInDoubleToggle)\n    })\n\n    test('w/ KeepAlive', async () => {\n      await runTestWithKeepAlive(testOutInDoubleToggle)\n    })\n  })\n\n  describe('mode: \"in-out\"', () => {\n    async function testInOut(\n      {\n        trueBranch,\n        falseBranch,\n        trueSerialized,\n        falseSerialized,\n      }: ToggleOptions,\n      withKeepAlive = false,\n    ) {\n      const toggle = ref(true)\n      const { props, cbs } = mockProps({ mode: 'in-out' }, withKeepAlive)\n      const { root } = mount(\n        props,\n        () => (toggle.value ? trueBranch() : falseBranch()),\n        withKeepAlive,\n      )\n\n      toggle.value = false\n      await nextTick()\n      expect(serializeInner(root)).toBe(`${trueSerialized}${falseSerialized}`)\n      // enter should start\n      expect(props.onBeforeEnter).toHaveBeenCalledTimes(1)\n      assertCalledWithEl(props.onBeforeEnter, falseSerialized)\n      expect(props.onEnter).toHaveBeenCalledTimes(1)\n      assertCalledWithEl(props.onEnter, falseSerialized)\n      expect(props.onAfterEnter).not.toHaveBeenCalled()\n      // leave should not start\n      expect(props.onBeforeLeave).not.toHaveBeenCalled()\n      expect(props.onLeave).not.toHaveBeenCalled()\n      expect(props.onAfterLeave).not.toHaveBeenCalled()\n\n      // finish enter\n      cbs.doneEnter[falseSerialized]()\n      expect(props.onAfterEnter).toHaveBeenCalledTimes(1)\n      assertCalledWithEl(props.onAfterEnter, falseSerialized)\n\n      // leave should start now\n      expect(props.onBeforeLeave).toHaveBeenCalledTimes(1)\n      assertCalledWithEl(props.onBeforeLeave, trueSerialized)\n      expect(props.onLeave).toHaveBeenCalledTimes(1)\n      assertCalledWithEl(props.onLeave, trueSerialized)\n      expect(props.onAfterLeave).not.toHaveBeenCalled()\n      // finish leave\n      cbs.doneLeave[trueSerialized]()\n      expect(props.onAfterLeave).toHaveBeenCalledTimes(1)\n      assertCalledWithEl(props.onAfterLeave, trueSerialized)\n\n      // toggle again\n      toggle.value = true\n      await nextTick()\n      expect(serializeInner(root)).toBe(`${falseSerialized}${trueSerialized}`)\n      // enter should start\n      expect(props.onBeforeEnter).toHaveBeenCalledTimes(2)\n      assertCalledWithEl(props.onBeforeEnter, trueSerialized, 1)\n      expect(props.onEnter).toHaveBeenCalledTimes(2)\n      assertCalledWithEl(props.onEnter, trueSerialized, 1)\n      expect(props.onAfterEnter).toHaveBeenCalledTimes(1)\n      // leave should not start\n      expect(props.onBeforeLeave).toHaveBeenCalledTimes(1)\n      expect(props.onLeave).toHaveBeenCalledTimes(1)\n      expect(props.onAfterLeave).toHaveBeenCalledTimes(1)\n\n      // finish enter\n      cbs.doneEnter[trueSerialized]()\n      expect(props.onAfterEnter).toHaveBeenCalledTimes(2)\n      assertCalledWithEl(props.onAfterEnter, trueSerialized, 1)\n\n      // leave should start now\n      expect(props.onBeforeLeave).toHaveBeenCalledTimes(2)\n      assertCalledWithEl(props.onBeforeLeave, falseSerialized, 1)\n      expect(props.onLeave).toHaveBeenCalledTimes(2)\n      assertCalledWithEl(props.onLeave, falseSerialized, 1)\n      expect(props.onAfterLeave).toHaveBeenCalledTimes(1)\n      // finish leave\n      cbs.doneLeave[falseSerialized]()\n      expect(props.onAfterLeave).toHaveBeenCalledTimes(2)\n      assertCalledWithEl(props.onAfterLeave, falseSerialized, 1)\n\n      assertCalls(props, {\n        onBeforeEnter: 2,\n        onEnter: 2,\n        onAfterEnter: 2,\n        onEnterCancelled: 0,\n        onBeforeLeave: 2,\n        onLeave: 2,\n        onAfterLeave: 2,\n        onLeaveCancelled: 0,\n      })\n    }\n\n    test('w/ elements', async () => {\n      await runTestWithElements(testInOut)\n    })\n\n    test('w/ components', async () => {\n      await runTestWithComponents(testInOut)\n    })\n\n    test('w/ KeepAlive', async () => {\n      await runTestWithKeepAlive(testInOut)\n    })\n  })\n\n  describe('mode: \"in-out\" toggle before finish', () => {\n    async function testInOutBeforeFinish(\n      {\n        trueBranch,\n        falseBranch,\n        trueSerialized,\n        falseSerialized,\n      }: ToggleOptions,\n      withKeepAlive = false,\n    ) {\n      const toggle = ref(true)\n      const { props, cbs } = mockProps({ mode: 'in-out' }, withKeepAlive)\n      const { root } = mount(\n        props,\n        () => (toggle.value ? trueBranch() : falseBranch()),\n        withKeepAlive,\n      )\n\n      toggle.value = false\n      await nextTick()\n      expect(serializeInner(root)).toBe(`${trueSerialized}${falseSerialized}`)\n\n      // toggle back before enter finishes\n      toggle.value = true\n      await nextTick()\n      // should force remove stale true branch\n      expect(serializeInner(root)).toBe(`${falseSerialized}${trueSerialized}`)\n      expect(props.onBeforeEnter).toHaveBeenCalledTimes(2)\n      assertCalledWithEl(props.onBeforeEnter, falseSerialized)\n      assertCalledWithEl(props.onBeforeEnter, trueSerialized, 1)\n      expect(props.onEnter).toHaveBeenCalledTimes(2)\n      assertCalledWithEl(props.onEnter, falseSerialized)\n      assertCalledWithEl(props.onEnter, trueSerialized, 1)\n      expect(props.onAfterEnter).not.toHaveBeenCalled()\n      expect(props.onEnterCancelled).not.toHaveBeenCalled()\n\n      // calling the enter done for false branch does fire the afterEnter\n      // hook, but should have no other effects since stale branch has already\n      // left\n      cbs.doneEnter[falseSerialized]()\n      expect(props.onAfterEnter).toHaveBeenCalledTimes(1)\n      assertCalledWithEl(props.onAfterEnter, falseSerialized)\n\n      // leave should not start for either branch\n      expect(props.onBeforeLeave).not.toHaveBeenCalled()\n      expect(props.onLeave).not.toHaveBeenCalled()\n      expect(props.onAfterLeave).not.toHaveBeenCalled()\n\n      cbs.doneEnter[trueSerialized]()\n      expect(props.onAfterEnter).toHaveBeenCalledTimes(2)\n      assertCalledWithEl(props.onAfterEnter, trueSerialized, 1)\n      // should start leave for false branch\n      expect(props.onBeforeLeave).toHaveBeenCalledTimes(1)\n      assertCalledWithEl(props.onBeforeLeave, falseSerialized)\n      expect(props.onLeave).toHaveBeenCalledTimes(1)\n      assertCalledWithEl(props.onLeave, falseSerialized)\n      expect(props.onAfterLeave).not.toHaveBeenCalled()\n      // finish leave\n      cbs.doneLeave[falseSerialized]()\n      expect(serializeInner(root)).toBe(trueSerialized)\n      expect(props.onAfterLeave).toHaveBeenCalledTimes(1)\n      assertCalledWithEl(props.onAfterLeave, falseSerialized)\n\n      assertCalls(props, {\n        onBeforeEnter: 2,\n        onEnter: 2,\n        onAfterEnter: 2,\n        onEnterCancelled: 0,\n        onBeforeLeave: 1,\n        onLeave: 1,\n        onAfterLeave: 1,\n        onLeaveCancelled: 0,\n      })\n    }\n\n    test('w/ elements', async () => {\n      await runTestWithElements(testInOutBeforeFinish)\n    })\n\n    test('w/ components', async () => {\n      await runTestWithComponents(testInOutBeforeFinish)\n    })\n\n    test('w/ KeepAlive', async () => {\n      await runTestWithKeepAlive(testInOutBeforeFinish)\n    })\n  })\n\n  // #10719\n  test('should not error on KeepAlive w/ function children', () => {\n    expect(() => mount({}, () => () => h('div'), true)).not.toThrow()\n  })\n\n  // #12465\n  test('mode: \"out-in\" w/ KeepAlive + fallthrough attrs (prod mode)', async () => {\n    __DEV__ = false\n    async function testOutIn({ trueBranch, falseBranch }: ToggleOptions) {\n      const toggle = ref(true)\n      const { props, cbs } = mockProps({ mode: 'out-in' }, true)\n      const root = nodeOps.createElement('div')\n      const App = {\n        render() {\n          return h(\n            BaseTransition,\n            {\n              ...props,\n              class: 'test',\n            },\n            () =>\n              h(KeepAlive, null, toggle.value ? trueBranch() : falseBranch()),\n          )\n        },\n      }\n      render(h(App), root)\n\n      expect(serializeInner(root)).toBe(`<div class=\"test\">0</div>`)\n\n      // trigger toggle\n      toggle.value = false\n      await nextTick()\n      expect(props.onBeforeLeave).toHaveBeenCalledTimes(1)\n      expect(serialize((props.onBeforeLeave as any).mock.calls[0][0])).toBe(\n        `<div class=\"test\">0</div>`,\n      )\n      expect(props.onLeave).toHaveBeenCalledTimes(1)\n      expect(serialize((props.onLeave as any).mock.calls[0][0])).toBe(\n        `<div class=\"test\">0</div>`,\n      )\n      expect(props.onAfterLeave).not.toHaveBeenCalled()\n      // enter should not have started\n      expect(props.onBeforeEnter).not.toHaveBeenCalled()\n      expect(props.onEnter).not.toHaveBeenCalled()\n      expect(props.onAfterEnter).not.toHaveBeenCalled()\n      cbs.doneLeave[`<div class=\"test\">0</div>`]()\n      expect(serializeInner(root)).toBe(`<span class=\"test\">0</span>`)\n    }\n    await runTestWithKeepAlive(testOutIn)\n    __DEV__ = true\n  })\n})\n"
  },
  {
    "path": "packages/runtime-core/__tests__/components/KeepAlive.spec.ts",
    "content": "import {\n  type Component,\n  type ComponentOptions,\n  type ComponentPublicInstance,\n  KeepAlive,\n  type Ref,\n  type TestElement,\n  cloneVNode,\n  createApp,\n  defineAsyncComponent,\n  defineComponent,\n  h,\n  inject,\n  markRaw,\n  nextTick,\n  nodeOps,\n  onActivated,\n  onDeactivated,\n  onMounted,\n  onUnmounted,\n  provide,\n  reactive,\n  ref,\n  render,\n  serializeInner,\n  shallowRef,\n} from '@vue/runtime-test'\nimport type { KeepAliveProps } from '../../src/components/KeepAlive'\n\nconst timeout = (n: number = 0) => new Promise(r => setTimeout(r, n))\n\ndescribe('KeepAlive', () => {\n  let one: ComponentOptions\n  let two: ComponentOptions\n  let oneTest: ComponentOptions\n  let views: Record<string, ComponentOptions>\n  let root: TestElement\n\n  beforeEach(() => {\n    root = nodeOps.createElement('div')\n    one = {\n      name: 'one',\n      data: () => ({ msg: 'one' }),\n      render(this: any) {\n        return h('div', this.msg)\n      },\n      created: vi.fn(),\n      mounted: vi.fn(),\n      activated: vi.fn(),\n      deactivated: vi.fn(),\n      unmounted: vi.fn(),\n    }\n    oneTest = {\n      name: 'oneTest',\n      data: () => ({ msg: 'oneTest' }),\n      render(this: any) {\n        return h('div', this.msg)\n      },\n      created: vi.fn(),\n      mounted: vi.fn(),\n      activated: vi.fn(),\n      deactivated: vi.fn(),\n      unmounted: vi.fn(),\n    }\n    two = {\n      name: 'two',\n      data: () => ({ msg: 'two' }),\n      render(this: any) {\n        return h('div', this.msg)\n      },\n      created: vi.fn(),\n      mounted: vi.fn(),\n      activated: vi.fn(),\n      deactivated: vi.fn(),\n      unmounted: vi.fn(),\n    }\n    views = {\n      one,\n      oneTest,\n      two,\n    }\n  })\n\n  function assertHookCalls(component: any, callCounts: number[]) {\n    expect([\n      component.created.mock.calls.length,\n      component.mounted.mock.calls.length,\n      component.activated.mock.calls.length,\n      component.deactivated.mock.calls.length,\n      component.unmounted.mock.calls.length,\n    ]).toEqual(callCounts)\n  }\n\n  test('should preserve state', async () => {\n    const viewRef = ref('one')\n    const instanceRef = ref<any>(null)\n    const App = {\n      render() {\n        return h(KeepAlive, null, {\n          default: () => h(views[viewRef.value], { ref: instanceRef }),\n        })\n      },\n    }\n    render(h(App), root)\n    expect(serializeInner(root)).toBe(`<div>one</div>`)\n    instanceRef.value.msg = 'changed'\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<div>changed</div>`)\n    viewRef.value = 'two'\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<div>two</div>`)\n    viewRef.value = 'one'\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<div>changed</div>`)\n  })\n\n  test('should call correct lifecycle hooks', async () => {\n    const toggle = ref(true)\n    const viewRef = ref('one')\n    const App = {\n      render() {\n        return toggle.value ? h(KeepAlive, () => h(views[viewRef.value])) : null\n      },\n    }\n    render(h(App), root)\n\n    expect(serializeInner(root)).toBe(`<div>one</div>`)\n    assertHookCalls(one, [1, 1, 1, 0, 0])\n    assertHookCalls(two, [0, 0, 0, 0, 0])\n\n    // toggle kept-alive component\n    viewRef.value = 'two'\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<div>two</div>`)\n    assertHookCalls(one, [1, 1, 1, 1, 0])\n    assertHookCalls(two, [1, 1, 1, 0, 0])\n\n    viewRef.value = 'one'\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<div>one</div>`)\n    assertHookCalls(one, [1, 1, 2, 1, 0])\n    assertHookCalls(two, [1, 1, 1, 1, 0])\n\n    viewRef.value = 'two'\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<div>two</div>`)\n    assertHookCalls(one, [1, 1, 2, 2, 0])\n    assertHookCalls(two, [1, 1, 2, 1, 0])\n\n    // teardown keep-alive, should unmount all components including cached\n    toggle.value = false\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<!---->`)\n    assertHookCalls(one, [1, 1, 2, 2, 1])\n    assertHookCalls(two, [1, 1, 2, 2, 1])\n  })\n\n  test('should call correct lifecycle hooks when toggle the KeepAlive first', async () => {\n    const toggle = ref(true)\n    const viewRef = ref('one')\n    const App = {\n      render() {\n        return toggle.value ? h(KeepAlive, () => h(views[viewRef.value])) : null\n      },\n    }\n    render(h(App), root)\n\n    expect(serializeInner(root)).toBe(`<div>one</div>`)\n    assertHookCalls(one, [1, 1, 1, 0, 0])\n    assertHookCalls(two, [0, 0, 0, 0, 0])\n\n    // should unmount 'one' component when toggle the KeepAlive first\n    toggle.value = false\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<!---->`)\n    assertHookCalls(one, [1, 1, 1, 1, 1])\n    assertHookCalls(two, [0, 0, 0, 0, 0])\n\n    toggle.value = true\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<div>one</div>`)\n    assertHookCalls(one, [2, 2, 2, 1, 1])\n    assertHookCalls(two, [0, 0, 0, 0, 0])\n\n    // 1. the first time toggle kept-alive component\n    viewRef.value = 'two'\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<div>two</div>`)\n    assertHookCalls(one, [2, 2, 2, 2, 1])\n    assertHookCalls(two, [1, 1, 1, 0, 0])\n\n    // 2. should unmount all components including cached\n    toggle.value = false\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<!---->`)\n    assertHookCalls(one, [2, 2, 2, 2, 2])\n    assertHookCalls(two, [1, 1, 1, 1, 1])\n  })\n\n  test('should call lifecycle hooks on nested components', async () => {\n    one.render = () => h(two)\n\n    const toggle = ref(true)\n    const App = {\n      render() {\n        return h(KeepAlive, () => (toggle.value ? h(one) : null))\n      },\n    }\n    render(h(App), root)\n\n    expect(serializeInner(root)).toBe(`<div>two</div>`)\n    assertHookCalls(one, [1, 1, 1, 0, 0])\n    assertHookCalls(two, [1, 1, 1, 0, 0])\n\n    toggle.value = false\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<!---->`)\n    assertHookCalls(one, [1, 1, 1, 1, 0])\n    assertHookCalls(two, [1, 1, 1, 1, 0])\n\n    toggle.value = true\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<div>two</div>`)\n    assertHookCalls(one, [1, 1, 2, 1, 0])\n    assertHookCalls(two, [1, 1, 2, 1, 0])\n\n    toggle.value = false\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<!---->`)\n    assertHookCalls(one, [1, 1, 2, 2, 0])\n    assertHookCalls(two, [1, 1, 2, 2, 0])\n  })\n\n  // #1742\n  test('should call lifecycle hooks on nested components when root component no hooks', async () => {\n    const two = {\n      name: 'two',\n      data: () => ({ msg: 'two' }),\n      render(this: any) {\n        return h('div', this.msg)\n      },\n      activated: vi.fn(),\n    }\n    const one = {\n      name: 'one',\n      data: () => ({ msg: 'one' }),\n      render(this: any) {\n        return h(two)\n      },\n    }\n\n    const toggle = ref(true)\n    const App = {\n      render() {\n        return h(KeepAlive, () => (toggle.value ? h(one) : null))\n      },\n    }\n    render(h(App), root)\n\n    expect(serializeInner(root)).toBe(`<div>two</div>`)\n    expect(two.activated).toHaveBeenCalledTimes(1)\n  })\n\n  test('should call correct hooks for nested keep-alive', async () => {\n    const toggle2 = ref(true)\n    one.render = () => h(KeepAlive, () => (toggle2.value ? h(two) : null))\n\n    const toggle1 = ref(true)\n    const App = {\n      render() {\n        return h(KeepAlive, () => (toggle1.value ? h(one) : null))\n      },\n    }\n    render(h(App), root)\n\n    expect(serializeInner(root)).toBe(`<div>two</div>`)\n    assertHookCalls(one, [1, 1, 1, 0, 0])\n    assertHookCalls(two, [1, 1, 1, 0, 0])\n\n    toggle1.value = false\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<!---->`)\n    assertHookCalls(one, [1, 1, 1, 1, 0])\n    assertHookCalls(two, [1, 1, 1, 1, 0])\n\n    toggle1.value = true\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<div>two</div>`)\n    assertHookCalls(one, [1, 1, 2, 1, 0])\n    assertHookCalls(two, [1, 1, 2, 1, 0])\n\n    // toggle nested instance\n    toggle2.value = false\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<!---->`)\n    assertHookCalls(one, [1, 1, 2, 1, 0])\n    assertHookCalls(two, [1, 1, 2, 2, 0])\n\n    toggle2.value = true\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<div>two</div>`)\n    assertHookCalls(one, [1, 1, 2, 1, 0])\n    assertHookCalls(two, [1, 1, 3, 2, 0])\n\n    toggle1.value = false\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<!---->`)\n    assertHookCalls(one, [1, 1, 2, 2, 0])\n    assertHookCalls(two, [1, 1, 3, 3, 0])\n\n    // toggle nested instance when parent is deactivated\n    toggle2.value = false\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<!---->`)\n    assertHookCalls(one, [1, 1, 2, 2, 0])\n    assertHookCalls(two, [1, 1, 3, 3, 0]) // should not be affected\n\n    toggle2.value = true\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<!---->`)\n    assertHookCalls(one, [1, 1, 2, 2, 0])\n    assertHookCalls(two, [1, 1, 3, 3, 0]) // should not be affected\n\n    toggle1.value = true\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<div>two</div>`)\n    assertHookCalls(one, [1, 1, 3, 2, 0])\n    assertHookCalls(two, [1, 1, 4, 3, 0])\n\n    toggle1.value = false\n    toggle2.value = false\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<!---->`)\n    assertHookCalls(one, [1, 1, 3, 3, 0])\n    assertHookCalls(two, [1, 1, 4, 4, 0])\n\n    toggle1.value = true\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<!---->`)\n    assertHookCalls(one, [1, 1, 4, 3, 0])\n    assertHookCalls(two, [1, 1, 4, 4, 0]) // should remain inactive\n  })\n\n  async function assertNameMatch(props: KeepAliveProps) {\n    const outerRef = ref(true)\n    const viewRef = ref('one')\n    const App = {\n      render() {\n        return outerRef.value\n          ? h(KeepAlive, props, () => h(views[viewRef.value]))\n          : null\n      },\n    }\n    render(h(App), root)\n\n    expect(serializeInner(root)).toBe(`<div>one</div>`)\n    assertHookCalls(one, [1, 1, 1, 0, 0])\n    assertHookCalls(two, [0, 0, 0, 0, 0])\n\n    viewRef.value = 'two'\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<div>two</div>`)\n    assertHookCalls(one, [1, 1, 1, 1, 0])\n    assertHookCalls(two, [1, 1, 0, 0, 0])\n\n    viewRef.value = 'one'\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<div>one</div>`)\n    assertHookCalls(one, [1, 1, 2, 1, 0])\n    assertHookCalls(two, [1, 1, 0, 0, 1])\n\n    viewRef.value = 'two'\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<div>two</div>`)\n    assertHookCalls(one, [1, 1, 2, 2, 0])\n    assertHookCalls(two, [2, 2, 0, 0, 1])\n\n    // teardown\n    outerRef.value = false\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<!---->`)\n    assertHookCalls(one, [1, 1, 2, 2, 1])\n    assertHookCalls(two, [2, 2, 0, 0, 2])\n  }\n\n  async function assertNameMatchWithFlag(props: KeepAliveProps) {\n    const outerRef = ref(true)\n    const viewRef = ref('one')\n    const App = {\n      render() {\n        return outerRef.value\n          ? h(KeepAlive, props, () => h(views[viewRef.value]))\n          : null\n      },\n    }\n    render(h(App), root)\n\n    expect(serializeInner(root)).toBe(`<div>one</div>`)\n    assertHookCalls(one, [1, 1, 1, 0, 0])\n    assertHookCalls(oneTest, [0, 0, 0, 0, 0])\n    assertHookCalls(two, [0, 0, 0, 0, 0])\n\n    viewRef.value = 'oneTest'\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<div>oneTest</div>`)\n    assertHookCalls(one, [1, 1, 1, 1, 0])\n    assertHookCalls(oneTest, [1, 1, 1, 0, 0])\n    assertHookCalls(two, [0, 0, 0, 0, 0])\n\n    viewRef.value = 'two'\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<div>two</div>`)\n    assertHookCalls(one, [1, 1, 1, 1, 0])\n    assertHookCalls(oneTest, [1, 1, 1, 1, 0])\n    assertHookCalls(two, [1, 1, 0, 0, 0])\n\n    viewRef.value = 'one'\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<div>one</div>`)\n    assertHookCalls(one, [1, 1, 2, 1, 0])\n    assertHookCalls(oneTest, [1, 1, 1, 1, 0])\n    assertHookCalls(two, [1, 1, 0, 0, 1])\n\n    viewRef.value = 'oneTest'\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<div>oneTest</div>`)\n    assertHookCalls(one, [1, 1, 2, 2, 0])\n    assertHookCalls(oneTest, [1, 1, 2, 1, 0])\n    assertHookCalls(two, [1, 1, 0, 0, 1])\n\n    viewRef.value = 'two'\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<div>two</div>`)\n    assertHookCalls(one, [1, 1, 2, 2, 0])\n    assertHookCalls(oneTest, [1, 1, 2, 2, 0])\n    assertHookCalls(two, [2, 2, 0, 0, 1])\n\n    // teardown\n    outerRef.value = false\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<!---->`)\n    assertHookCalls(one, [1, 1, 2, 2, 1])\n    assertHookCalls(oneTest, [1, 1, 2, 2, 1])\n    assertHookCalls(two, [2, 2, 0, 0, 2])\n  }\n\n  async function assertNameMatchWithFlagExclude(props: KeepAliveProps) {\n    const outerRef = ref(true)\n    const viewRef = ref('one')\n    const App = {\n      render() {\n        return outerRef.value\n          ? h(KeepAlive, props, () => h(views[viewRef.value]))\n          : null\n      },\n    }\n    render(h(App), root)\n\n    expect(serializeInner(root)).toBe(`<div>one</div>`)\n    assertHookCalls(one, [1, 1, 0, 0, 0])\n    assertHookCalls(oneTest, [0, 0, 0, 0, 0])\n    assertHookCalls(two, [0, 0, 0, 0, 0])\n\n    viewRef.value = 'oneTest'\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<div>oneTest</div>`)\n    assertHookCalls(one, [1, 1, 0, 0, 1])\n    assertHookCalls(oneTest, [1, 1, 0, 0, 0])\n    assertHookCalls(two, [0, 0, 0, 0, 0])\n\n    viewRef.value = 'two'\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<div>two</div>`)\n    assertHookCalls(one, [1, 1, 0, 0, 1])\n    assertHookCalls(oneTest, [1, 1, 0, 0, 1])\n    assertHookCalls(two, [1, 1, 1, 0, 0])\n\n    viewRef.value = 'one'\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<div>one</div>`)\n    assertHookCalls(one, [2, 2, 0, 0, 1])\n    assertHookCalls(oneTest, [1, 1, 0, 0, 1])\n    assertHookCalls(two, [1, 1, 1, 1, 0])\n\n    viewRef.value = 'oneTest'\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<div>oneTest</div>`)\n    assertHookCalls(one, [2, 2, 0, 0, 2])\n    assertHookCalls(oneTest, [2, 2, 0, 0, 1])\n    assertHookCalls(two, [1, 1, 1, 1, 0])\n\n    viewRef.value = 'two'\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<div>two</div>`)\n    assertHookCalls(one, [2, 2, 0, 0, 2])\n    assertHookCalls(oneTest, [2, 2, 0, 0, 2])\n    assertHookCalls(two, [1, 1, 2, 1, 0])\n\n    // teardown\n    outerRef.value = false\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<!---->`)\n    assertHookCalls(one, [2, 2, 0, 0, 2])\n    assertHookCalls(oneTest, [2, 2, 0, 0, 2])\n    assertHookCalls(two, [1, 1, 2, 2, 1])\n  }\n\n  describe('props', () => {\n    test('include (string)', async () => {\n      await assertNameMatch({ include: 'one' })\n    })\n\n    test('include (regex)', async () => {\n      await assertNameMatch({ include: /^one$/ })\n    })\n\n    test('include (regex with g flag)', async () => {\n      await assertNameMatchWithFlag({ include: /one/g })\n    })\n\n    test('include (array)', async () => {\n      await assertNameMatch({ include: ['one'] })\n    })\n\n    test('exclude (string)', async () => {\n      await assertNameMatch({ exclude: 'two' })\n    })\n\n    test('exclude (regex)', async () => {\n      await assertNameMatch({ exclude: /^two$/ })\n    })\n\n    test('exclude (regex with a flag)', async () => {\n      await assertNameMatchWithFlagExclude({ exclude: /one/g })\n    })\n\n    test('exclude (array)', async () => {\n      await assertNameMatch({ exclude: ['two'] })\n    })\n\n    test('include + exclude', async () => {\n      await assertNameMatch({ include: 'one,two', exclude: 'two' })\n    })\n\n    test('max', async () => {\n      const spyAC = vi.fn()\n      const spyBC = vi.fn()\n      const spyCC = vi.fn()\n      const spyAA = vi.fn()\n      const spyBA = vi.fn()\n      const spyCA = vi.fn()\n      const spyADA = vi.fn()\n      const spyBDA = vi.fn()\n      const spyCDA = vi.fn()\n      const spyAUM = vi.fn()\n      const spyBUM = vi.fn()\n      const spyCUM = vi.fn()\n\n      function assertCount(calls: number[]) {\n        expect([\n          spyAC.mock.calls.length,\n          spyAA.mock.calls.length,\n          spyADA.mock.calls.length,\n          spyAUM.mock.calls.length,\n          spyBC.mock.calls.length,\n          spyBA.mock.calls.length,\n          spyBDA.mock.calls.length,\n          spyBUM.mock.calls.length,\n          spyCC.mock.calls.length,\n          spyCA.mock.calls.length,\n          spyCDA.mock.calls.length,\n          spyCUM.mock.calls.length,\n        ]).toEqual(calls)\n      }\n\n      const viewRef = ref('a')\n      const views: Record<string, ComponentOptions> = {\n        a: {\n          render: () => `one`,\n          created: spyAC,\n          activated: spyAA,\n          deactivated: spyADA,\n          unmounted: spyAUM,\n        },\n        b: {\n          render: () => `two`,\n          created: spyBC,\n          activated: spyBA,\n          deactivated: spyBDA,\n          unmounted: spyBUM,\n        },\n        c: {\n          render: () => `three`,\n          created: spyCC,\n          activated: spyCA,\n          deactivated: spyCDA,\n          unmounted: spyCUM,\n        },\n      }\n\n      const App = {\n        render() {\n          return h(KeepAlive, { max: 2 }, () => {\n            return h(views[viewRef.value])\n          })\n        },\n      }\n      render(h(App), root)\n      assertCount([1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])\n\n      viewRef.value = 'b'\n      await nextTick()\n      assertCount([1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0])\n\n      viewRef.value = 'c'\n      await nextTick()\n      // should prune A because max cache reached\n      assertCount([1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0])\n\n      viewRef.value = 'b'\n      await nextTick()\n      // B should be reused, and made latest\n      assertCount([1, 1, 1, 1, 1, 2, 1, 0, 1, 1, 1, 0])\n\n      viewRef.value = 'a'\n      await nextTick()\n      // C should be pruned because B was used last so C is the oldest cached\n      assertCount([2, 2, 1, 1, 1, 2, 2, 0, 1, 1, 1, 1])\n    })\n  })\n\n  describe('cache invalidation', () => {\n    function setup() {\n      const viewRef = ref('one')\n      const includeRef = ref('one,two')\n      const App = {\n        render() {\n          return h(\n            KeepAlive,\n            {\n              include: includeRef.value,\n            },\n            () => h(views[viewRef.value]),\n          )\n        },\n      }\n      render(h(App), root)\n      return { viewRef, includeRef }\n    }\n\n    function setupExclude() {\n      const viewRef = ref('one')\n      const excludeRef = ref('')\n      const App = {\n        render() {\n          return h(\n            KeepAlive,\n            {\n              exclude: excludeRef.value,\n            },\n            () => h(views[viewRef.value]),\n          )\n        },\n      }\n      render(h(App), root)\n      return { viewRef, excludeRef }\n    }\n\n    test('on include change', async () => {\n      const { viewRef, includeRef } = setup()\n\n      viewRef.value = 'two'\n      await nextTick()\n      assertHookCalls(one, [1, 1, 1, 1, 0])\n      assertHookCalls(two, [1, 1, 1, 0, 0])\n\n      includeRef.value = 'two'\n      await nextTick()\n      assertHookCalls(one, [1, 1, 1, 1, 1])\n      assertHookCalls(two, [1, 1, 1, 0, 0])\n\n      viewRef.value = 'one'\n      await nextTick()\n      assertHookCalls(one, [2, 2, 1, 1, 1])\n      assertHookCalls(two, [1, 1, 1, 1, 0])\n    })\n\n    test('on exclude change', async () => {\n      const { viewRef, excludeRef } = setupExclude()\n\n      viewRef.value = 'two'\n      await nextTick()\n      assertHookCalls(one, [1, 1, 1, 1, 0])\n      assertHookCalls(two, [1, 1, 1, 0, 0])\n\n      excludeRef.value = 'one'\n      await nextTick()\n      assertHookCalls(one, [1, 1, 1, 1, 1])\n      assertHookCalls(two, [1, 1, 1, 0, 0])\n\n      viewRef.value = 'one'\n      await nextTick()\n      assertHookCalls(one, [2, 2, 1, 1, 1])\n      assertHookCalls(two, [1, 1, 1, 1, 0])\n    })\n\n    test('on include change + view switch', async () => {\n      const { viewRef, includeRef } = setup()\n\n      viewRef.value = 'two'\n      await nextTick()\n      assertHookCalls(one, [1, 1, 1, 1, 0])\n      assertHookCalls(two, [1, 1, 1, 0, 0])\n\n      includeRef.value = 'one'\n      viewRef.value = 'one'\n      await nextTick()\n      assertHookCalls(one, [1, 1, 2, 1, 0])\n      // two should be pruned\n      assertHookCalls(two, [1, 1, 1, 1, 1])\n    })\n\n    test('on exclude change + view switch', async () => {\n      const { viewRef, excludeRef } = setupExclude()\n\n      viewRef.value = 'two'\n      await nextTick()\n      assertHookCalls(one, [1, 1, 1, 1, 0])\n      assertHookCalls(two, [1, 1, 1, 0, 0])\n\n      excludeRef.value = 'two'\n      viewRef.value = 'one'\n      await nextTick()\n      assertHookCalls(one, [1, 1, 2, 1, 0])\n      // two should be pruned\n      assertHookCalls(two, [1, 1, 1, 1, 1])\n    })\n\n    test('should not prune current active instance', async () => {\n      const { viewRef, includeRef } = setup()\n\n      includeRef.value = 'two'\n      await nextTick()\n      assertHookCalls(one, [1, 1, 1, 0, 0])\n      assertHookCalls(two, [0, 0, 0, 0, 0])\n\n      viewRef.value = 'two'\n      await nextTick()\n      assertHookCalls(one, [1, 1, 1, 0, 1])\n      assertHookCalls(two, [1, 1, 1, 0, 0])\n    })\n\n    async function assertAnonymous(include: boolean) {\n      const one = {\n        name: 'one',\n        created: vi.fn(),\n        render: () => 'one',\n      }\n\n      const two = {\n        // anonymous\n        created: vi.fn(),\n        render: () => 'two',\n      }\n\n      const views: any = { one, two }\n      const viewRef = ref('one')\n\n      const App = {\n        render() {\n          return h(\n            KeepAlive,\n            {\n              include: include ? 'one' : undefined,\n            },\n            () => h(views[viewRef.value]),\n          )\n        },\n      }\n      render(h(App), root)\n\n      function assert(oneCreateCount: number, twoCreateCount: number) {\n        expect(one.created.mock.calls.length).toBe(oneCreateCount)\n        expect(two.created.mock.calls.length).toBe(twoCreateCount)\n      }\n\n      assert(1, 0)\n\n      viewRef.value = 'two'\n      await nextTick()\n      assert(1, 1)\n\n      viewRef.value = 'one'\n      await nextTick()\n      assert(1, 1)\n\n      viewRef.value = 'two'\n      await nextTick()\n      // two should be re-created if include is specified, since it's not matched\n      // otherwise it should be cached.\n      assert(1, include ? 2 : 1)\n    }\n\n    // 2.x #6938\n    test('should not cache anonymous component when include is specified', async () => {\n      await assertAnonymous(true)\n    })\n\n    test('should cache anonymous components if include is not specified', async () => {\n      await assertAnonymous(false)\n    })\n\n    // 2.x #7105\n    test('should not destroy active instance when pruning cache', async () => {\n      const Foo = {\n        render: () => 'foo',\n        unmounted: vi.fn(),\n      }\n      const includeRef = ref(['foo'])\n      const App = {\n        render() {\n          return h(\n            KeepAlive,\n            {\n              include: includeRef.value,\n            },\n            () => h(Foo),\n          )\n        },\n      }\n      render(h(App), root)\n      // condition: a render where a previous component is reused\n      includeRef.value = ['foo', 'bar']\n      await nextTick()\n      includeRef.value = []\n      await nextTick()\n      expect(Foo.unmounted).not.toHaveBeenCalled()\n    })\n\n    test('should update re-activated component if props have changed', async () => {\n      const Foo = (props: { n: number }) => props.n\n\n      const toggle = ref(true)\n      const n = ref(0)\n\n      const App = {\n        setup() {\n          return () =>\n            h(KeepAlive, () => (toggle.value ? h(Foo, { n: n.value }) : null))\n        },\n      }\n\n      render(h(App), root)\n      expect(serializeInner(root)).toBe(`0`)\n\n      toggle.value = false\n      await nextTick()\n      expect(serializeInner(root)).toBe(`<!---->`)\n\n      n.value++\n      await nextTick()\n      toggle.value = true\n      await nextTick()\n      expect(serializeInner(root)).toBe(`1`)\n    })\n  })\n\n  it('should call correct vnode hooks', async () => {\n    const Foo = markRaw({\n      name: 'Foo',\n      render() {\n        return h('Foo')\n      },\n    })\n    const Bar = markRaw({\n      name: 'Bar',\n      render() {\n        return h('Bar')\n      },\n    })\n\n    const spyMounted = vi.fn()\n    const spyUnmounted = vi.fn()\n\n    const RouterView = defineComponent({\n      setup(_, { slots }) {\n        const Component = inject<Ref<ComponentPublicInstance>>('component')\n        const refView = ref()\n\n        let componentProps = {\n          ref: refView,\n          onVnodeMounted() {\n            spyMounted()\n          },\n          onVnodeUnmounted() {\n            spyUnmounted()\n          },\n        }\n\n        return () => {\n          const child: any = slots.default!({\n            Component: Component!.value,\n          })[0]\n\n          const innerChild = child.children[0]\n          child.children[0] = cloneVNode(innerChild, componentProps)\n          return child\n        }\n      },\n    })\n\n    let toggle: () => void = () => {}\n\n    const App = defineComponent({\n      setup() {\n        const component = ref(Foo)\n\n        provide('component', component)\n\n        toggle = () => {\n          component.value = component.value === Foo ? Bar : Foo\n        }\n        return {\n          component,\n          toggle,\n        }\n      },\n      render() {\n        return h(RouterView, null, {\n          default: ({ Component }: any) => h(KeepAlive, null, [h(Component)]),\n        })\n      },\n    })\n\n    render(h(App), root)\n    await nextTick()\n    expect(spyMounted).toHaveBeenCalledTimes(1)\n    expect(spyUnmounted).toHaveBeenCalledTimes(0)\n\n    toggle()\n    await nextTick()\n\n    expect(spyMounted).toHaveBeenCalledTimes(2)\n    expect(spyUnmounted).toHaveBeenCalledTimes(1)\n\n    toggle()\n    await nextTick()\n    expect(spyMounted).toHaveBeenCalledTimes(3)\n    expect(spyUnmounted).toHaveBeenCalledTimes(2)\n\n    render(null, root)\n    await nextTick()\n    expect(spyMounted).toHaveBeenCalledTimes(3)\n    expect(spyUnmounted).toHaveBeenCalledTimes(4)\n  })\n\n  // #1511\n  test('should work with cloned root due to scopeId / fallthrough attrs', async () => {\n    const viewRef = ref('one')\n    const instanceRef = ref<any>(null)\n    const App = {\n      __scopeId: 'foo',\n      render: () => {\n        return h(KeepAlive, null, {\n          default: () => h(views[viewRef.value], { ref: instanceRef }),\n        })\n      },\n    }\n    render(h(App), root)\n    expect(serializeInner(root)).toBe(`<div foo>one</div>`)\n    instanceRef.value.msg = 'changed'\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<div foo>changed</div>`)\n    viewRef.value = 'two'\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<div foo>two</div>`)\n    viewRef.value = 'one'\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<div foo>changed</div>`)\n  })\n\n  test('should work with async component', async () => {\n    let resolve: (comp: Component) => void\n    const AsyncComp = defineAsyncComponent(\n      () =>\n        new Promise(r => {\n          resolve = r as any\n        }),\n    )\n\n    const toggle = ref(true)\n    const instanceRef = ref<any>(null)\n    const App = {\n      render: () => {\n        return h(KeepAlive, { include: 'Foo' }, () =>\n          toggle.value ? h(AsyncComp, { ref: instanceRef }) : null,\n        )\n      },\n    }\n\n    render(h(App), root)\n    // async component has not been resolved\n    expect(serializeInner(root)).toBe('<!---->')\n\n    resolve!({\n      name: 'Foo',\n      data: () => ({ count: 0 }),\n      render() {\n        return h('p', this.count)\n      },\n    })\n\n    await timeout()\n    // resolved\n    expect(serializeInner(root)).toBe('<p>0</p>')\n\n    // change state + toggle out\n    instanceRef.value.count++\n    toggle.value = false\n    await nextTick()\n    expect(serializeInner(root)).toBe('<!---->')\n\n    // toggle in, state should be maintained\n    toggle.value = true\n    await nextTick()\n    expect(serializeInner(root)).toBe('<p>1</p>')\n  })\n\n  // #4976\n  test('handle error in async onActivated', async () => {\n    const err = new Error('foo')\n    const handler = vi.fn()\n\n    const app = createApp({\n      setup() {\n        return () => h(KeepAlive, null, () => h(Child))\n      },\n    })\n\n    const Child = {\n      setup() {\n        onActivated(async () => {\n          throw err\n        })\n      },\n      render() {},\n    }\n\n    app.config.errorHandler = handler\n    app.mount(nodeOps.createElement('div'))\n\n    await nextTick()\n    expect(handler).toHaveBeenCalledWith(err, {}, 'activated hook')\n  })\n\n  // #3648\n  test('should avoid unmount later included components', async () => {\n    const unmountedA = vi.fn()\n    const mountedA = vi.fn()\n    const activatedA = vi.fn()\n    const deactivatedA = vi.fn()\n    const unmountedB = vi.fn()\n    const mountedB = vi.fn()\n\n    const A = {\n      name: 'A',\n      setup() {\n        onMounted(mountedA)\n        onUnmounted(unmountedA)\n        onActivated(activatedA)\n        onDeactivated(deactivatedA)\n        return () => 'A'\n      },\n    }\n    const B = {\n      name: 'B',\n      setup() {\n        onMounted(mountedB)\n        onUnmounted(unmountedB)\n        return () => 'B'\n      },\n    }\n\n    const include = reactive<string[]>([])\n    const current = shallowRef(A)\n    const app = createApp({\n      setup() {\n        return () => {\n          return [\n            h(\n              KeepAlive,\n              {\n                include,\n              },\n              h(current.value),\n            ),\n          ]\n        }\n      },\n    })\n\n    app.mount(root)\n\n    expect(serializeInner(root)).toBe(`A`)\n    expect(mountedA).toHaveBeenCalledTimes(1)\n    expect(unmountedA).toHaveBeenCalledTimes(0)\n    expect(activatedA).toHaveBeenCalledTimes(0)\n    expect(deactivatedA).toHaveBeenCalledTimes(0)\n    expect(mountedB).toHaveBeenCalledTimes(0)\n    expect(unmountedB).toHaveBeenCalledTimes(0)\n\n    include.push('A') // cache A\n    await nextTick()\n    current.value = B // toggle to B\n    await nextTick()\n    expect(serializeInner(root)).toBe(`B`)\n    expect(mountedA).toHaveBeenCalledTimes(1)\n    expect(unmountedA).toHaveBeenCalledTimes(0)\n    expect(activatedA).toHaveBeenCalledTimes(0)\n    expect(deactivatedA).toHaveBeenCalledTimes(1)\n    expect(mountedB).toHaveBeenCalledTimes(1)\n    expect(unmountedB).toHaveBeenCalledTimes(0)\n  })\n\n  // #11717\n  test('remove component from include then switching child', async () => {\n    const About = {\n      name: 'About',\n      render() {\n        return h('h1', 'About')\n      },\n    }\n    const mountedHome = vi.fn()\n    const unmountedHome = vi.fn()\n    const activatedHome = vi.fn()\n    const deactivatedHome = vi.fn()\n    const Home = {\n      name: 'Home',\n      setup() {\n        onMounted(mountedHome)\n        onUnmounted(unmountedHome)\n        onDeactivated(deactivatedHome)\n        onActivated(activatedHome)\n        return () => {\n          h('h1', 'Home')\n        }\n      },\n    }\n    const activeViewName = ref('Home')\n    const cacheList = reactive(['Home'])\n    const App = createApp({\n      setup() {\n        return () => {\n          return [\n            h(\n              KeepAlive,\n              {\n                include: cacheList,\n              },\n              [activeViewName.value === 'Home' ? h(Home) : h(About)],\n            ),\n          ]\n        }\n      },\n    })\n    App.mount(nodeOps.createElement('div'))\n    expect(mountedHome).toHaveBeenCalledTimes(1)\n    expect(activatedHome).toHaveBeenCalledTimes(1)\n    cacheList.splice(0, 1)\n    await nextTick()\n    activeViewName.value = 'About'\n    await nextTick()\n    expect(deactivatedHome).toHaveBeenCalledTimes(0)\n    expect(unmountedHome).toHaveBeenCalledTimes(1)\n  })\n\n  test('should work with async component when update `include` props', async () => {\n    let resolve: (comp: Component) => void\n    const AsyncComp = defineAsyncComponent(\n      () =>\n        new Promise(r => {\n          resolve = r as any\n        }),\n    )\n\n    const toggle = ref(true)\n    const instanceRef = ref<any>(null)\n    const keepaliveInclude = ref(['Foo'])\n    const App = {\n      render: () => {\n        return h(KeepAlive, { include: keepaliveInclude.value }, () =>\n          toggle.value ? h(AsyncComp, { ref: instanceRef }) : null,\n        )\n      },\n    }\n\n    render(h(App), root)\n    // async component has not been resolved\n    expect(serializeInner(root)).toBe('<!---->')\n\n    resolve!({\n      name: 'Foo',\n      data: () => ({ count: 0 }),\n      render() {\n        return h('p', this.count)\n      },\n    })\n\n    await timeout()\n    // resolved\n    expect(serializeInner(root)).toBe('<p>0</p>')\n\n    // change state + toggle out + update `include` props\n    instanceRef.value.count++\n    toggle.value = false\n    keepaliveInclude.value = ['Foo']\n    await nextTick()\n    expect(serializeInner(root)).toBe('<!---->')\n\n    // toggle in, state should be maintained\n    toggle.value = true\n    await nextTick()\n    expect(serializeInner(root)).toBe('<p>1</p>')\n  })\n})\n"
  },
  {
    "path": "packages/runtime-core/__tests__/components/Suspense.spec.ts",
    "content": "/**\n * @vitest-environment jsdom\n */\n\nimport {\n  type ComponentOptions,\n  Fragment,\n  KeepAlive,\n  Suspense,\n  type SuspenseProps,\n  createCommentVNode,\n  h,\n  nextTick,\n  nodeOps,\n  onErrorCaptured,\n  onMounted,\n  onUnmounted,\n  onUpdated,\n  ref,\n  render,\n  renderList,\n  renderSlot,\n  resolveDynamicComponent,\n  serializeInner,\n  shallowRef,\n  watch,\n  watchEffect,\n  withDirectives,\n} from '@vue/runtime-test'\nimport { computed, createApp, defineComponent, inject, provide } from 'vue'\nimport type { RawSlots } from 'packages/runtime-core/src/componentSlots'\nimport { resetSuspenseId } from '../../src/components/Suspense'\n\ndescribe('Suspense', () => {\n  const deps: Promise<any>[] = []\n\n  beforeEach(() => {\n    deps.length = 0\n    resetSuspenseId()\n  })\n\n  // a simple async factory for testing purposes only.\n  function defineAsyncComponent<T extends ComponentOptions>(\n    comp: T,\n    delay: number = 0,\n  ) {\n    return {\n      setup(props: any, { slots }: any) {\n        const p = new Promise(resolve => {\n          setTimeout(() => {\n            resolve(() => h(comp, props, slots))\n          }, delay)\n        })\n        // in Node 12, due to timer/nextTick mechanism change, we have to wait\n        // an extra tick to avoid race conditions\n        deps.push(p.then(() => Promise.resolve()))\n        return p\n      },\n    }\n  }\n\n  const RouterView = {\n    setup(_: any, { slots }: any) {\n      const route = inject('route') as any\n      const depth = inject('depth', 0)\n      provide('depth', depth + 1)\n      return () => {\n        const current = route.value[depth]\n        return slots.default({ Component: current })[0]\n      }\n    },\n  }\n\n  test('fallback content', async () => {\n    const Async = defineAsyncComponent({\n      render() {\n        return h('div', 'async')\n      },\n    })\n\n    const Comp = {\n      setup() {\n        return () =>\n          h(Suspense, null, {\n            default: h(Async),\n            fallback: h('div', 'fallback'),\n          })\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(Comp), root)\n    expect(serializeInner(root)).toBe(`<div>fallback</div>`)\n\n    await Promise.all(deps)\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<div>async</div>`)\n  })\n\n  test('emits events', async () => {\n    const Async = defineAsyncComponent({\n      render() {\n        return h('div', 'async')\n      },\n    })\n\n    const onFallback = vi.fn()\n    const onResolve = vi.fn()\n    const onPending = vi.fn()\n\n    const show = ref(true)\n    const Comp = {\n      setup() {\n        return () =>\n          h(\n            Suspense,\n            {\n              onFallback,\n              onResolve,\n              onPending,\n              // force displaying the fallback right away\n              timeout: 0,\n            },\n            {\n              default: () => (show.value ? h(Async) : null),\n              fallback: h('div', 'fallback'),\n            },\n          )\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(Comp), root)\n    expect(onFallback).toHaveBeenCalledTimes(1)\n    expect(onPending).toHaveBeenCalledTimes(1)\n    expect(onResolve).toHaveBeenCalledTimes(0)\n\n    await Promise.all(deps)\n    await nextTick()\n    expect(onFallback).toHaveBeenCalledTimes(1)\n    expect(onPending).toHaveBeenCalledTimes(1)\n    expect(onResolve).toHaveBeenCalledTimes(1)\n\n    show.value = false\n    await nextTick()\n    expect(onFallback).toHaveBeenCalledTimes(1)\n    expect(onPending).toHaveBeenCalledTimes(2)\n    expect(onResolve).toHaveBeenCalledTimes(2)\n\n    deps.length = 0\n    show.value = true\n    await nextTick()\n    expect(onFallback).toHaveBeenCalledTimes(2)\n    expect(onPending).toHaveBeenCalledTimes(3)\n    expect(onResolve).toHaveBeenCalledTimes(2)\n\n    await Promise.all(deps)\n    await nextTick()\n    expect(onFallback).toHaveBeenCalledTimes(2)\n    expect(onPending).toHaveBeenCalledTimes(3)\n    expect(onResolve).toHaveBeenCalledTimes(3)\n  })\n\n  test('nested async deps', async () => {\n    const calls: string[] = []\n\n    const AsyncOuter = defineAsyncComponent({\n      setup() {\n        onMounted(() => {\n          calls.push('outer mounted')\n        })\n        return () => h(AsyncInner)\n      },\n    })\n\n    const AsyncInner = defineAsyncComponent(\n      {\n        setup() {\n          onMounted(() => {\n            calls.push('inner mounted')\n          })\n          return () => h('div', 'inner')\n        },\n      },\n      10,\n    )\n\n    const Comp = {\n      setup() {\n        return () =>\n          h(Suspense, null, {\n            default: h(AsyncOuter),\n            fallback: h('div', 'fallback'),\n          })\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(Comp), root)\n    expect(serializeInner(root)).toBe(`<div>fallback</div>`)\n    expect(calls).toEqual([])\n\n    await deps[0]\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<div>fallback</div>`)\n    expect(calls).toEqual([])\n\n    await Promise.all(deps)\n    await nextTick()\n    expect(calls).toEqual([`outer mounted`, `inner mounted`])\n    expect(serializeInner(root)).toBe(`<div>inner</div>`)\n  })\n\n  test('onResolve', async () => {\n    const Async = defineAsyncComponent({\n      render() {\n        return h('div', 'async')\n      },\n    })\n\n    const onResolve = vi.fn()\n\n    const Comp = {\n      setup() {\n        return () =>\n          h(\n            Suspense,\n            {\n              onResolve,\n            },\n            {\n              default: h(Async),\n              fallback: h('div', 'fallback'),\n            },\n          )\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(Comp), root)\n    expect(serializeInner(root)).toBe(`<div>fallback</div>`)\n    expect(onResolve).not.toHaveBeenCalled()\n\n    await Promise.all(deps)\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<div>async</div>`)\n    expect(onResolve).toHaveBeenCalled()\n  })\n\n  test('buffer mounted/updated hooks & post flush watch callbacks', async () => {\n    const deps: Promise<any>[] = []\n    const calls: string[] = []\n    const toggle = ref(true)\n\n    const Async = {\n      async setup() {\n        const p = new Promise(r => setTimeout(r, 1))\n        // extra tick needed for Node 12+\n        deps.push(p.then(() => Promise.resolve()))\n\n        watchEffect(\n          () => {\n            calls.push('watch effect')\n          },\n          { flush: 'post' },\n        )\n\n        const count = ref(0)\n        watch(\n          count,\n          () => {\n            calls.push('watch callback')\n          },\n          { flush: 'post' },\n        )\n        count.value++ // trigger the watcher now\n\n        onMounted(() => {\n          calls.push('mounted')\n        })\n\n        onUnmounted(() => {\n          calls.push('unmounted')\n        })\n\n        await p\n        return () => h('div', 'async')\n      },\n    }\n\n    const Comp = {\n      setup() {\n        return () =>\n          h(Suspense, null, {\n            default: toggle.value ? h(Async) : null,\n            fallback: h('div', 'fallback'),\n          })\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(Comp), root)\n    expect(serializeInner(root)).toBe(`<div>fallback</div>`)\n    expect(calls).toEqual([])\n\n    await Promise.all(deps)\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<div>async</div>`)\n    expect(calls).toEqual([`watch effect`, `watch callback`, `mounted`])\n\n    // effects inside an already resolved suspense should happen at normal timing\n    toggle.value = false\n    await nextTick()\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<!---->`)\n    expect(calls).toEqual([\n      `watch effect`,\n      `watch callback`,\n      `mounted`,\n      'unmounted',\n    ])\n  })\n\n  // #1059\n  test('mounted/updated hooks & fallback component', async () => {\n    const deps: Promise<any>[] = []\n    const calls: string[] = []\n    const toggle = ref(true)\n\n    const Async = {\n      async setup() {\n        const p = new Promise(r => setTimeout(r, 1))\n        // extra tick needed for Node 12+\n        deps.push(p.then(() => Promise.resolve()))\n\n        await p\n        return () => h('div', 'async')\n      },\n    }\n\n    const Fallback = {\n      setup() {\n        onMounted(() => {\n          calls.push('mounted')\n        })\n\n        onUnmounted(() => {\n          calls.push('unmounted')\n        })\n        return () => h('div', 'fallback')\n      },\n    }\n\n    const Comp = {\n      setup() {\n        return () =>\n          h(Suspense, null, {\n            default: toggle.value ? h(Async) : null,\n            fallback: h(Fallback),\n          })\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(Comp), root)\n    expect(serializeInner(root)).toBe(`<div>fallback</div>`)\n    expect(calls).toEqual([`mounted`])\n\n    await Promise.all(deps)\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<div>async</div>`)\n    expect(calls).toEqual([`mounted`, `unmounted`])\n  })\n\n  test('content update before suspense resolve', async () => {\n    const Async = defineAsyncComponent({\n      props: { msg: String },\n      setup(props: any) {\n        return () => h('div', props.msg)\n      },\n    })\n\n    const msg = ref('foo')\n\n    const Comp = {\n      setup() {\n        return () =>\n          h(Suspense, null, {\n            default: h(Async, { msg: msg.value }),\n            fallback: h('div', `fallback ${msg.value}`),\n          })\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(Comp), root)\n    expect(serializeInner(root)).toBe(`<div>fallback foo</div>`)\n\n    // value changed before resolve\n    msg.value = 'bar'\n    await nextTick()\n    // fallback content should be updated\n    expect(serializeInner(root)).toBe(`<div>fallback bar</div>`)\n\n    await Promise.all(deps)\n    await nextTick()\n    // async component should receive updated props/slots when resolved\n    expect(serializeInner(root)).toBe(`<div>bar</div>`)\n  })\n\n  // mount/unmount hooks should not even fire\n  test('unmount before suspense resolve', async () => {\n    const deps: Promise<any>[] = []\n    const calls: string[] = []\n    const toggle = ref(true)\n\n    const Async = {\n      async setup() {\n        const p = new Promise(r => setTimeout(r, 1))\n        deps.push(p)\n\n        watchEffect(\n          () => {\n            calls.push('watch effect')\n          },\n          { flush: 'post' },\n        )\n\n        const count = ref(0)\n        watch(\n          count,\n          () => {\n            calls.push('watch callback')\n          },\n          { flush: 'post' },\n        )\n        count.value++ // trigger the watcher now\n\n        onMounted(() => {\n          calls.push('mounted')\n        })\n\n        onUnmounted(() => {\n          calls.push('unmounted')\n        })\n\n        await p\n        return () => h('div', 'async')\n      },\n    }\n\n    const Comp = {\n      setup() {\n        return () =>\n          h(Suspense, null, {\n            default: toggle.value ? h(Async) : null,\n            fallback: h('div', 'fallback'),\n          })\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(Comp), root)\n    expect(serializeInner(root)).toBe(`<div>fallback</div>`)\n    expect(calls).toEqual([])\n\n    // remove the async dep before it's resolved\n    toggle.value = false\n    await nextTick()\n    // should cause the suspense to resolve immediately\n    expect(serializeInner(root)).toBe(`<!---->`)\n\n    await Promise.all(deps)\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<!---->`)\n    // should discard effects\n    expect(calls).toEqual([])\n  })\n\n  test('unmount suspense after resolve', async () => {\n    const toggle = ref(true)\n    const unmounted = vi.fn()\n\n    const Async = defineAsyncComponent({\n      setup() {\n        onUnmounted(unmounted)\n        return () => h('div', 'async')\n      },\n    })\n\n    const Comp = {\n      setup() {\n        return () =>\n          toggle.value\n            ? h(Suspense, null, {\n                default: h(Async),\n                fallback: h('div', 'fallback'),\n              })\n            : null\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(Comp), root)\n    expect(serializeInner(root)).toBe(`<div>fallback</div>`)\n\n    await Promise.all(deps)\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<div>async</div>`)\n    expect(unmounted).not.toHaveBeenCalled()\n\n    toggle.value = false\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<!---->`)\n    expect(unmounted).toHaveBeenCalled()\n  })\n\n  test('unmount suspense before resolve', async () => {\n    const toggle = ref(true)\n    const mounted = vi.fn()\n    const unmounted = vi.fn()\n\n    const Async = defineAsyncComponent({\n      setup() {\n        onMounted(mounted)\n        onUnmounted(unmounted)\n        return () => h('div', 'async')\n      },\n    })\n\n    const Comp = {\n      setup() {\n        return () =>\n          toggle.value\n            ? h(Suspense, null, {\n                default: h(Async),\n                fallback: h('div', 'fallback'),\n              })\n            : null\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(Comp), root)\n    expect(serializeInner(root)).toBe(`<div>fallback</div>`)\n\n    toggle.value = false\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<!---->`)\n    expect(mounted).not.toHaveBeenCalled()\n    expect(unmounted).not.toHaveBeenCalled()\n\n    await Promise.all(deps)\n    await nextTick()\n    // should not resolve and cause unmount\n    expect(mounted).not.toHaveBeenCalled()\n    expect(unmounted).not.toHaveBeenCalled()\n  })\n\n  // vuetifyjs/vuetify#15207\n  test('update prop of async element before suspense resolve', async () => {\n    let resolve: () => void\n    const mounted = new Promise<void>(r => {\n      resolve = r\n    })\n    const Async = {\n      async setup() {\n        onMounted(() => {\n          resolve()\n        })\n        const p = new Promise(r => setTimeout(r, 1))\n        await p\n        return () => h('div', 'async')\n      },\n    }\n\n    const Comp: ComponentOptions<{ data: string }> = {\n      props: ['data'],\n      setup(props) {\n        return () => h(Async, { 'data-test': props.data })\n      },\n    }\n\n    const Root = {\n      setup() {\n        const data = ref('1')\n        onMounted(() => {\n          data.value = '2'\n        })\n        return () =>\n          h(Suspense, null, {\n            default: h(Comp, { data: data.value }),\n            fallback: h('div', 'fallback'),\n          })\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(Root), root)\n    expect(serializeInner(root)).toBe(`<div>fallback</div>`)\n    await mounted\n    expect(serializeInner(root)).toBe(`<div data-test=\"2\">async</div>`)\n  })\n\n  test('nested suspense (parent resolves first)', async () => {\n    const calls: string[] = []\n\n    const AsyncOuter = defineAsyncComponent(\n      {\n        setup: () => {\n          onMounted(() => {\n            calls.push('outer mounted')\n          })\n          return () => h('div', 'async outer')\n        },\n      },\n      1,\n    )\n\n    const AsyncInner = defineAsyncComponent(\n      {\n        setup: () => {\n          onMounted(() => {\n            calls.push('inner mounted')\n          })\n          return () => h('div', 'async inner')\n        },\n      },\n      10,\n    )\n\n    const Inner = {\n      setup() {\n        return () =>\n          h(Suspense, null, {\n            default: h(AsyncInner),\n            fallback: h('div', 'fallback inner'),\n          })\n      },\n    }\n\n    const Comp = {\n      setup() {\n        return () =>\n          h(Suspense, null, {\n            default: h('div', [h(AsyncOuter), h(Inner)]),\n            fallback: h('div', 'fallback outer'),\n          })\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(Comp), root)\n    expect(serializeInner(root)).toBe(`<div>fallback outer</div>`)\n\n    await deps[0]\n    await nextTick()\n    expect(serializeInner(root)).toBe(\n      `<div><div>async outer</div><div>fallback inner</div></div>`,\n    )\n    expect(calls).toEqual([`outer mounted`])\n\n    await Promise.all(deps)\n    await nextTick()\n    expect(serializeInner(root)).toBe(\n      `<div><div>async outer</div><div>async inner</div></div>`,\n    )\n    expect(calls).toEqual([`outer mounted`, `inner mounted`])\n  })\n\n  test('nested suspense (child resolves first)', async () => {\n    const calls: string[] = []\n\n    const AsyncOuter = defineAsyncComponent(\n      {\n        setup: () => {\n          onMounted(() => {\n            calls.push('outer mounted')\n          })\n          return () => h('div', 'async outer')\n        },\n      },\n      10,\n    )\n\n    const AsyncInner = defineAsyncComponent(\n      {\n        setup: () => {\n          onMounted(() => {\n            calls.push('inner mounted')\n          })\n          return () => h('div', 'async inner')\n        },\n      },\n      1,\n    )\n\n    const Inner = {\n      setup() {\n        return () =>\n          h(Suspense, null, {\n            default: h(AsyncInner),\n            fallback: h('div', 'fallback inner'),\n          })\n      },\n    }\n\n    const Comp = {\n      setup() {\n        return () =>\n          h(Suspense, null, {\n            default: h('div', [h(AsyncOuter), h(Inner)]),\n            fallback: h('div', 'fallback outer'),\n          })\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(Comp), root)\n    expect(serializeInner(root)).toBe(`<div>fallback outer</div>`)\n\n    await deps[1]\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<div>fallback outer</div>`)\n    expect(calls).toEqual([])\n\n    await Promise.all(deps)\n    await nextTick()\n    expect(serializeInner(root)).toBe(\n      `<div><div>async outer</div><div>async inner</div></div>`,\n    )\n    expect(calls).toEqual([`inner mounted`, `outer mounted`])\n  })\n\n  test('error handling', async () => {\n    const Async = {\n      async setup() {\n        throw new Error('oops')\n      },\n    }\n\n    const Comp = {\n      setup() {\n        const errorMessage = ref<string | null>(null)\n        onErrorCaptured(err => {\n          errorMessage.value =\n            err instanceof Error\n              ? err.message\n              : `A non-Error value thrown: ${err}`\n          return false\n        })\n\n        return () =>\n          errorMessage.value\n            ? h('div', errorMessage.value)\n            : h(Suspense, null, {\n                default: h(Async),\n                fallback: h('div', 'fallback'),\n              })\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(Comp), root)\n    expect(serializeInner(root)).toBe(`<div>fallback</div>`)\n\n    await Promise.all(deps)\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<div>oops</div>`)\n  })\n\n  // #3857\n  test('error handling w/ template optimization', async () => {\n    const Async = {\n      async setup() {\n        throw new Error('oops')\n      },\n    }\n\n    const Comp = {\n      template: `\n      <div v-if=\"errorMessage\">{{ errorMessage }}</div>\n      <Suspense v-else>\n        <div>\n          <Async />\n        </div>\n        <template #fallback>\n          <div>fallback</div>\n        </template>\n      </Suspense>\n      `,\n      components: { Async },\n      setup() {\n        const errorMessage = ref<string | null>(null)\n        onErrorCaptured(err => {\n          errorMessage.value =\n            err instanceof Error\n              ? err.message\n              : `A non-Error value thrown: ${err}`\n          return false\n        })\n        return { errorMessage }\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(Comp), root)\n    expect(serializeInner(root)).toBe(`<div>fallback</div>`)\n\n    await Promise.all(deps)\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<div>oops</div>`)\n  })\n\n  it('combined usage (nested async + nested suspense + multiple deps)', async () => {\n    const msg = ref('nested msg')\n    const calls: number[] = []\n\n    const AsyncChildWithSuspense = defineAsyncComponent({\n      props: { msg: String },\n      setup(props: any) {\n        onMounted(() => {\n          calls.push(0)\n        })\n        return () =>\n          h(Suspense, null, {\n            default: h(AsyncInsideNestedSuspense, { msg: props.msg }),\n            fallback: h('div', 'nested fallback'),\n          })\n      },\n    })\n\n    const AsyncInsideNestedSuspense = defineAsyncComponent(\n      {\n        props: { msg: String },\n        setup(props: any) {\n          onMounted(() => {\n            calls.push(2)\n          })\n          return () => h('div', props.msg)\n        },\n      },\n      20,\n    )\n\n    const AsyncChildParent = defineAsyncComponent({\n      props: { msg: String },\n      setup(props: any) {\n        onMounted(() => {\n          calls.push(1)\n        })\n        return () => h(NestedAsyncChild, { msg: props.msg })\n      },\n    })\n\n    const NestedAsyncChild = defineAsyncComponent(\n      {\n        props: { msg: String },\n        setup(props: any) {\n          onMounted(() => {\n            calls.push(3)\n          })\n          return () => h('div', props.msg)\n        },\n      },\n      10,\n    )\n\n    const MiddleComponent = {\n      setup() {\n        return () =>\n          h(AsyncChildWithSuspense, {\n            msg: msg.value,\n          })\n      },\n    }\n\n    const Comp = {\n      setup() {\n        return () =>\n          h(Suspense, null, {\n            default: h('div', [\n              h(MiddleComponent),\n              h(AsyncChildParent, {\n                msg: 'root async',\n              }),\n            ]),\n            fallback: h('div', 'root fallback'),\n          })\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(Comp), root)\n    expect(serializeInner(root)).toBe(`<div>root fallback</div>`)\n    expect(calls).toEqual([])\n\n    /**\n     * <Root>\n     *   <Suspense>\n     *     <MiddleComponent>\n     *       <AsyncChildWithSuspense> (0: resolves on macrotask)\n     *         <Suspense>\n     *           <AsyncInsideNestedSuspense> (2: resolves on macrotask + 20ms)\n     *     <AsyncChildParent> (1: resolves on macrotask)\n     *       <NestedAsyncChild> (3: resolves on macrotask + 10ms)\n     */\n\n    // both top level async deps resolved, but there is another nested dep\n    // so should still be in fallback state\n    await Promise.all([deps[0], deps[1]])\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<div>root fallback</div>`)\n    expect(calls).toEqual([])\n\n    // root suspense all deps resolved. should show root content now\n    // with nested suspense showing fallback content\n    await deps[3]\n    await nextTick()\n    expect(serializeInner(root)).toBe(\n      `<div><div>nested fallback</div><div>root async</div></div>`,\n    )\n    expect(calls).toEqual([0, 1, 3])\n\n    // change state for the nested component before it resolves\n    msg.value = 'nested changed'\n\n    // all deps resolved, nested suspense should resolve now\n    await Promise.all(deps)\n    await nextTick()\n    expect(serializeInner(root)).toBe(\n      `<div><div>nested changed</div><div>root async</div></div>`,\n    )\n    expect(calls).toEqual([0, 1, 3, 2])\n\n    // should update just fine after resolve\n    msg.value = 'nested changed again'\n    await nextTick()\n    expect(serializeInner(root)).toBe(\n      `<div><div>nested changed again</div><div>root async</div></div>`,\n    )\n  })\n\n  test('switching branches', async () => {\n    const calls: string[] = []\n    const toggle = ref(true)\n\n    const Foo = defineAsyncComponent({\n      setup() {\n        onMounted(() => {\n          calls.push('foo mounted')\n        })\n        onUnmounted(() => {\n          calls.push('foo unmounted')\n        })\n        return () => h('div', ['foo', h(FooNested)])\n      },\n    })\n\n    const FooNested = defineAsyncComponent(\n      {\n        setup() {\n          onMounted(() => {\n            calls.push('foo nested mounted')\n          })\n          onUnmounted(() => {\n            calls.push('foo nested unmounted')\n          })\n          return () => h('div', 'foo nested')\n        },\n      },\n      10,\n    )\n\n    const Bar = defineAsyncComponent(\n      {\n        setup() {\n          onMounted(() => {\n            calls.push('bar mounted')\n          })\n          onUnmounted(() => {\n            calls.push('bar unmounted')\n          })\n          return () => h('div', 'bar')\n        },\n      },\n      10,\n    )\n\n    const Comp = {\n      setup() {\n        return () =>\n          h(Suspense, null, {\n            default: toggle.value ? h(Foo) : h(Bar),\n            fallback: h('div', 'fallback'),\n          })\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(Comp), root)\n    expect(serializeInner(root)).toBe(`<div>fallback</div>`)\n    expect(calls).toEqual([])\n\n    await deps[0]\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<div>fallback</div>`)\n    expect(calls).toEqual([])\n\n    await Promise.all(deps)\n    await nextTick()\n    expect(calls).toEqual([`foo mounted`, `foo nested mounted`])\n    expect(serializeInner(root)).toBe(`<div>foo<div>foo nested</div></div>`)\n\n    // toggle\n    toggle.value = false\n    await nextTick()\n    expect(deps.length).toBe(3)\n    // should remain on current view\n    expect(calls).toEqual([`foo mounted`, `foo nested mounted`])\n    expect(serializeInner(root)).toBe(`<div>foo<div>foo nested</div></div>`)\n\n    await Promise.all(deps)\n    await nextTick()\n    const tempCalls = [\n      `foo mounted`,\n      `foo nested mounted`,\n      `bar mounted`,\n      `foo nested unmounted`,\n      `foo unmounted`,\n    ]\n    expect(calls).toEqual(tempCalls)\n    expect(serializeInner(root)).toBe(`<div>bar</div>`)\n\n    // toggle back\n    toggle.value = true\n    await nextTick()\n    // should remain\n    expect(calls).toEqual(tempCalls)\n    expect(serializeInner(root)).toBe(`<div>bar</div>`)\n\n    await deps[3]\n    await nextTick()\n    // still pending...\n    expect(calls).toEqual(tempCalls)\n    expect(serializeInner(root)).toBe(`<div>bar</div>`)\n\n    await Promise.all(deps)\n    await nextTick()\n    expect(calls).toEqual([\n      ...tempCalls,\n      `foo mounted`,\n      `foo nested mounted`,\n      `bar unmounted`,\n    ])\n    expect(serializeInner(root)).toBe(`<div>foo<div>foo nested</div></div>`)\n  })\n\n  // #10098\n  test('switching branches w/ nested suspense', async () => {\n    const OuterB = defineAsyncComponent({\n      setup: () => {\n        return () =>\n          h(RouterView, null, {\n            default: ({ Component }: any) => [\n              h(Suspense, null, {\n                default: () => h(Component),\n              }),\n            ],\n          })\n      },\n    })\n\n    const InnerB = defineAsyncComponent({\n      setup: () => {\n        return () => h('div', 'innerB')\n      },\n    })\n\n    const OuterA = defineAsyncComponent({\n      setup: () => {\n        return () =>\n          h(RouterView, null, {\n            default: ({ Component }: any) => [\n              h(Suspense, null, {\n                default: () => h(Component),\n              }),\n            ],\n          })\n      },\n    })\n\n    const InnerA = defineAsyncComponent({\n      setup: () => {\n        return () => h('div', 'innerA')\n      },\n    })\n\n    const toggle = ref(true)\n    const route = computed(() => {\n      return toggle.value ? [OuterA, InnerA] : [OuterB, InnerB]\n    })\n\n    const Comp = {\n      setup() {\n        provide('route', route)\n        return () =>\n          h(RouterView, null, {\n            default: ({ Component }: any) => [\n              h(Suspense, null, {\n                default: () => h(Component),\n              }),\n            ],\n          })\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(Comp), root)\n    await Promise.all(deps)\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<!---->`)\n\n    await Promise.all(deps)\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<div>innerA</div>`)\n\n    deps.length = 0\n\n    toggle.value = false\n    await nextTick()\n    // toggle again\n    toggle.value = true\n\n    await Promise.all(deps)\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<div>innerA</div>`)\n  })\n\n  // #10415\n  test('nested suspense (w/ suspensible) switch several times before parent suspense resolve', async () => {\n    const OuterA = defineAsyncComponent({\n      setup: () => {\n        return () =>\n          h(RouterView, null, {\n            default: ({ Component }: any) => [\n              h(Suspense, null, {\n                default: () => h(Component),\n              }),\n            ],\n          })\n      },\n    })\n\n    const InnerA = defineAsyncComponent({\n      setup: () => {\n        return () => h('div', 'innerA')\n      },\n    })\n\n    const route = shallowRef([OuterA, InnerA])\n    const InnerB = defineAsyncComponent(\n      {\n        setup: () => {\n          return () => h('div', 'innerB')\n        },\n      },\n      5,\n    )\n\n    const InnerB1 = defineAsyncComponent(\n      {\n        setup: () => {\n          return () => h('div', 'innerB1')\n        },\n      },\n      5,\n    )\n\n    const InnerB2 = defineAsyncComponent(\n      {\n        setup: () => {\n          return () => h('div', 'innerB2')\n        },\n      },\n      5,\n    )\n\n    const OuterB = defineAsyncComponent(\n      {\n        setup() {\n          nextTick(async () => {\n            await new Promise(resolve => setTimeout(resolve, 1))\n            route.value = [OuterB, InnerB1]\n          })\n\n          nextTick(async () => {\n            await new Promise(resolve => setTimeout(resolve, 1))\n            route.value = [OuterB, InnerB2]\n          })\n\n          return () =>\n            h(RouterView, null, {\n              default: ({ Component }: any) => [\n                h(\n                  Suspense,\n                  { suspensible: true },\n                  {\n                    default: () => h(Component),\n                  },\n                ),\n              ],\n            })\n        },\n      },\n      5,\n    )\n\n    const Comp = {\n      setup() {\n        provide('route', route)\n        return () =>\n          h(RouterView, null, {\n            default: ({ Component }: any) => [\n              h(Suspense, null, {\n                default: () => h(Component),\n              }),\n            ],\n          })\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(Comp), root)\n    await Promise.all(deps)\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<!---->`)\n\n    await Promise.all(deps)\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<div>innerA</div>`)\n\n    deps.length = 0\n\n    route.value = [OuterB, InnerB]\n    await nextTick()\n\n    await Promise.all(deps)\n    await Promise.all(deps)\n    await Promise.all(deps)\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<div>innerB2</div>`)\n  })\n\n  test('branch switch to 3rd branch before resolve', async () => {\n    const calls: string[] = []\n\n    const makeComp = (name: string, delay = 0) =>\n      defineAsyncComponent(\n        {\n          setup() {\n            onMounted(() => {\n              calls.push(`${name} mounted`)\n            })\n            onUnmounted(() => {\n              calls.push(`${name} unmounted`)\n            })\n            return () => h('div', [name])\n          },\n        },\n        delay,\n      )\n\n    const One = makeComp('one')\n    const Two = makeComp('two', 10)\n    const Three = makeComp('three', 20)\n\n    const view = shallowRef(One)\n\n    const Comp = {\n      setup() {\n        return () =>\n          h(Suspense, null, {\n            default: h(view.value),\n            fallback: h('div', 'fallback'),\n          })\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(Comp), root)\n    expect(serializeInner(root)).toBe(`<div>fallback</div>`)\n    expect(calls).toEqual([])\n\n    await deps[0]\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<div>one</div>`)\n    expect(calls).toEqual([`one mounted`])\n\n    view.value = Two\n    await nextTick()\n    expect(deps.length).toBe(2)\n\n    // switch before two resolves\n    view.value = Three\n    await nextTick()\n    expect(deps.length).toBe(3)\n\n    // dep for two resolves\n    await deps[1]\n    await nextTick()\n    // should still be on view one\n    expect(serializeInner(root)).toBe(`<div>one</div>`)\n    expect(calls).toEqual([`one mounted`])\n\n    await deps[2]\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<div>three</div>`)\n    expect(calls).toEqual([`one mounted`, `three mounted`, `one unmounted`])\n  })\n\n  test('branch switch back before resolve', async () => {\n    const calls: string[] = []\n\n    const makeComp = (name: string, delay = 0) =>\n      defineAsyncComponent(\n        {\n          setup() {\n            onMounted(() => {\n              calls.push(`${name} mounted`)\n            })\n            onUnmounted(() => {\n              calls.push(`${name} unmounted`)\n            })\n            return () => h('div', [name])\n          },\n        },\n        delay,\n      )\n\n    const One = makeComp('one')\n    const Two = makeComp('two', 10)\n\n    const view = shallowRef(One)\n\n    const Comp = {\n      setup() {\n        return () =>\n          h(Suspense, null, {\n            default: h(view.value),\n            fallback: h('div', 'fallback'),\n          })\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(Comp), root)\n    expect(serializeInner(root)).toBe(`<div>fallback</div>`)\n    expect(calls).toEqual([])\n\n    await deps[0]\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<div>one</div>`)\n    expect(calls).toEqual([`one mounted`])\n\n    view.value = Two\n    await nextTick()\n    expect(deps.length).toBe(2)\n\n    // switch back before two resolves\n    view.value = One\n    await nextTick()\n    expect(deps.length).toBe(2)\n\n    // dep for two resolves\n    await deps[1]\n    await nextTick()\n    // should still be on view one\n    expect(serializeInner(root)).toBe(`<div>one</div>`)\n    expect(calls).toEqual([`one mounted`])\n  })\n\n  test('branch switch timeout + fallback', async () => {\n    const calls: string[] = []\n\n    const makeComp = (name: string, delay = 0) =>\n      defineAsyncComponent(\n        {\n          setup() {\n            onMounted(() => {\n              calls.push(`${name} mounted`)\n            })\n            onUnmounted(() => {\n              calls.push(`${name} unmounted`)\n            })\n            return () => h('div', [name])\n          },\n        },\n        delay,\n      )\n\n    const One = makeComp('one')\n    const Two = makeComp('two', 20)\n\n    const view = shallowRef(One)\n\n    const Comp = {\n      setup() {\n        return () =>\n          h(\n            Suspense,\n            {\n              timeout: 10,\n            },\n            {\n              default: h(view.value),\n              fallback: h('div', 'fallback'),\n            },\n          )\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(Comp), root)\n    expect(serializeInner(root)).toBe(`<div>fallback</div>`)\n    expect(calls).toEqual([])\n\n    await deps[0]\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<div>one</div>`)\n    expect(calls).toEqual([`one mounted`])\n\n    view.value = Two\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<div>one</div>`)\n    expect(calls).toEqual([`one mounted`])\n\n    await new Promise(r => setTimeout(r, 10))\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<div>fallback</div>`)\n    expect(calls).toEqual([`one mounted`, `one unmounted`])\n\n    await deps[1]\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<div>two</div>`)\n    expect(calls).toEqual([`one mounted`, `one unmounted`, `two mounted`])\n  })\n\n  test('mount the fallback content is in the correct position', async () => {\n    const makeComp = (name: string, delay = 0) =>\n      defineAsyncComponent(\n        {\n          setup() {\n            return () => h('div', [name])\n          },\n        },\n        delay,\n      )\n\n    const One = makeComp('one')\n    const Two = makeComp('two', 20)\n\n    const view = shallowRef(One)\n\n    const Comp = {\n      setup() {\n        return () =>\n          h('div', [\n            h(\n              Suspense,\n              {\n                timeout: 10,\n              },\n              {\n                default: h(view.value),\n                fallback: h('div', 'fallback'),\n              },\n            ),\n            h('div', 'three'),\n          ])\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(Comp), root)\n    expect(serializeInner(root)).toBe(\n      `<div><div>fallback</div><div>three</div></div>`,\n    )\n\n    await deps[0]\n    await nextTick()\n    expect(serializeInner(root)).toBe(\n      `<div><div>one</div><div>three</div></div>`,\n    )\n\n    view.value = Two\n    await nextTick()\n    expect(serializeInner(root)).toBe(\n      `<div><div>one</div><div>three</div></div>`,\n    )\n\n    await new Promise(r => setTimeout(r, 10))\n    await nextTick()\n    expect(serializeInner(root)).toBe(\n      `<div><div>fallback</div><div>three</div></div>`,\n    )\n\n    await deps[1]\n    await nextTick()\n    expect(serializeInner(root)).toBe(\n      `<div><div>two</div><div>three</div></div>`,\n    )\n  })\n\n  // #2214\n  // Since suspense renders its own root like a component, it should not patch\n  // its content in optimized mode.\n  test('should not miss nested element updates when used in templates', async () => {\n    const n = ref(1)\n    const Comp = {\n      setup() {\n        return { n }\n      },\n      template: `\n      <Suspense>\n        <div><span>{{ n }}</span></div>\n      </Suspense>\n      `,\n    }\n    const root = document.createElement('div')\n    createApp(Comp).mount(root)\n    expect(root.innerHTML).toBe(`<div><span>1</span></div>`)\n\n    n.value++\n    await nextTick()\n    expect(root.innerHTML).toBe(`<div><span>2</span></div>`)\n  })\n\n  // #2215\n  test('toggling nested async setup component inside already resolved suspense', async () => {\n    const toggle = ref(false)\n    const Child = {\n      async setup() {\n        return () => h('div', 'child')\n      },\n    }\n    const Parent = () => h('div', ['parent', toggle.value ? h(Child) : null])\n    const Comp = {\n      setup() {\n        return () => h(Suspense, () => h(Parent))\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(Comp), root)\n    expect(serializeInner(root)).toBe(`<div>parent<!----></div>`)\n\n    toggle.value = true\n    // wait for flush\n    await nextTick()\n    // wait for child async setup resolve\n    await nextTick()\n    // child should be rendered now instead of stuck in limbo\n    expect(serializeInner(root)).toBe(`<div>parent<div>child</div></div>`)\n\n    toggle.value = false\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<div>parent<!----></div>`)\n  })\n\n  test('warn if using async setup when not in a Suspense boundary', () => {\n    const Child = {\n      name: 'Child',\n      async setup() {\n        return () => h('div', 'child')\n      },\n    }\n    const Parent = {\n      setup() {\n        return () => h('div', [h(Child)])\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(Parent), root)\n\n    expect(\n      `A component with async setup() must be nested in a <Suspense>`,\n    ).toHaveBeenWarned()\n  })\n\n  test('nested suspense with suspensible', async () => {\n    const calls: string[] = []\n    let expected = ''\n\n    const InnerA = defineAsyncComponent(\n      {\n        setup: () => {\n          calls.push('innerA created')\n          onMounted(() => {\n            calls.push('innerA mounted')\n          })\n          return () => h('div', 'innerA')\n        },\n      },\n      10,\n    )\n\n    const InnerB = defineAsyncComponent(\n      {\n        setup: () => {\n          calls.push('innerB created')\n          onMounted(() => {\n            calls.push('innerB mounted')\n          })\n          return () => h('div', 'innerB')\n        },\n      },\n      10,\n    )\n\n    const OuterA = defineAsyncComponent(\n      {\n        setup: (_, { slots }: any) => {\n          calls.push('outerA created')\n          onMounted(() => {\n            calls.push('outerA mounted')\n          })\n          return () =>\n            h(Fragment, null, [h('div', 'outerA'), slots.default?.()])\n        },\n      },\n      5,\n    )\n\n    const OuterB = defineAsyncComponent(\n      {\n        setup: (_, { slots }: any) => {\n          calls.push('outerB created')\n          onMounted(() => {\n            calls.push('outerB mounted')\n          })\n          return () =>\n            h(Fragment, null, [h('div', 'outerB'), slots.default?.()])\n        },\n      },\n      5,\n    )\n\n    const outerToggle = ref(false)\n    const innerToggle = ref(false)\n\n    /**\n     *  <Suspense>\n     *    <component :is=\"outerToggle ? outerB : outerA\">\n     *      <Suspense suspensible>\n     *        <component :is=\"innerToggle ? innerB : innerA\" />\n     *      </Suspense>\n     *    </component>\n     *  </Suspense>\n     */\n    const Comp = {\n      setup() {\n        return () =>\n          h(Suspense, null, {\n            default: [\n              h(outerToggle.value ? OuterB : OuterA, null, {\n                default: () =>\n                  h(\n                    Suspense,\n                    { suspensible: true },\n                    {\n                      default: h(innerToggle.value ? InnerB : InnerA),\n                    },\n                  ),\n              }),\n            ],\n            fallback: h('div', 'fallback outer'),\n          })\n      },\n    }\n\n    expected = `<div>fallback outer</div>`\n    const root = nodeOps.createElement('div')\n    render(h(Comp), root)\n    expect(serializeInner(root)).toBe(expected)\n\n    // mount outer component\n    await Promise.all(deps)\n    await nextTick()\n\n    expect(serializeInner(root)).toBe(expected)\n    expect(calls).toEqual([`outerA created`])\n\n    // mount inner component\n    await Promise.all(deps)\n    await nextTick()\n    expected = `<div>outerA</div><div>innerA</div>`\n    expect(serializeInner(root)).toBe(expected)\n\n    expect(calls).toEqual([\n      'outerA created',\n      'innerA created',\n      'outerA mounted',\n      'innerA mounted',\n    ])\n\n    // toggle outer component\n    calls.length = 0\n    deps.length = 0\n    outerToggle.value = true\n    await nextTick()\n\n    await Promise.all(deps)\n    await nextTick()\n    expect(serializeInner(root)).toBe(expected) // expect not change\n\n    await Promise.all(deps)\n    await nextTick()\n    expected = `<div>outerB</div><div>innerA</div>`\n    expect(serializeInner(root)).toBe(expected)\n    expect(calls).toContain('outerB mounted')\n    expect(calls).toContain('innerA mounted')\n\n    // toggle inner component\n    calls.length = 0\n    deps.length = 0\n    innerToggle.value = true\n    await nextTick()\n    expect(serializeInner(root)).toBe(expected) // expect not change\n\n    await Promise.all(deps)\n    await nextTick()\n    expected = `<div>outerB</div><div>innerB</div>`\n    expect(serializeInner(root)).toBe(expected)\n    expect(calls).toContain('innerB mounted')\n  })\n\n  // #8206\n  test('nested suspense with suspensible & no async deps', async () => {\n    const calls: string[] = []\n    let expected = ''\n\n    const InnerA = defineComponent({\n      setup: () => {\n        calls.push('innerA created')\n        onMounted(() => {\n          calls.push('innerA mounted')\n        })\n        return () => h('div', 'innerA')\n      },\n    })\n\n    const InnerB = defineComponent({\n      setup: () => {\n        calls.push('innerB created')\n        onMounted(() => {\n          calls.push('innerB mounted')\n        })\n        return () => h('div', 'innerB')\n      },\n    })\n\n    const OuterA = defineComponent({\n      setup: (_, { slots }: any) => {\n        calls.push('outerA created')\n        onMounted(() => {\n          calls.push('outerA mounted')\n        })\n        return () => h(Fragment, null, [h('div', 'outerA'), slots.default?.()])\n      },\n    })\n\n    const OuterB = defineComponent({\n      setup: (_, { slots }: any) => {\n        calls.push('outerB created')\n        onMounted(() => {\n          calls.push('outerB mounted')\n        })\n        return () => h(Fragment, null, [h('div', 'outerB'), slots.default?.()])\n      },\n    })\n\n    const outerToggle = ref(false)\n    const innerToggle = ref(false)\n\n    /**\n     *  <Suspense>\n     *    <component :is=\"outerToggle ? outerB : outerA\">\n     *      <Suspense suspensible>\n     *        <component :is=\"innerToggle ? innerB : innerA\" />\n     *      </Suspense>\n     *    </component>\n     *  </Suspense>\n     */\n    const Comp = defineComponent({\n      setup() {\n        return () =>\n          h(Suspense, null, {\n            default: [\n              h(outerToggle.value ? OuterB : OuterA, null, {\n                default: () =>\n                  h(\n                    Suspense,\n                    { suspensible: true },\n                    {\n                      default: h(innerToggle.value ? InnerB : InnerA),\n                    },\n                  ),\n              }),\n            ],\n            fallback: h('div', 'fallback outer'),\n          })\n      },\n    })\n\n    expected = `<div>outerA</div><div>innerA</div>`\n    const root = nodeOps.createElement('div')\n    render(h(Comp), root)\n    expect(serializeInner(root)).toBe(expected)\n\n    // mount outer component and inner component\n    await Promise.all(deps)\n    await nextTick()\n\n    expect(serializeInner(root)).toBe(expected)\n    expect(calls).toEqual([\n      'outerA created',\n      'innerA created',\n      'innerA mounted',\n      'outerA mounted',\n    ])\n\n    // toggle outer component\n    calls.length = 0\n    deps.length = 0\n    outerToggle.value = true\n    await nextTick()\n\n    await Promise.all(deps)\n    await nextTick()\n    expected = `<div>outerB</div><div>innerA</div>`\n    expect(serializeInner(root)).toBe(expected)\n    expect(calls).toContain('outerB mounted')\n    expect(calls).toContain('innerA mounted')\n\n    // toggle inner component\n    calls.length = 0\n    deps.length = 0\n    innerToggle.value = true\n    await Promise.all(deps)\n    await nextTick()\n    expected = `<div>outerB</div><div>innerB</div>`\n    expect(serializeInner(root)).toBe(expected)\n  })\n\n  //#8678\n  test('nested suspense (child suspense update before parent suspense resolve)', async () => {\n    const calls: string[] = []\n\n    const InnerA = defineAsyncComponent(\n      {\n        setup: () => {\n          calls.push('innerA created')\n          onMounted(() => {\n            calls.push('innerA mounted')\n          })\n          return () => h('div', 'innerA')\n        },\n      },\n      10,\n    )\n\n    const InnerB = defineAsyncComponent(\n      {\n        setup: () => {\n          calls.push('innerB created')\n          onMounted(() => {\n            calls.push('innerB mounted')\n          })\n          return () => h('div', 'innerB')\n        },\n      },\n      10,\n    )\n\n    const OuterA = defineAsyncComponent(\n      {\n        setup: (_, { slots }: any) => {\n          calls.push('outerA created')\n          onMounted(() => {\n            calls.push('outerA mounted')\n          })\n          return () =>\n            h(Fragment, null, [h('div', 'outerA'), slots.default?.()])\n        },\n      },\n      5,\n    )\n\n    const OuterB = defineAsyncComponent(\n      {\n        setup: (_, { slots }: any) => {\n          calls.push('outerB created')\n          onMounted(() => {\n            calls.push('outerB mounted')\n          })\n          return () =>\n            h(Fragment, null, [h('div', 'outerB'), slots.default?.()])\n        },\n      },\n      5,\n    )\n\n    const outerToggle = ref(false)\n    const innerToggle = ref(false)\n\n    /**\n     *  <Suspense>\n     *    <component :is=\"outerToggle ? outerB : outerA\">\n     *      <Suspense>\n     *        <component :is=\"innerToggle ? innerB : innerA\" />\n     *      </Suspense>\n     *    </component>\n     *  </Suspense>\n     */\n    const Comp = {\n      setup() {\n        return () =>\n          h(Suspense, null, {\n            default: [\n              h(outerToggle.value ? OuterB : OuterA, null, {\n                default: () =>\n                  h(Suspense, null, {\n                    default: h(innerToggle.value ? InnerB : InnerA),\n                  }),\n              }),\n            ],\n            fallback: h('div', 'fallback outer'),\n          })\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(Comp), root)\n    expect(serializeInner(root)).toBe(`<div>fallback outer</div>`)\n\n    // mount outer component\n    await Promise.all(deps)\n    await nextTick()\n\n    expect(serializeInner(root)).toBe(`<div>outerA</div><!---->`)\n    expect(calls).toEqual([`outerA created`, `outerA mounted`])\n\n    // mount inner component\n    await Promise.all(deps)\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<div>outerA</div><div>innerA</div>`)\n\n    expect(calls).toEqual([\n      'outerA created',\n      'outerA mounted',\n      'innerA created',\n      'innerA mounted',\n    ])\n\n    calls.length = 0\n    deps.length = 0\n\n    // toggle both outer and inner components\n    outerToggle.value = true\n    innerToggle.value = true\n    await nextTick()\n\n    await Promise.all(deps)\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<div>outerB</div><!---->`)\n\n    await Promise.all(deps)\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<div>outerB</div><div>innerB</div>`)\n\n    // innerB only mount once\n    expect(calls).toEqual([\n      'outerB created',\n      'outerB mounted',\n      'innerB created',\n      'innerB mounted',\n    ])\n  })\n\n  // #6416\n  test('KeepAlive with Suspense', async () => {\n    const Async = defineAsyncComponent({\n      render() {\n        return h('div', 'async')\n      },\n    })\n    const Sync = {\n      render() {\n        return h('div', 'sync')\n      },\n    }\n    const components = [Async, Sync]\n    const viewRef = ref(0)\n    const root = nodeOps.createElement('div')\n    const App = {\n      render() {\n        return h(KeepAlive, null, {\n          default: () => {\n            return h(Suspense, null, {\n              default: h(components[viewRef.value]),\n              fallback: h('div', 'Loading-dynamic-components'),\n            })\n          },\n        })\n      },\n    }\n    render(h(App), root)\n    expect(serializeInner(root)).toBe(`<div>Loading-dynamic-components</div>`)\n\n    viewRef.value = 1\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<div>sync</div>`)\n\n    viewRef.value = 0\n    await nextTick()\n\n    expect(serializeInner(root)).toBe('<div>sync</div>')\n\n    await Promise.all(deps)\n    await nextTick()\n    // when async resolve,it should be <div>async</div>\n    expect(serializeInner(root)).toBe('<div>async</div>')\n\n    viewRef.value = 1\n    await nextTick()\n    // TypeError: Cannot read properties of null (reading 'parentNode')\n    // This has been fixed\n    expect(serializeInner(root)).toBe(`<div>sync</div>`)\n  })\n\n  // #10899 / #11427\n  test('KeepAlive + Suspense switch before branch resolves', async () => {\n    const Async1 = defineAsyncComponent({\n      render() {\n        return h('div', 'async1')\n      },\n    })\n    const Async2 = defineAsyncComponent({\n      render() {\n        return h('div', 'async2')\n      },\n    })\n    const components = [Async1, Async2]\n    const viewRef = ref(0)\n    const root = nodeOps.createElement('div')\n    const App = {\n      render() {\n        return h(\n          KeepAlive,\n          {\n            max: 1,\n          },\n          {\n            default: () => {\n              return h(Suspense, null, {\n                default: h(components[viewRef.value]),\n                fallback: h('div', 'loading'),\n              })\n            },\n          },\n        )\n      },\n    }\n    render(h(App), root)\n    expect(serializeInner(root)).toBe(`<div>loading</div>`)\n\n    // switch to Async2 before Async1 resolves\n    viewRef.value = 1\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<div>loading</div>`)\n\n    await Promise.all(deps)\n    await nextTick()\n    expect(serializeInner(root)).toBe('<div>async2</div>')\n\n    viewRef.value = 0\n    await nextTick()\n    await Promise.all(deps)\n    expect(serializeInner(root)).toBe(`<div>async1</div>`)\n\n    viewRef.value = 1\n    await nextTick()\n    await Promise.all(deps)\n    expect(serializeInner(root)).toBe(`<div>async2</div>`)\n  })\n\n  test('KeepAlive + Suspense + comment slot', async () => {\n    const toggle = ref(false)\n    const Async = defineAsyncComponent({\n      render() {\n        return h('div', 'async1')\n      },\n    })\n    const App = {\n      render() {\n        return h(KeepAlive, null, {\n          default: () => {\n            return h(Suspense, null, {\n              default: toggle.value ? h(Async) : createCommentVNode('v-if'),\n            })\n          },\n        })\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(App), root)\n    expect(serializeInner(root)).toBe(`<!--v-if-->`)\n\n    toggle.value = true\n    await nextTick()\n    await Promise.all(deps)\n    expect(serializeInner(root)).toBe(`<div>async1</div>`)\n  })\n\n  // #6416 follow up / #10017\n  test('Suspense patched during HOC async component re-mount', async () => {\n    const key = ref('k')\n    const data = ref('data')\n\n    const Async = defineAsyncComponent({\n      render() {\n        return h('div', 'async')\n      },\n    })\n\n    const Comp = {\n      render() {\n        return h(Async, { key: key.value })\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    const App = {\n      render() {\n        return h(Suspense, null, {\n          default: h(Comp, { k: key.value, data: data.value }),\n        })\n      },\n    }\n    render(h(App), root)\n    expect(serializeInner(root)).toBe(`<!---->`)\n\n    await Promise.all(deps)\n\n    // async mounted, but key change causing a new async comp to be loaded\n    key.value = 'k1'\n    await nextTick()\n\n    // patch the Suspense\n    // should not throw error due to Suspense vnode.el being null\n    data.value = 'data2'\n    await Promise.all(deps)\n  })\n\n  //#11617\n  test('update async component before resolve then update again', async () => {\n    const arr: boolean[] = []\n    const Child = {\n      props: ['loading'],\n      async setup(props: any) {\n        onUpdated(() => {\n          arr.push(props.loading)\n        })\n        await 1\n        return () => {\n          const loading = props.loading\n          return h('div', null, loading ? '1' : '2')\n        }\n      },\n    }\n\n    const Parent = defineComponent({\n      setup() {\n        const loading = ref(false)\n        const delay = (delayInms: any) => {\n          return new Promise(resolve => setTimeout(resolve, delayInms))\n        }\n        onMounted(async () => {\n          loading.value = true\n          await delay(1000)\n          loading.value = false\n          await nextTick()\n          expect(arr).toEqual([true, false])\n        })\n        return () => {\n          return h(Child, { loading: loading.value })\n        }\n      },\n    })\n\n    const RouterView = {\n      props: {\n        name: { type: Object },\n      },\n      setup(props: any) {\n        return () => {\n          const name = props.name\n          return h(name)\n        }\n      },\n    }\n    const App = {\n      setup() {\n        const Dummy = {\n          setup() {\n            return () => {\n              return h('div', null, 'dummy')\n            }\n          },\n        }\n\n        const flag: any = shallowRef(Dummy)\n\n        onMounted(() => {\n          flag.value = Parent\n        })\n        return () => {\n          return h(Suspense, null, {\n            default: () => h(RouterView, { name: flag.value }),\n          })\n        }\n      },\n    }\n\n    const root: any = nodeOps.createElement('div')\n\n    render(h(App), root)\n  })\n\n  // #13453\n  test('add new async deps during patching', async () => {\n    const getComponent = (type: string) => {\n      if (type === 'A') {\n        return defineAsyncComponent({\n          setup() {\n            return () => h('div', 'A')\n          },\n        })\n      }\n      return defineAsyncComponent({\n        setup() {\n          return () => h('div', 'B')\n        },\n      })\n    }\n\n    const types = ref(['A'])\n    const add = async () => {\n      types.value.push('B')\n    }\n\n    const update = async () => {\n      // mount Suspense B\n      // [Suspense A] -> [Suspense A(pending), Suspense B(pending)]\n      await add()\n      // patch Suspense B (still pending)\n      // [Suspense A(pending), Suspense B(pending)] -> [Suspense B(pending)]\n      types.value.shift()\n    }\n\n    const Comp = {\n      render(this: any) {\n        return h(Fragment, null, [\n          renderList(types.value, type => {\n            return h(\n              Suspense,\n              { key: type },\n              {\n                default: () => [\n                  renderSlot(this.$slots, 'default', { type: type }),\n                ],\n              },\n            )\n          }),\n        ])\n      },\n    }\n\n    const App = {\n      setup() {\n        return () =>\n          h(Comp, null, {\n            default: (params: any) => [h(getComponent(params.type))],\n          })\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(App), root)\n    expect(serializeInner(root)).toBe(`<!---->`)\n\n    await Promise.all(deps)\n    expect(serializeInner(root)).toBe(`<div>A</div>`)\n\n    update()\n    await nextTick()\n    // wait for both A and B to resolve\n    await Promise.all(deps)\n    // wait for new B to resolve\n    await Promise.all(deps)\n    expect(serializeInner(root)).toBe(`<div>B</div>`)\n  })\n\n  describe('warnings', () => {\n    // base function to check if a combination of slots warns or not\n    function baseCheckWarn(\n      shouldWarn: boolean,\n      children: RawSlots,\n      props: SuspenseProps | null = null,\n    ) {\n      const Comp = {\n        setup() {\n          return () => h(Suspense, props, children)\n        },\n      }\n\n      const root = nodeOps.createElement('div')\n      render(h(Comp), root)\n\n      if (shouldWarn) {\n        expect(`<Suspense> slots expect a single root node.`).toHaveBeenWarned()\n      } else {\n        expect(\n          `<Suspense> slots expect a single root node.`,\n        ).not.toHaveBeenWarned()\n      }\n    }\n\n    // actual function that we use in tests\n    const checkWarn = baseCheckWarn.bind(null, true)\n    const checkNoWarn = baseCheckWarn.bind(null, false)\n\n    test('does not warn on single child', async () => {\n      checkNoWarn({\n        default: h('div'),\n        fallback: h('div'),\n      })\n    })\n\n    test('does not warn on null', async () => {\n      checkNoWarn({\n        default: null,\n        fallback: null,\n      })\n    })\n\n    test('does not warn on <component :is=\"null\" />', async () => {\n      checkNoWarn({\n        default: () => [resolveDynamicComponent(null)],\n        fallback: () => null,\n      })\n    })\n\n    test('does not warn on empty array', async () => {\n      checkNoWarn({\n        default: [],\n        fallback: () => [],\n      })\n    })\n\n    test('warns on multiple children in default', async () => {\n      checkWarn({\n        default: [h('div'), h('div')],\n      })\n    })\n\n    test('warns on multiple children in fallback', async () => {\n      checkWarn({\n        default: h('div'),\n        fallback: [h('div'), h('div')],\n      })\n    })\n\n    // #13559\n    test('renders multiple async components in Suspense with v-for and updates on items change', async () => {\n      const CompAsyncSetup = defineAsyncComponent({\n        props: ['item'],\n        render(ctx: any) {\n          return h('div', ctx.item.name)\n        },\n      })\n\n      const items = ref([\n        { id: 1, name: '111' },\n        { id: 2, name: '222' },\n        { id: 3, name: '333' },\n      ])\n\n      const Comp = {\n        setup() {\n          return () =>\n            h(Suspense, null, {\n              default: () =>\n                h(\n                  Fragment,\n                  null,\n                  items.value.map(item =>\n                    h(CompAsyncSetup, { item, key: item.id }),\n                  ),\n                ),\n            })\n        },\n      }\n\n      const root = nodeOps.createElement('div')\n      render(h(Comp), root)\n      await nextTick()\n      await Promise.all(deps)\n\n      expect(serializeInner(root)).toBe(\n        `<div>111</div><div>222</div><div>333</div>`,\n      )\n\n      items.value = [\n        { id: 4, name: '444' },\n        { id: 5, name: '555' },\n        { id: 6, name: '666' },\n      ]\n      await nextTick()\n      await Promise.all(deps)\n      expect(serializeInner(root)).toBe(\n        `<div>444</div><div>555</div><div>666</div>`,\n      )\n    })\n\n    // #14173\n    test('nested async components with v-for + only Suspense and async component wrappers', async () => {\n      const CompAsyncSetup = defineAsyncComponent({\n        props: ['item', 'id'],\n        render(ctx: any) {\n          return h('div', ctx.id + '-' + ctx.item.name)\n        },\n      })\n      const items = ref([\n        { id: 1, name: 'a' },\n        { id: 2, name: 'b' },\n        { id: 3, name: 'c' },\n      ])\n      const Comp = {\n        props: ['id'],\n        setup(props: any) {\n          return () =>\n            h(Suspense, null, {\n              default: () =>\n                h(\n                  Fragment,\n                  null,\n                  items.value.map(item =>\n                    h(CompAsyncSetup, {\n                      item,\n                      key: item.id,\n                      id: props.id,\n                    }),\n                  ),\n                ),\n            })\n        },\n      }\n\n      const CompAsyncWrapper = defineAsyncComponent({\n        props: ['id'],\n        render(ctx: any) {\n          return h(Comp, { id: ctx.id })\n        },\n      })\n      const CompWrapper = defineComponent({\n        props: ['id'],\n        render(ctx: any) {\n          return h(CompAsyncWrapper, { id: ctx.id })\n        },\n      })\n      const list = ref([{ id: 1 }, { id: 2 }, { id: 3 }])\n\n      const App = {\n        setup() {\n          return () =>\n            h(Suspense, null, {\n              default: () =>\n                h(\n                  Fragment,\n                  null,\n                  list.value.map(item =>\n                    h(CompWrapper, { id: item.id, key: item.id }),\n                  ),\n                ),\n            })\n        },\n      }\n\n      const root = nodeOps.createElement('div')\n      render(h(App), root)\n      await nextTick()\n      await Promise.all(deps)\n      await Promise.all(deps)\n\n      expect(serializeInner(root)).toBe(\n        `<div>1-a</div><div>1-b</div><div>1-c</div><div>2-a</div><div>2-b</div><div>2-c</div><div>3-a</div><div>3-b</div><div>3-c</div>`,\n      )\n\n      list.value = [{ id: 4 }, { id: 5 }, { id: 6 }]\n      await nextTick()\n      await Promise.all(deps)\n      await Promise.all(deps)\n      expect(serializeInner(root)).toBe(\n        `<div>4-a</div><div>4-b</div><div>4-c</div><div>5-a</div><div>5-b</div><div>5-c</div><div>6-a</div><div>6-b</div><div>6-c</div>`,\n      )\n\n      items.value = [\n        { id: 4, name: 'd' },\n        { id: 5, name: 'f' },\n        { id: 6, name: 'g' },\n      ]\n      await nextTick()\n      await Promise.all(deps)\n      await Promise.all(deps)\n      expect(serializeInner(root)).toBe(\n        `<div>4-d</div><div>4-f</div><div>4-g</div><div>5-d</div><div>5-f</div><div>5-g</div><div>6-d</div><div>6-f</div><div>6-g</div>`,\n      )\n    })\n\n    test('should call unmounted directive once when fallback is replaced by resolved async component', async () => {\n      const Comp = {\n        render() {\n          return h('div', null, 'comp')\n        },\n      }\n      const Foo = defineAsyncComponent({\n        render() {\n          return h(Comp)\n        },\n      })\n      const unmounted = vi.fn(el => {\n        el.foo = null\n      })\n      const vDir = {\n        unmounted,\n      }\n      const App = {\n        setup() {\n          return () => {\n            return h(Suspense, null, {\n              fallback: () => withDirectives(h('div'), [[vDir, true]]),\n              default: () => h(Foo),\n            })\n          }\n        },\n      }\n      const root = nodeOps.createElement('div')\n      render(h(App), root)\n\n      await Promise.all(deps)\n      await nextTick()\n      expect(unmounted).toHaveBeenCalledTimes(1)\n    })\n  })\n})\n"
  },
  {
    "path": "packages/runtime-core/__tests__/components/Teleport.spec.ts",
    "content": "/**\n * @vitest-environment jsdom\n */\n\nimport {\n  Teleport,\n  Text,\n  createApp,\n  defineComponent,\n  markRaw,\n  nextTick,\n  nodeOps,\n  onMounted,\n  h as originalH,\n  ref,\n  render,\n  serialize,\n  serializeInner,\n  useModel,\n  withDirectives,\n} from '@vue/runtime-test'\nimport {\n  Fragment,\n  createBlock,\n  createCommentVNode,\n  createTextVNode,\n  createVNode,\n  openBlock,\n} from '../../src/vnode'\nimport { toDisplayString } from '@vue/shared'\nimport { compile, createApp as createDOMApp, render as domRender } from 'vue'\nimport type { HMRRuntime } from '../../src/hmr'\n\ndeclare var __VUE_HMR_RUNTIME__: HMRRuntime\nconst { rerender, createRecord } = __VUE_HMR_RUNTIME__\n\ndescribe('renderer: teleport', () => {\n  describe('eager mode', () => {\n    runSharedTests(false)\n  })\n\n  describe('defer mode', () => {\n    runSharedTests(true)\n\n    const h = originalH\n\n    test('should be able to target content appearing later than the teleport with defer', () => {\n      const root = document.createElement('div')\n      document.body.appendChild(root)\n\n      createDOMApp({\n        render() {\n          return [\n            h(Teleport, { to: '#target', defer: true }, h('div', 'teleported')),\n            h('div', { id: 'target' }),\n          ]\n        },\n      }).mount(root)\n\n      expect(root.innerHTML).toMatchInlineSnapshot(\n        `\"<!--teleport start--><!--teleport end--><div id=\"target\"><div>teleported</div></div>\"`,\n      )\n    })\n\n    test('defer mode should work inside suspense', async () => {\n      const root = document.createElement('div')\n      document.body.appendChild(root)\n\n      let p: Promise<any>\n\n      const Comp = defineComponent({\n        template: `\n        <suspense>\n          <div>\n            <async />\n            <teleport defer to=\"#target-suspense\">\n              <div>teleported</div>\n            </teleport>\n            <div id=\"target-suspense\" />\n          </div>\n        </suspense>`,\n        components: {\n          async: {\n            setup() {\n              p = Promise.resolve(() => 'async')\n              return p\n            },\n          },\n        },\n      })\n\n      domRender(h(Comp), root)\n      expect(root.innerHTML).toBe(`<!---->`)\n\n      await p!.then(() => Promise.resolve())\n      await nextTick()\n      expect(root.innerHTML).toBe(\n        `<div>` +\n          `async` +\n          `<!--teleport start--><!--teleport end-->` +\n          `<div id=\"target-suspense\"><div>teleported</div></div>` +\n          `</div>`,\n      )\n    })\n\n    test('update before mounted with defer', async () => {\n      const root = document.createElement('div')\n      document.body.appendChild(root)\n\n      const show = ref(false)\n      const foo = ref('foo')\n      const Header = {\n        props: { foo: String },\n        setup(props: any) {\n          return () => h('div', props.foo)\n        },\n      }\n      const Footer = {\n        setup() {\n          foo.value = 'bar'\n          return () => h('div', 'Footer')\n        },\n      }\n      createDOMApp({\n        render() {\n          return show.value\n            ? [\n                h(\n                  Teleport,\n                  { to: '#targetId', defer: true },\n                  h(Header, { foo: foo.value }),\n                ),\n                h(Footer),\n                h('div', { id: 'targetId' }),\n              ]\n            : [h('div')]\n        },\n      }).mount(root)\n\n      expect(root.innerHTML).toMatchInlineSnapshot(`\"<div></div>\"`)\n\n      show.value = true\n      await nextTick()\n      expect(root.innerHTML).toMatchInlineSnapshot(\n        `\"<!--teleport start--><!--teleport end--><div>Footer</div><div id=\"targetId\"><div>bar</div></div>\"`,\n      )\n    })\n\n    // #13349\n    test('handle deferred teleport updates before and after mount', async () => {\n      const root = document.createElement('div')\n      document.body.appendChild(root)\n\n      const show = ref(false)\n      const data2 = ref('2')\n      const data3 = ref('3')\n\n      const Comp = {\n        props: {\n          modelValue: {},\n          modelModifiers: {},\n        },\n        emits: ['update:modelValue'],\n        setup(props: any) {\n          const data2 = useModel(props, 'modelValue')\n          data2.value = '2+'\n          return () => h('span')\n        },\n      }\n\n      createDOMApp({\n        setup() {\n          setTimeout(() => (show.value = true), 5)\n          setTimeout(() => (data3.value = '3+'), 10)\n        },\n        render() {\n          return h(Fragment, null, [\n            h('span', { id: 'targetId001' }),\n            show.value\n              ? h(Fragment, null, [\n                  h(Teleport, { to: '#targetId001', defer: true }, [\n                    createTextVNode(String(data3.value)),\n                  ]),\n                  h(Comp, {\n                    modelValue: data2.value,\n                    'onUpdate:modelValue': (event: any) =>\n                      (data2.value = event),\n                  }),\n                ])\n              : createCommentVNode('v-if'),\n          ])\n        },\n      }).mount(root)\n\n      expect(root.innerHTML).toMatchInlineSnapshot(\n        `\"<span id=\"targetId001\"></span><!--v-if-->\"`,\n      )\n\n      await new Promise(r => setTimeout(r, 10))\n      expect(root.innerHTML).toMatchInlineSnapshot(\n        `\"<span id=\"targetId001\">3+</span><!--teleport start--><!--teleport end--><span></span>\"`,\n      )\n    })\n  })\n\n  function runSharedTests(deferMode: boolean) {\n    const h = (deferMode\n      ? (type: any, props: any, ...args: any[]) => {\n          if (type === Teleport) {\n            props.defer = true\n          }\n          return originalH(type, props, ...args)\n        }\n      : originalH) as unknown as typeof originalH\n\n    test('should work', () => {\n      const target = nodeOps.createElement('div')\n      const root = nodeOps.createElement('div')\n\n      render(\n        h(() => [\n          h(Teleport, { to: target }, h('div', 'teleported')),\n          h('div', 'root'),\n        ]),\n        root,\n      )\n\n      expect(serializeInner(root)).toBe(\n        `<!--teleport start--><!--teleport end--><div>root</div>`,\n      )\n      expect(serializeInner(target)).toBe(`<div>teleported</div>`)\n    })\n\n    test('should work with SVG', async () => {\n      const root = document.createElement('div')\n      const svg = ref()\n      const circle = ref()\n\n      const Comp = defineComponent({\n        setup() {\n          return {\n            svg,\n            circle,\n          }\n        },\n        template: `\n        <svg ref=\"svg\"></svg>\n        <teleport :to=\"svg\" v-if=\"svg\">\n        <circle ref=\"circle\"></circle>\n        </teleport>`,\n      })\n\n      domRender(h(Comp), root)\n\n      await nextTick()\n\n      expect(root.innerHTML).toBe(\n        `<svg><circle></circle></svg><!--teleport start--><!--teleport end-->`,\n      )\n\n      expect(svg.value.namespaceURI).toBe('http://www.w3.org/2000/svg')\n      expect(circle.value.namespaceURI).toBe('http://www.w3.org/2000/svg')\n    })\n\n    test('should update target', async () => {\n      const targetA = nodeOps.createElement('div')\n      const targetB = nodeOps.createElement('div')\n      const target = ref(targetA)\n      const root = nodeOps.createElement('div')\n\n      render(\n        h(() => [\n          h(Teleport, { to: target.value }, h('div', 'teleported')),\n          h('div', 'root'),\n        ]),\n        root,\n      )\n\n      expect(serializeInner(root)).toBe(\n        `<!--teleport start--><!--teleport end--><div>root</div>`,\n      )\n      expect(serializeInner(targetA)).toBe(`<div>teleported</div>`)\n      expect(serializeInner(targetB)).toBe(``)\n\n      target.value = targetB\n      await nextTick()\n\n      expect(serializeInner(root)).toBe(\n        `<!--teleport start--><!--teleport end--><div>root</div>`,\n      )\n      expect(serializeInner(targetA)).toBe(``)\n      expect(serializeInner(targetB)).toBe(`<div>teleported</div>`)\n    })\n\n    test('move cached text nodes', async () => {\n      document.body.innerHTML = ''\n      const root = document.createElement('div')\n      document.body.appendChild(root)\n\n      const to = ref('#teleport01')\n      const disabled = ref(true)\n\n      const App = defineComponent({\n        setup() {\n          return { to, disabled, deferMode }\n        },\n        template: `  \n          <div id=\"teleport01\">\n            <Teleport :to=\"to\" :defer=\"deferMode\" :disabled=\"disabled\">\n              static text\n            </Teleport>\n          </div>\n          <div id=\"teleport02\"></div>\n        `,\n      })\n\n      domRender(h(App), root)\n      await nextTick()\n\n      const target1 = root.querySelector('#teleport01') as HTMLElement\n      const target2 = root.querySelector('#teleport02') as HTMLElement\n      expect(target1.innerHTML).toBe(\n        '<!--teleport start--> static text <!--teleport end-->',\n      )\n      expect(target2.innerHTML).toBe('')\n\n      to.value = '#teleport02'\n      disabled.value = false\n\n      await nextTick()\n      expect(target1.innerHTML).toBe('<!--teleport start--><!--teleport end-->')\n      expect(target2.innerHTML).toContain('static text')\n\n      domRender(null, root)\n      root.remove()\n    })\n\n    test('should update children', async () => {\n      const target = nodeOps.createElement('div')\n      const root = nodeOps.createElement('div')\n      const children = ref([h('div', 'teleported')])\n\n      render(\n        h(() => h(Teleport, { to: target }, children.value)),\n        root,\n      )\n      expect(serializeInner(target)).toBe(`<div>teleported</div>`)\n\n      children.value = []\n      await nextTick()\n\n      expect(serializeInner(target)).toBe(``)\n\n      children.value = [createVNode(Text, null, 'teleported')]\n      await nextTick()\n\n      expect(serializeInner(target)).toBe(`teleported`)\n    })\n\n    test('should traverse comment node after updating in optimize mode', async () => {\n      const target = nodeOps.createElement('div')\n      const root = nodeOps.createElement('div')\n      const count = ref(0)\n      let teleport\n\n      __DEV__ = false\n      render(\n        h(() => {\n          teleport =\n            (openBlock(),\n            createBlock(Teleport, { to: target }, [\n              createCommentVNode('comment in teleport'),\n            ]))\n          return h('div', null, [\n            createTextVNode(toDisplayString(count.value)),\n            teleport,\n          ])\n        }),\n        root,\n      )\n      const commentNode = teleport!.children[0].el\n      expect(serializeInner(root)).toBe(`<div>0</div>`)\n      expect(serializeInner(target)).toBe(`<!--comment in teleport-->`)\n      expect(serialize(commentNode)).toBe(`<!--comment in teleport-->`)\n\n      count.value = 1\n      await nextTick()\n      __DEV__ = true\n      expect(serializeInner(root)).toBe(`<div>1</div>`)\n      expect(teleport!.children[0].el).toBe(commentNode)\n    })\n\n    test('should remove children when unmounted', () => {\n      const target = nodeOps.createElement('div')\n      const root = nodeOps.createElement('div')\n\n      function testUnmount(props: any) {\n        render(\n          h(() => [\n            h(Teleport, props, h('div', 'teleported')),\n            h('div', 'root'),\n          ]),\n          root,\n        )\n        expect(serializeInner(target)).toBe(\n          props.disabled ? `` : `<div>teleported</div>`,\n        )\n\n        render(null, root)\n        expect(serializeInner(target)).toBe('')\n        expect(target.children.length).toBe(0)\n      }\n\n      testUnmount({ to: target, disabled: false })\n      testUnmount({ to: target, disabled: true })\n      testUnmount({ to: null, disabled: true })\n    })\n\n    // #10747\n    test('should unmount correctly when using top level comment in teleport', async () => {\n      const target = nodeOps.createElement('div')\n      const root = nodeOps.createElement('div')\n      const count = ref(0)\n\n      __DEV__ = false\n      render(\n        h(() => {\n          return h('div', null, [\n            createTextVNode(toDisplayString(count.value)),\n            (openBlock(),\n            createBlock(Teleport, { to: target }, [\n              createCommentVNode('comment in teleport'),\n            ])),\n          ])\n        }),\n        root,\n      )\n\n      count.value = 1\n\n      await nextTick()\n      __DEV__ = true\n      render(null, root)\n      expect(root.children.length).toBe(0)\n    })\n\n    test('component with multi roots should be removed when unmounted', () => {\n      const target = nodeOps.createElement('div')\n      const root = nodeOps.createElement('div')\n\n      const Comp = {\n        render() {\n          return [h('p'), h('p')]\n        },\n      }\n\n      render(\n        h(() => [h(Teleport, { to: target }, h(Comp)), h('div', 'root')]),\n        root,\n      )\n      expect(serializeInner(target)).toBe(`<p></p><p></p>`)\n\n      render(null, root)\n      expect(serializeInner(target)).toBe('')\n    })\n\n    // #6347\n    test('descendent component should be unmounted when teleport is disabled and unmounted', () => {\n      const root = nodeOps.createElement('div')\n\n      const CompWithHook = {\n        render() {\n          return [h('p'), h('p')]\n        },\n        beforeUnmount: vi.fn(),\n        unmounted: vi.fn(),\n      }\n\n      render(\n        h(() => [h(Teleport, { to: null, disabled: true }, h(CompWithHook))]),\n        root,\n      )\n      expect(CompWithHook.beforeUnmount).toBeCalledTimes(0)\n      expect(CompWithHook.unmounted).toBeCalledTimes(0)\n\n      render(null, root)\n\n      expect(CompWithHook.beforeUnmount).toBeCalledTimes(1)\n      expect(CompWithHook.unmounted).toBeCalledTimes(1)\n    })\n\n    test('multiple teleport with same target', () => {\n      const target = nodeOps.createElement('div')\n      const root = nodeOps.createElement('div')\n\n      render(\n        h('div', [\n          h(Teleport, { to: target }, h('div', 'one')),\n          h(Teleport, { to: target }, 'two'),\n        ]),\n        root,\n      )\n\n      expect(serializeInner(root)).toBe(\n        `<div><!--teleport start--><!--teleport end--><!--teleport start--><!--teleport end--></div>`,\n      )\n      expect(serializeInner(target)).toBe(`<div>one</div>two`)\n\n      // update existing content\n      render(\n        h('div', [\n          h(Teleport, { to: target }, [h('div', 'one'), h('div', 'two')]),\n          h(Teleport, { to: target }, 'three'),\n        ]),\n        root,\n      )\n      expect(serializeInner(target)).toBe(`<div>one</div><div>two</div>three`)\n\n      // toggling\n      render(h('div', [null, h(Teleport, { to: target }, 'three')]), root)\n      expect(serializeInner(root)).toBe(\n        `<div><!----><!--teleport start--><!--teleport end--></div>`,\n      )\n      expect(serializeInner(target)).toBe(`three`)\n\n      // toggle back\n      render(\n        h('div', [\n          h(Teleport, { to: target }, [h('div', 'one'), h('div', 'two')]),\n          h(Teleport, { to: target }, 'three'),\n        ]),\n        root,\n      )\n      expect(serializeInner(root)).toBe(\n        `<div><!--teleport start--><!--teleport end--><!--teleport start--><!--teleport end--></div>`,\n      )\n      // should append\n      expect(serializeInner(target)).toBe(`three<div>one</div><div>two</div>`)\n\n      // toggle the other teleport\n      render(\n        h('div', [\n          h(Teleport, { to: target }, [h('div', 'one'), h('div', 'two')]),\n          null,\n        ]),\n        root,\n      )\n      expect(serializeInner(root)).toBe(\n        `<div><!--teleport start--><!--teleport end--><!----></div>`,\n      )\n      expect(serializeInner(target)).toBe(`<div>one</div><div>two</div>`)\n    })\n\n    test('should work when using template ref as target', async () => {\n      const root = nodeOps.createElement('div')\n      const target = ref(null)\n      const disabled = ref(true)\n\n      const App = {\n        setup() {\n          return () =>\n            h(Fragment, [\n              h('div', { ref: target }),\n              h(\n                Teleport,\n                { to: target.value, disabled: disabled.value },\n                h('div', 'teleported'),\n              ),\n            ])\n        },\n      }\n      render(h(App), root)\n      expect(serializeInner(root)).toBe(\n        `<div></div><!--teleport start--><div>teleported</div><!--teleport end-->`,\n      )\n\n      disabled.value = false\n      await nextTick()\n      expect(serializeInner(root)).toBe(\n        `<div><div>teleported</div></div><!--teleport start--><!--teleport end-->`,\n      )\n    })\n\n    test('disabled', () => {\n      const target = nodeOps.createElement('div')\n      const root = nodeOps.createElement('div')\n\n      const renderWithDisabled = (disabled: boolean) => {\n        return h(Fragment, [\n          h(Teleport, { to: target, disabled }, h('div', 'teleported')),\n          h('div', 'root'),\n        ])\n      }\n\n      render(renderWithDisabled(false), root)\n      expect(serializeInner(root)).toBe(\n        `<!--teleport start--><!--teleport end--><div>root</div>`,\n      )\n      expect(serializeInner(target)).toBe(`<div>teleported</div>`)\n\n      render(renderWithDisabled(true), root)\n      expect(serializeInner(root)).toBe(\n        `<!--teleport start--><div>teleported</div><!--teleport end--><div>root</div>`,\n      )\n      expect(serializeInner(target)).toBe(``)\n\n      // toggle back\n      render(renderWithDisabled(false), root)\n      expect(serializeInner(root)).toBe(\n        `<!--teleport start--><!--teleport end--><div>root</div>`,\n      )\n      expect(serializeInner(target)).toBe(`<div>teleported</div>`)\n    })\n\n    test('moving teleport while enabled', () => {\n      const target = nodeOps.createElement('div')\n      const root = nodeOps.createElement('div')\n\n      render(\n        h(Fragment, [\n          h(Teleport, { to: target }, h('div', 'teleported')),\n          h('div', 'root'),\n        ]),\n        root,\n      )\n      expect(serializeInner(root)).toBe(\n        `<!--teleport start--><!--teleport end--><div>root</div>`,\n      )\n      expect(serializeInner(target)).toBe(`<div>teleported</div>`)\n\n      render(\n        h(Fragment, [\n          h('div', 'root'),\n          h(Teleport, { to: target }, h('div', 'teleported')),\n        ]),\n        root,\n      )\n      expect(serializeInner(root)).toBe(\n        `<div>root</div><!--teleport start--><!--teleport end-->`,\n      )\n      expect(serializeInner(target)).toBe(`<div>teleported</div>`)\n\n      render(\n        h(Fragment, [\n          h(Teleport, { to: target }, h('div', 'teleported')),\n          h('div', 'root'),\n        ]),\n        root,\n      )\n      expect(serializeInner(root)).toBe(\n        `<!--teleport start--><!--teleport end--><div>root</div>`,\n      )\n      expect(serializeInner(target)).toBe(`<div>teleported</div>`)\n    })\n\n    test('moving teleport while disabled', () => {\n      const target = nodeOps.createElement('div')\n      const root = nodeOps.createElement('div')\n\n      render(\n        h(Fragment, [\n          h(Teleport, { to: target, disabled: true }, h('div', 'teleported')),\n          h('div', 'root'),\n        ]),\n        root,\n      )\n      expect(serializeInner(root)).toBe(\n        `<!--teleport start--><div>teleported</div><!--teleport end--><div>root</div>`,\n      )\n      expect(serializeInner(target)).toBe('')\n\n      render(\n        h(Fragment, [\n          h('div', 'root'),\n          h(Teleport, { to: target, disabled: true }, h('div', 'teleported')),\n        ]),\n        root,\n      )\n      expect(serializeInner(root)).toBe(\n        `<div>root</div><!--teleport start--><div>teleported</div><!--teleport end-->`,\n      )\n      expect(serializeInner(target)).toBe('')\n\n      render(\n        h(Fragment, [\n          h(Teleport, { to: target, disabled: true }, h('div', 'teleported')),\n          h('div', 'root'),\n        ]),\n        root,\n      )\n      expect(serializeInner(root)).toBe(\n        `<!--teleport start--><div>teleported</div><!--teleport end--><div>root</div>`,\n      )\n      expect(serializeInner(target)).toBe('')\n    })\n\n    test('should work with block tree', async () => {\n      const target = nodeOps.createElement('div')\n      const root = nodeOps.createElement('div')\n      const disabled = ref(false)\n\n      const App = {\n        setup() {\n          return {\n            target: markRaw(target),\n            disabled,\n          }\n        },\n        render: compile(`\n        <teleport :to=\"target\" :disabled=\"disabled\">\n          <div>teleported</div><span>{{ disabled }}</span><span v-if=\"disabled\"/>\n        </teleport>\n        <div>root</div>\n        `),\n      }\n      render(h(App), root)\n      expect(serializeInner(root)).toBe(\n        `<!--teleport start--><!--teleport end--><div>root</div>`,\n      )\n      expect(serializeInner(target)).toBe(\n        `<div>teleported</div><span>false</span><!--v-if-->`,\n      )\n\n      disabled.value = true\n      await nextTick()\n      expect(serializeInner(root)).toBe(\n        `<!--teleport start--><div>teleported</div><span>true</span><span></span><!--teleport end--><div>root</div>`,\n      )\n      expect(serializeInner(target)).toBe(``)\n\n      // toggle back\n      disabled.value = false\n      await nextTick()\n      expect(serializeInner(root)).toBe(\n        `<!--teleport start--><!--teleport end--><div>root</div>`,\n      )\n      expect(serializeInner(target)).toBe(\n        `<div>teleported</div><span>false</span><!--v-if-->`,\n      )\n    })\n\n    // #3497\n    test(`the dir hooks of the Teleport's children should be called correctly`, async () => {\n      const target = nodeOps.createElement('div')\n      const root = nodeOps.createElement('div')\n      const toggle = ref(true)\n      const dir = {\n        mounted: vi.fn(),\n        unmounted: vi.fn(),\n      }\n\n      const app = createApp({\n        setup() {\n          return () => {\n            return toggle.value\n              ? h(Teleport, { to: target }, [\n                  withDirectives(h('div', ['foo']), [[dir]]),\n                ])\n              : null\n          }\n        },\n      })\n      app.mount(root)\n\n      expect(serializeInner(root)).toBe(\n        `<!--teleport start--><!--teleport end-->`,\n      )\n      expect(serializeInner(target)).toBe(`<div>foo</div>`)\n      await nextTick()\n      expect(dir.mounted).toHaveBeenCalledTimes(1)\n      expect(dir.unmounted).toHaveBeenCalledTimes(0)\n\n      toggle.value = false\n      await nextTick()\n      expect(serializeInner(root)).toBe(`<!---->`)\n      expect(serializeInner(target)).toBe(``)\n      expect(dir.mounted).toHaveBeenCalledTimes(1)\n      expect(dir.unmounted).toHaveBeenCalledTimes(1)\n    })\n\n    // #7835\n    test(`ensure that target changes when disabled are updated correctly when enabled`, async () => {\n      const root = nodeOps.createElement('div')\n      const target1 = nodeOps.createElement('div')\n      const target2 = nodeOps.createElement('div')\n      const target3 = nodeOps.createElement('div')\n      const target = ref(target1)\n      const disabled = ref(true)\n\n      const App = {\n        setup() {\n          return () =>\n            h(Fragment, [\n              h(\n                Teleport,\n                { to: target.value, disabled: disabled.value },\n                h('div', 'teleported'),\n              ),\n            ])\n        },\n      }\n      render(h(App), root)\n      disabled.value = false\n      await nextTick()\n      expect(serializeInner(target1)).toBe(`<div>teleported</div>`)\n      expect(serializeInner(target2)).toBe(``)\n      expect(serializeInner(target3)).toBe(``)\n\n      disabled.value = true\n      await nextTick()\n      target.value = target2\n      await nextTick()\n      expect(serializeInner(target1)).toBe(``)\n      expect(serializeInner(target2)).toBe(``)\n      expect(serializeInner(target3)).toBe(``)\n\n      target.value = target3\n      await nextTick()\n      expect(serializeInner(target1)).toBe(``)\n      expect(serializeInner(target2)).toBe(``)\n      expect(serializeInner(target3)).toBe(``)\n\n      disabled.value = false\n      await nextTick()\n      expect(serializeInner(target1)).toBe(``)\n      expect(serializeInner(target2)).toBe(``)\n      expect(serializeInner(target3)).toBe(`<div>teleported</div>`)\n    })\n\n    //#9071\n    test('toggle sibling node inside target node', async () => {\n      const root = document.createElement('div')\n      const show = ref(false)\n      const App = defineComponent({\n        setup() {\n          return () => {\n            return show.value\n              ? h(Teleport, { to: root }, [h('div', 'teleported')])\n              : h('div', 'foo')\n          }\n        },\n      })\n\n      domRender(h(App), root)\n      expect(root.innerHTML).toBe('<div>foo</div>')\n\n      show.value = true\n      await nextTick()\n\n      expect(root.innerHTML).toBe(\n        '<!--teleport start--><!--teleport end--><div>teleported</div>',\n      )\n\n      show.value = false\n      await nextTick()\n\n      expect(root.innerHTML).toBe('<div>foo</div>')\n    })\n\n    test('unmount previous sibling node inside target node', async () => {\n      const root = document.createElement('div')\n      const parentShow = ref(false)\n      const childShow = ref(true)\n\n      const Comp = {\n        setup() {\n          return () => h(Teleport, { to: root }, [h('div', 'foo')])\n        },\n      }\n\n      const App = defineComponent({\n        setup() {\n          return () => {\n            return parentShow.value\n              ? h(Fragment, { key: 0 }, [\n                  childShow.value ? h(Comp) : createCommentVNode('v-if'),\n                ])\n              : createCommentVNode('v-if')\n          }\n        },\n      })\n\n      domRender(h(App), root)\n      expect(root.innerHTML).toBe('<!--v-if-->')\n\n      parentShow.value = true\n      await nextTick()\n      expect(root.innerHTML).toBe(\n        '<!--teleport start--><!--teleport end--><div>foo</div>',\n      )\n\n      parentShow.value = false\n      await nextTick()\n      expect(root.innerHTML).toBe('<!--v-if-->')\n    })\n\n    test('accessing template refs inside teleport', async () => {\n      const target = nodeOps.createElement('div')\n      const tRef = ref()\n      let tRefInMounted\n\n      render(\n        h({\n          render: () => [\n            h(Teleport, { to: target }, h('div', { ref: tRef }, 'teleported')),\n            h('div', 'root'),\n          ],\n          mounted() {\n            tRefInMounted = tRef.value\n          },\n        }),\n        nodeOps.createElement('div'),\n      )\n\n      // children[0] is the start anchor\n      expect(tRefInMounted).toBe(target.children[1])\n    })\n  }\n\n  test('handle update and hmr rerender', async () => {\n    const target = document.createElement('div')\n    const root = document.createElement('div')\n\n    const Comp = {\n      setup() {\n        const cls = ref('foo')\n        onMounted(() => {\n          // trigger update\n          cls.value = 'bar'\n        })\n        return { cls, target }\n      },\n      template: `\n        <Teleport :to=\"target\">\n          <div :class=\"cls\">\n            <div>\n              <slot></slot>\n            </div>\n          </div>\n        </Teleport>\n      `,\n    }\n\n    const appId = 'test-app-id'\n    const App = {\n      __hmrId: appId,\n      components: { Comp },\n      render() {\n        return originalH(Comp, null, { default: () => originalH('div', 'foo') })\n      },\n    }\n    createRecord(appId, App)\n\n    domRender(originalH(App), root)\n    expect(target.innerHTML).toBe(\n      '<div class=\"foo\"><div><div>foo</div></div></div>',\n    )\n    await nextTick()\n    expect(target.innerHTML).toBe(\n      '<div class=\"bar\"><div><div>foo</div></div></div>',\n    )\n\n    rerender(appId, () =>\n      originalH(Comp, null, { default: () => originalH('div', 'bar') }),\n    )\n    await nextTick()\n    expect(target.innerHTML).toBe(\n      '<div class=\"bar\"><div><div>bar</div></div></div>',\n    )\n  })\n})\n"
  },
  {
    "path": "packages/runtime-core/__tests__/directives.spec.ts",
    "content": "import {\n  type DirectiveBinding,\n  type DirectiveHook,\n  type VNode,\n  defineComponent,\n  h,\n  nextTick,\n  nodeOps,\n  ref,\n  render,\n  withDirectives,\n} from '@vue/runtime-test'\nimport {\n  type ComponentInternalInstance,\n  currentInstance,\n} from '../src/component'\n\ndescribe('directives', () => {\n  it('should work', async () => {\n    const count = ref(0)\n\n    function assertBindings(binding: DirectiveBinding) {\n      expect(binding.value).toBe(count.value)\n      expect(binding.arg).toBe('foo')\n      expect(binding.instance).toBe(_instance && _instance.proxy)\n      expect(binding.modifiers && binding.modifiers.ok).toBe(true)\n    }\n\n    const beforeMount = vi.fn(((el, binding, vnode, prevVNode) => {\n      expect(el.tag).toBe('div')\n      // should not be inserted yet\n      expect(el.parentNode).toBe(null)\n      expect(root.children.length).toBe(0)\n\n      assertBindings(binding)\n\n      expect(vnode).toBe(_vnode)\n      expect(prevVNode).toBe(null)\n    }) as DirectiveHook)\n\n    const mounted = vi.fn(((el, binding, vnode, prevVNode) => {\n      expect(el.tag).toBe('div')\n      // should be inserted now\n      expect(el.parentNode).toBe(root)\n      expect(root.children[0]).toBe(el)\n\n      assertBindings(binding)\n\n      expect(vnode).toBe(_vnode)\n      expect(prevVNode).toBe(null)\n    }) as DirectiveHook)\n\n    const beforeUpdate = vi.fn(((el, binding, vnode, prevVNode) => {\n      expect(el.tag).toBe('div')\n      expect(el.parentNode).toBe(root)\n      expect(root.children[0]).toBe(el)\n\n      // node should not have been updated yet\n      expect(el.children[0].text).toBe(`${count.value - 1}`)\n\n      assertBindings(binding)\n\n      expect(vnode).toBe(_vnode)\n      expect(prevVNode).toBe(_prevVnode)\n    }) as DirectiveHook)\n\n    const updated = vi.fn(((el, binding, vnode, prevVNode) => {\n      expect(el.tag).toBe('div')\n      expect(el.parentNode).toBe(root)\n      expect(root.children[0]).toBe(el)\n\n      // node should have been updated\n      expect(el.children[0].text).toBe(`${count.value}`)\n\n      assertBindings(binding)\n\n      expect(vnode).toBe(_vnode)\n      expect(prevVNode).toBe(_prevVnode)\n    }) as DirectiveHook)\n\n    const beforeUnmount = vi.fn(((el, binding, vnode, prevVNode) => {\n      expect(el.tag).toBe('div')\n      // should be removed now\n      expect(el.parentNode).toBe(root)\n      expect(root.children[0]).toBe(el)\n\n      assertBindings(binding)\n\n      expect(vnode).toBe(_vnode)\n      expect(prevVNode).toBe(null)\n    }) as DirectiveHook)\n\n    const unmounted = vi.fn(((el, binding, vnode, prevVNode) => {\n      expect(el.tag).toBe('div')\n      // should have been removed\n      expect(el.parentNode).toBe(null)\n      expect(root.children.length).toBe(0)\n\n      assertBindings(binding)\n\n      expect(vnode).toBe(_vnode)\n      expect(prevVNode).toBe(null)\n    }) as DirectiveHook)\n\n    const dir = {\n      beforeMount,\n      mounted,\n      beforeUpdate,\n      updated,\n      beforeUnmount,\n      unmounted,\n    }\n\n    let _instance: ComponentInternalInstance | null = null\n    let _vnode: VNode | null = null\n    let _prevVnode: VNode | null = null\n    const Comp = {\n      setup() {\n        _instance = currentInstance\n      },\n      render() {\n        _prevVnode = _vnode\n        _vnode = withDirectives(h('div', count.value), [\n          [\n            dir,\n            // value\n            count.value,\n            // argument\n            'foo',\n            // modifiers\n            { ok: true },\n          ],\n        ])\n        return _vnode\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(Comp), root)\n\n    expect(beforeMount).toHaveBeenCalledTimes(1)\n    expect(mounted).toHaveBeenCalledTimes(1)\n\n    count.value++\n    await nextTick()\n    expect(beforeUpdate).toHaveBeenCalledTimes(1)\n    expect(updated).toHaveBeenCalledTimes(1)\n\n    render(null, root)\n    expect(beforeUnmount).toHaveBeenCalledTimes(1)\n    expect(unmounted).toHaveBeenCalledTimes(1)\n  })\n\n  it('should work with a function directive', async () => {\n    const count = ref(0)\n\n    function assertBindings(binding: DirectiveBinding) {\n      expect(binding.value).toBe(count.value)\n      expect(binding.arg).toBe('foo')\n      expect(binding.instance).toBe(_instance && _instance.proxy)\n      expect(binding.modifiers && binding.modifiers.ok).toBe(true)\n    }\n\n    const fn = vi.fn(((el, binding, vnode, prevVNode) => {\n      expect(el.tag).toBe('div')\n      expect(el.parentNode).toBe(root)\n\n      assertBindings(binding)\n\n      expect(vnode).toBe(_vnode)\n      expect(prevVNode).toBe(_prevVnode)\n    }) as DirectiveHook)\n\n    let _instance: ComponentInternalInstance | null = null\n    let _vnode: VNode | null = null\n    let _prevVnode: VNode | null = null\n    const Comp = {\n      setup() {\n        _instance = currentInstance\n      },\n      render() {\n        _prevVnode = _vnode\n        _vnode = withDirectives(h('div', count.value), [\n          [\n            fn,\n            // value\n            count.value,\n            // argument\n            'foo',\n            // modifiers\n            { ok: true },\n          ],\n        ])\n        return _vnode\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(Comp), root)\n\n    expect(fn).toHaveBeenCalledTimes(1)\n\n    count.value++\n    await nextTick()\n    expect(fn).toHaveBeenCalledTimes(2)\n  })\n\n  it('should work on component vnode', async () => {\n    const count = ref(0)\n\n    function assertBindings(binding: DirectiveBinding) {\n      expect(binding.value).toBe(count.value)\n      expect(binding.arg).toBe('foo')\n      expect(binding.instance).toBe(_instance && _instance.proxy)\n      expect(binding.modifiers && binding.modifiers.ok).toBe(true)\n    }\n\n    const beforeMount = vi.fn(((el, binding, vnode, prevVNode) => {\n      expect(el.tag).toBe('div')\n      // should not be inserted yet\n      expect(el.parentNode).toBe(null)\n      expect(root.children.length).toBe(0)\n\n      assertBindings(binding)\n\n      expect(vnode.type).toBe(_vnode!.type)\n      expect(prevVNode).toBe(null)\n    }) as DirectiveHook)\n\n    const mounted = vi.fn(((el, binding, vnode, prevVNode) => {\n      expect(el.tag).toBe('div')\n      // should be inserted now\n      expect(el.parentNode).toBe(root)\n      expect(root.children[0]).toBe(el)\n\n      assertBindings(binding)\n\n      expect(vnode.type).toBe(_vnode!.type)\n      expect(prevVNode).toBe(null)\n    }) as DirectiveHook)\n\n    const beforeUpdate = vi.fn(((el, binding, vnode, prevVNode) => {\n      expect(el.tag).toBe('div')\n      expect(el.parentNode).toBe(root)\n      expect(root.children[0]).toBe(el)\n\n      // node should not have been updated yet\n      expect(el.children[0].text).toBe(`${count.value - 1}`)\n\n      assertBindings(binding)\n\n      expect(vnode.type).toBe(_vnode!.type)\n      expect(prevVNode!.type).toBe(_prevVnode!.type)\n    }) as DirectiveHook)\n\n    const updated = vi.fn(((el, binding, vnode, prevVNode) => {\n      expect(el.tag).toBe('div')\n      expect(el.parentNode).toBe(root)\n      expect(root.children[0]).toBe(el)\n\n      // node should have been updated\n      expect(el.children[0].text).toBe(`${count.value}`)\n\n      assertBindings(binding)\n\n      expect(vnode.type).toBe(_vnode!.type)\n      expect(prevVNode!.type).toBe(_prevVnode!.type)\n    }) as DirectiveHook)\n\n    const beforeUnmount = vi.fn(((el, binding, vnode, prevVNode) => {\n      expect(el.tag).toBe('div')\n      // should be removed now\n      expect(el.parentNode).toBe(root)\n      expect(root.children[0]).toBe(el)\n\n      assertBindings(binding)\n\n      expect(vnode.type).toBe(_vnode!.type)\n      expect(prevVNode).toBe(null)\n    }) as DirectiveHook)\n\n    const unmounted = vi.fn(((el, binding, vnode, prevVNode) => {\n      expect(el.tag).toBe('div')\n      // should have been removed\n      expect(el.parentNode).toBe(null)\n      expect(root.children.length).toBe(0)\n\n      assertBindings(binding)\n\n      expect(vnode.type).toBe(_vnode!.type)\n      expect(prevVNode).toBe(null)\n    }) as DirectiveHook)\n\n    const dir = {\n      beforeMount,\n      mounted,\n      beforeUpdate,\n      updated,\n      beforeUnmount,\n      unmounted,\n    }\n\n    let _instance: ComponentInternalInstance | null = null\n    let _vnode: VNode | null = null\n    let _prevVnode: VNode | null = null\n\n    const Child = (props: { count: number }) => {\n      _prevVnode = _vnode\n      _vnode = h('div', props.count)\n      return _vnode\n    }\n\n    const Comp = {\n      setup() {\n        _instance = currentInstance\n      },\n      render() {\n        return withDirectives(h(Child, { count: count.value }), [\n          [\n            dir,\n            // value\n            count.value,\n            // argument\n            'foo',\n            // modifiers\n            { ok: true },\n          ],\n        ])\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(Comp), root)\n\n    expect(beforeMount).toHaveBeenCalledTimes(1)\n    expect(mounted).toHaveBeenCalledTimes(1)\n\n    count.value++\n    await nextTick()\n    expect(beforeUpdate).toHaveBeenCalledTimes(1)\n    expect(updated).toHaveBeenCalledTimes(1)\n\n    render(null, root)\n    expect(beforeUnmount).toHaveBeenCalledTimes(1)\n    expect(unmounted).toHaveBeenCalledTimes(1)\n  })\n\n  // #2298\n  it('directive merging on component root', () => {\n    const d1 = {\n      mounted: vi.fn(),\n    }\n    const d2 = {\n      mounted: vi.fn(),\n    }\n    const Comp = {\n      render() {\n        return withDirectives(h('div'), [[d2]])\n      },\n    }\n\n    const App = {\n      name: 'App',\n      render() {\n        return h('div', [withDirectives(h(Comp), [[d1]])])\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(App), root)\n    expect(d1.mounted).toHaveBeenCalled()\n    expect(d2.mounted).toHaveBeenCalled()\n  })\n\n  test('should disable tracking inside directive lifecycle hooks', async () => {\n    const count = ref(0)\n    const text = ref('')\n    const beforeUpdate = vi.fn(() => count.value++)\n\n    const App = {\n      render() {\n        return withDirectives(h('p', text.value), [\n          [\n            {\n              beforeUpdate,\n            },\n          ],\n        ])\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(App), root)\n    expect(beforeUpdate).toHaveBeenCalledTimes(0)\n    expect(count.value).toBe(0)\n\n    text.value = 'foo'\n    await nextTick()\n    expect(beforeUpdate).toHaveBeenCalledTimes(1)\n    expect(count.value).toBe(1)\n  })\n\n  test('should receive exposeProxy for closed instances', async () => {\n    let res: string\n    const App = defineComponent({\n      setup(_, { expose }) {\n        expose({\n          msg: 'Test',\n        })\n\n        return () =>\n          withDirectives(h('p', 'Lore Ipsum'), [\n            [\n              {\n                mounted(el, { instance }) {\n                  res = (instance as any).msg as string\n                },\n              },\n            ],\n          ])\n      },\n    })\n    const root = nodeOps.createElement('div')\n    render(h(App), root)\n    expect(res!).toBe('Test')\n  })\n\n  test('should not throw with unknown directive', async () => {\n    const d1 = {\n      mounted: vi.fn(),\n    }\n    const App = {\n      name: 'App',\n      render() {\n        // simulates the code generated on an unknown directive\n        return withDirectives(h('div'), [[undefined], [d1]])\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(App), root)\n    expect(d1.mounted).toHaveBeenCalled()\n  })\n})\n"
  },
  {
    "path": "packages/runtime-core/__tests__/errorHandling.spec.ts",
    "content": "import {\n  type VNode,\n  computed,\n  createApp,\n  defineComponent,\n  h,\n  nextTick,\n  nodeOps,\n  onErrorCaptured,\n  onMounted,\n  ref,\n  render,\n  watch,\n  watchEffect,\n} from '@vue/runtime-test'\nimport { ErrorCodes, ErrorTypeStrings } from '../src/errorHandling'\n\ndescribe('error handling', () => {\n  test('propagation', () => {\n    const err = new Error('foo')\n    const fn = vi.fn()\n\n    const Comp = {\n      setup() {\n        onErrorCaptured((err, instance, info) => {\n          fn(err, info, 'root')\n          return false\n        })\n        return () => h(Child)\n      },\n    }\n\n    const Child = {\n      setup() {\n        onErrorCaptured((err, instance, info) => {\n          fn(err, info, 'child')\n        })\n        return () => h(GrandChild)\n      },\n    }\n\n    const GrandChild = {\n      setup() {\n        onMounted(() => {\n          throw err\n        })\n        return () => null\n      },\n    }\n\n    render(h(Comp), nodeOps.createElement('div'))\n    expect(fn).toHaveBeenCalledTimes(2)\n    expect(fn).toHaveBeenCalledWith(err, 'mounted hook', 'root')\n    expect(fn).toHaveBeenCalledWith(err, 'mounted hook', 'child')\n  })\n\n  test('propagation stoppage', () => {\n    const err = new Error('foo')\n    const fn = vi.fn()\n\n    const Comp = {\n      setup() {\n        onErrorCaptured((err, instance, info) => {\n          fn(err, info, 'root')\n          return false\n        })\n        return () => h(Child)\n      },\n    }\n\n    const Child = {\n      setup() {\n        onErrorCaptured((err, instance, info) => {\n          fn(err, info, 'child')\n          return false\n        })\n        return () => h(GrandChild)\n      },\n    }\n\n    const GrandChild = {\n      setup() {\n        onMounted(() => {\n          throw err\n        })\n        return () => null\n      },\n    }\n\n    render(h(Comp), nodeOps.createElement('div'))\n    expect(fn).toHaveBeenCalledTimes(1)\n    expect(fn).toHaveBeenCalledWith(err, 'mounted hook', 'child')\n  })\n\n  test('async error handling', async () => {\n    const err = new Error('foo')\n    const fn = vi.fn()\n\n    const Comp = {\n      setup() {\n        onErrorCaptured((err, instance, info) => {\n          fn(err, info)\n          return false\n        })\n        return () => h(Child)\n      },\n    }\n\n    const Child = {\n      setup() {\n        onMounted(async () => {\n          throw err\n        })\n      },\n      render() {},\n    }\n\n    render(h(Comp), nodeOps.createElement('div'))\n    expect(fn).not.toHaveBeenCalled()\n    await new Promise(r => setTimeout(r))\n    expect(fn).toHaveBeenCalledWith(err, 'mounted hook')\n  })\n\n  test('error thrown in onErrorCaptured', () => {\n    const err = new Error('foo')\n    const err2 = new Error('bar')\n    const fn = vi.fn()\n\n    const Comp = {\n      setup() {\n        onErrorCaptured((err, instance, info) => {\n          fn(err, info)\n          return false\n        })\n        return () => h(Child)\n      },\n    }\n\n    const Child = {\n      setup() {\n        onErrorCaptured(() => {\n          throw err2\n        })\n        return () => h(GrandChild)\n      },\n    }\n\n    const GrandChild = {\n      setup() {\n        onMounted(() => {\n          throw err\n        })\n        return () => null\n      },\n    }\n\n    render(h(Comp), nodeOps.createElement('div'))\n    expect(fn).toHaveBeenCalledTimes(2)\n    expect(fn).toHaveBeenCalledWith(err, 'mounted hook')\n    expect(fn).toHaveBeenCalledWith(err2, 'errorCaptured hook')\n  })\n\n  test('setup function', () => {\n    const err = new Error('foo')\n    const fn = vi.fn()\n\n    const Comp = {\n      setup() {\n        onErrorCaptured((err, instance, info) => {\n          fn(err, info)\n          return false\n        })\n        return () => h(Child)\n      },\n    }\n\n    const Child = {\n      setup() {\n        throw err\n      },\n      render() {},\n    }\n\n    render(h(Comp), nodeOps.createElement('div'))\n    expect(fn).toHaveBeenCalledWith(err, 'setup function')\n  })\n\n  // unlike other lifecycle hooks, created/beforeCreate are called as part of\n  // the options API initialization process instead of by the renderer.\n  test('in created/beforeCreate hook', () => {\n    const err = new Error('foo')\n    const fn = vi.fn()\n\n    const Comp = {\n      setup() {\n        onErrorCaptured((err, instance, info) => {\n          fn(err, info)\n          return false\n        })\n        return () => [h(Child1), h(Child2)]\n      },\n    }\n\n    const Child1 = {\n      created() {\n        throw err\n      },\n      render() {},\n    }\n\n    const Child2 = {\n      beforeCreate() {\n        throw err\n      },\n      render() {},\n    }\n\n    render(h(Comp), nodeOps.createElement('div'))\n    expect(fn).toHaveBeenCalledWith(err, 'created hook')\n    expect(fn).toHaveBeenCalledWith(err, 'beforeCreate hook')\n  })\n\n  test('in render function', () => {\n    const err = new Error('foo')\n    const fn = vi.fn()\n\n    const Comp = {\n      setup() {\n        onErrorCaptured((err, instance, info) => {\n          fn(err, info)\n          return false\n        })\n        return () => h(Child)\n      },\n    }\n\n    const Child = {\n      setup() {\n        return () => {\n          throw err\n        }\n      },\n    }\n\n    render(h(Comp), nodeOps.createElement('div'))\n    expect(fn).toHaveBeenCalledWith(err, 'render function')\n  })\n\n  test('in function ref', () => {\n    const err = new Error('foo')\n    const ref = () => {\n      throw err\n    }\n    const fn = vi.fn()\n\n    const Comp = {\n      setup() {\n        onErrorCaptured((err, instance, info) => {\n          fn(err, info)\n          return false\n        })\n        return () => h(Child)\n      },\n    }\n\n    const Child = defineComponent(() => () => h('div', { ref }))\n\n    render(h(Comp), nodeOps.createElement('div'))\n    expect(fn).toHaveBeenCalledWith(err, 'ref function')\n  })\n\n  test('in effect', () => {\n    const err = new Error('foo')\n    const fn = vi.fn()\n\n    const Comp = {\n      setup() {\n        onErrorCaptured((err, instance, info) => {\n          fn(err, info)\n          return false\n        })\n        return () => h(Child)\n      },\n    }\n\n    const Child = {\n      setup() {\n        watchEffect(() => {\n          throw err\n        })\n        return () => null\n      },\n    }\n\n    render(h(Comp), nodeOps.createElement('div'))\n    expect(fn).toHaveBeenCalledWith(err, 'watcher callback')\n  })\n\n  test('in watch getter', () => {\n    const err = new Error('foo')\n    const fn = vi.fn()\n\n    const Comp = {\n      setup() {\n        onErrorCaptured((err, instance, info) => {\n          fn(err, info)\n          return false\n        })\n        return () => h(Child)\n      },\n    }\n\n    const Child = {\n      setup() {\n        watch(\n          () => {\n            throw err\n          },\n          () => {},\n        )\n        return () => null\n      },\n    }\n\n    render(h(Comp), nodeOps.createElement('div'))\n    expect(fn).toHaveBeenCalledWith(err, 'watcher getter')\n  })\n\n  test('in watch callback', async () => {\n    const err = new Error('foo')\n    const fn = vi.fn()\n\n    const Comp = {\n      setup() {\n        onErrorCaptured((err, instance, info) => {\n          fn(err, info)\n          return false\n        })\n        return () => h(Child)\n      },\n    }\n\n    const count = ref(0)\n    const Child = {\n      setup() {\n        watch(\n          () => count.value,\n          () => {\n            throw err\n          },\n        )\n        return () => null\n      },\n    }\n\n    render(h(Comp), nodeOps.createElement('div'))\n\n    count.value++\n    await nextTick()\n    expect(fn).toHaveBeenCalledWith(err, 'watcher callback')\n  })\n\n  test('in effect cleanup', async () => {\n    const err = new Error('foo')\n    const count = ref(0)\n    const fn = vi.fn()\n\n    const Comp = {\n      setup() {\n        onErrorCaptured((err, instance, info) => {\n          fn(err, info)\n          return false\n        })\n        return () => h(Child)\n      },\n    }\n\n    const Child = {\n      setup() {\n        watchEffect(onCleanup => {\n          count.value\n          onCleanup(() => {\n            throw err\n          })\n        })\n        return () => null\n      },\n    }\n\n    render(h(Comp), nodeOps.createElement('div'))\n\n    count.value++\n    await nextTick()\n    expect(fn).toHaveBeenCalledWith(err, 'watcher cleanup function')\n  })\n\n  test('in component event handler via emit', () => {\n    const err = new Error('foo')\n    const fn = vi.fn()\n\n    const Comp = {\n      setup() {\n        onErrorCaptured((err, instance, info) => {\n          fn(err, info)\n          return false\n        })\n        return () =>\n          h(Child, {\n            onFoo: () => {\n              throw err\n            },\n          })\n      },\n    }\n\n    const Child = {\n      setup(props: any, { emit }: any) {\n        emit('foo')\n        return () => null\n      },\n    }\n\n    render(h(Comp), nodeOps.createElement('div'))\n    expect(fn).toHaveBeenCalledWith(err, 'component event handler')\n  })\n\n  test('in component event handler via emit (async)', async () => {\n    const err = new Error('foo')\n    const fn = vi.fn()\n\n    const Comp = {\n      setup() {\n        onErrorCaptured((err, instance, info) => {\n          fn(err, info)\n          return false\n        })\n        return () =>\n          h(Child, {\n            async onFoo() {\n              throw err\n            },\n          })\n      },\n    }\n\n    const Child = {\n      props: ['onFoo'],\n      setup(props: any, { emit }: any) {\n        emit('foo')\n        return () => null\n      },\n    }\n\n    render(h(Comp), nodeOps.createElement('div'))\n    await nextTick()\n    expect(fn).toHaveBeenCalledWith(err, 'component event handler')\n  })\n\n  test('in component event handler via emit (async + array)', async () => {\n    const err = new Error('foo')\n    const fn = vi.fn()\n\n    const res: Promise<any>[] = []\n    const createAsyncHandler = (p: Promise<any>) => () => {\n      res.push(p)\n      return p\n    }\n\n    const Comp = {\n      setup() {\n        onErrorCaptured((err, instance, info) => {\n          fn(err, info)\n          return false\n        })\n        return () =>\n          h(Child, {\n            onFoo: [\n              createAsyncHandler(Promise.reject(err)),\n              createAsyncHandler(Promise.resolve(1)),\n            ],\n          })\n      },\n    }\n\n    const Child = {\n      setup(props: any, { emit }: any) {\n        emit('foo')\n        return () => null\n      },\n    }\n\n    render(h(Comp), nodeOps.createElement('div'))\n\n    try {\n      await Promise.all(res)\n    } catch (e: any) {\n      expect(e).toBe(err)\n    }\n    expect(fn).toHaveBeenCalledWith(err, 'component event handler')\n  })\n\n  it('should warn unhandled', () => {\n    const groupCollapsed = vi.spyOn(console, 'groupCollapsed')\n    groupCollapsed.mockImplementation(() => {})\n    const log = vi.spyOn(console, 'log')\n    log.mockImplementation(() => {})\n\n    const err = new Error('foo')\n    const fn = vi.fn()\n\n    const Comp = {\n      setup() {\n        onErrorCaptured((err, instance, info) => {\n          fn(err, info)\n        })\n        return () => h(Child)\n      },\n    }\n\n    const Child = {\n      setup() {\n        throw err\n      },\n      render() {},\n    }\n\n    let caughtError\n    try {\n      render(h(Comp), nodeOps.createElement('div'))\n    } catch (caught) {\n      caughtError = caught\n    }\n    expect(fn).toHaveBeenCalledWith(err, 'setup function')\n    expect(\n      `Unhandled error during execution of setup function`,\n    ).toHaveBeenWarned()\n    expect(caughtError).toBe(err)\n\n    groupCollapsed.mockRestore()\n    log.mockRestore()\n  })\n\n  //# 3127\n  test('handle error in watch & watchEffect', async () => {\n    const error1 = new Error('error1')\n    const error2 = new Error('error2')\n    const error3 = new Error('error3')\n    const error4 = new Error('error4')\n    const handler = vi.fn()\n\n    const app = createApp({\n      setup() {\n        const count = ref(1)\n        watch(\n          count,\n          () => {\n            throw error1\n          },\n          { immediate: true },\n        )\n        watch(\n          count,\n          async () => {\n            throw error2\n          },\n          { immediate: true },\n        )\n        watchEffect(() => {\n          throw error3\n        })\n        watchEffect(async () => {\n          throw error4\n        })\n      },\n      render() {},\n    })\n\n    app.config.errorHandler = handler\n    app.mount(nodeOps.createElement('div'))\n\n    await nextTick()\n    expect(handler).toHaveBeenCalledWith(error1, {}, 'watcher callback')\n    expect(handler).toHaveBeenCalledWith(error2, {}, 'watcher callback')\n    expect(handler).toHaveBeenCalledWith(error3, {}, 'watcher callback')\n    expect(handler).toHaveBeenCalledWith(error4, {}, 'watcher callback')\n    expect(handler).toHaveBeenCalledTimes(4)\n  })\n\n  // #9574\n  test('should pause tracking in error handler', async () => {\n    const error = new Error('error')\n    const x = ref(Math.random())\n\n    const handler = vi.fn(() => {\n      x.value\n      x.value = Math.random()\n    })\n\n    const app = createApp({\n      setup() {\n        return () => {\n          throw error\n        }\n      },\n    })\n\n    app.config.errorHandler = handler\n    app.mount(nodeOps.createElement('div'))\n\n    await nextTick()\n    expect(handler).toHaveBeenCalledWith(error, {}, 'render function')\n    expect(handler).toHaveBeenCalledTimes(1)\n  })\n\n  test('errors in scheduler job with owner instance should be caught', async () => {\n    let vnode: VNode\n    const x = ref(0)\n    const app = createApp({\n      render() {\n        return (vnode = vnode || h('div', x.value))\n      },\n    })\n\n    app.config.errorHandler = vi.fn()\n    app.mount(nodeOps.createElement('div'))\n\n    const error = new Error('error')\n    Object.defineProperty(vnode!, 'el', {\n      get() {\n        throw error\n      },\n    })\n\n    x.value++\n    await nextTick()\n    expect(app.config.errorHandler).toHaveBeenCalledWith(\n      error,\n      {},\n      ErrorTypeStrings[ErrorCodes.COMPONENT_UPDATE],\n    )\n  })\n\n  // #11286\n  test('handle error in computed', async () => {\n    const err = new Error()\n    const handler = vi.fn()\n\n    const count = ref(1)\n    const x = computed(() => {\n      if (count.value === 2) throw err\n      return count.value + 1\n    })\n\n    const app = createApp({\n      setup() {\n        return () => x.value\n      },\n    })\n\n    app.config.errorHandler = handler\n    app.mount(nodeOps.createElement('div'))\n\n    count.value = 2\n\n    await nextTick()\n    expect(handler).toHaveBeenCalledWith(\n      err,\n      {},\n      ErrorTypeStrings[ErrorCodes.COMPONENT_UPDATE],\n    )\n  })\n\n  // #11624\n  test('in computed that is used as key for watch', async () => {\n    const err = new Error('foo')\n    const fn = vi.fn()\n    const trigger = ref(false)\n\n    const Comp = {\n      setup() {\n        onErrorCaptured((err, instance, info) => {\n          fn(err, info)\n          return false\n        })\n        return () => h(Child)\n      },\n    }\n\n    const Child = {\n      setup() {\n        const foo = computed(() => {\n          if (trigger.value) throw err\n          return 1\n        })\n        watch(foo, () => {})\n        return () => null\n      },\n    }\n\n    render(h(Comp), nodeOps.createElement('div'))\n\n    trigger.value = true\n    await nextTick()\n    expect(fn).toHaveBeenCalledWith(\n      err,\n      ErrorTypeStrings[ErrorCodes.COMPONENT_UPDATE],\n    )\n  })\n\n  // native event handler handling should be tested in respective renderers\n})\n"
  },
  {
    "path": "packages/runtime-core/__tests__/h.spec.ts",
    "content": "import { h } from '../src/h'\nimport { createVNode } from '../src/vnode'\nimport type { RawSlots } from '../src/componentSlots'\n\n// Since h is a thin layer on top of createVNode, we are only testing its\n// own logic here. Details of vnode creation is tested in vnode.spec.ts.\ndescribe('renderer: h', () => {\n  test('type only', () => {\n    expect(h('div')).toMatchObject(createVNode('div'))\n  })\n\n  test('type + props', () => {\n    expect(h('div', { id: 'foo' })).toMatchObject(\n      createVNode('div', { id: 'foo' }),\n    )\n  })\n\n  test('type + omit props', () => {\n    // array\n    expect(h('div', ['foo'])).toMatchObject(createVNode('div', null, ['foo']))\n    // default slot\n    const Component = { template: '<br />' }\n    const slot = () => {}\n    expect(h(Component, slot)).toMatchObject(createVNode(Component, null, slot))\n    // single vnode\n    const vnode = h('div')\n    expect(h('div', vnode)).toMatchObject(createVNode('div', null, [vnode]))\n    // text\n    expect(h('div', 'foo')).toMatchObject(createVNode('div', null, 'foo'))\n  })\n\n  test('type + props + children', () => {\n    // array\n    expect(h('div', {}, ['foo'])).toMatchObject(createVNode('div', {}, ['foo']))\n    // slots\n    const slots = {} as RawSlots\n    expect(h('div', {}, slots)).toMatchObject(createVNode('div', {}, slots))\n    const Component = { template: '<br />' }\n    expect(h(Component, {}, slots)).toMatchObject(\n      createVNode(Component, {}, slots),\n    )\n    // default slot\n    const slot = () => {}\n    expect(h(Component, {}, slot)).toMatchObject(\n      createVNode(Component, {}, slot),\n    )\n    // single vnode\n    const vnode = h('div')\n    expect(h('div', {}, vnode)).toMatchObject(createVNode('div', {}, [vnode]))\n    // text\n    expect(h('div', {}, 'foo')).toMatchObject(createVNode('div', {}, 'foo'))\n  })\n\n  test('named slots with null props', () => {\n    const Component = { template: '<br />' }\n    const slot = () => {}\n    expect(\n      h(Component, null, {\n        foo: slot,\n      }),\n    ).toMatchObject(\n      createVNode(Component, null, {\n        foo: slot,\n      }),\n    )\n  })\n\n  // for simple JSX compat\n  // note this signature is not supported in types; it's purely for usage with\n  // compiled code.\n  test('support variadic children', () => {\n    // @ts-expect-error\n    const vnode = h('div', null, h('span'), h('span'))\n    expect(vnode.children).toMatchObject([\n      {\n        type: 'span',\n      },\n      {\n        type: 'span',\n      },\n    ])\n  })\n})\n"
  },
  {
    "path": "packages/runtime-core/__tests__/helpers/createSlots.spec.ts",
    "content": "import type { Slot } from '../../src/componentSlots'\nimport { createSlots } from '../../src/helpers/createSlots'\n\ndescribe('createSlot', () => {\n  const slot = () => []\n  let record: Record<string, Slot>\n\n  beforeEach(() => {\n    record = {}\n  })\n\n  it('should return a slot', () => {\n    const dynamicSlot = [{ name: 'descriptor', fn: slot }]\n\n    const actual = createSlots(record, dynamicSlot)\n\n    expect(actual).toEqual({ descriptor: slot })\n  })\n\n  it('should attach key', () => {\n    const dynamicSlot = [{ name: 'descriptor', fn: slot, key: '1' }]\n\n    const actual = createSlots(record, dynamicSlot)\n    const ret = actual.descriptor()\n    // @ts-expect-error\n    expect(ret.key).toBe('1')\n  })\n\n  it('should check nullability', () => {\n    const slot = (() => {}) as Slot\n    const dynamicSlot = [{ name: 'descriptor', fn: slot, key: '1' }]\n\n    const actual = createSlots(record, dynamicSlot)\n    expect(actual).toHaveProperty('descriptor')\n  })\n\n  it('should add all slots to the record', () => {\n    const dynamicSlot = [\n      { name: 'descriptor', fn: slot },\n      { name: 'descriptor2', fn: slot },\n    ]\n\n    const actual = createSlots(record, dynamicSlot)\n\n    expect(actual).toEqual({ descriptor: slot, descriptor2: slot })\n  })\n\n  it('should add slot to the record when given slot is an array', () => {\n    const dynamicSlot = [\n      { name: 'descriptor', fn: slot },\n      [{ name: 'descriptor2', fn: slot }],\n    ]\n\n    const actual = createSlots(record, dynamicSlot)\n\n    expect(actual).toEqual({ descriptor: slot, descriptor2: slot })\n  })\n\n  it('should add each slot to the record when given slot is an array', () => {\n    const dynamicSlot = [\n      { name: 'descriptor', fn: slot },\n      [\n        { name: 'descriptor2', fn: slot },\n        { name: 'descriptor3', fn: slot },\n      ],\n    ]\n\n    const actual = createSlots(record, dynamicSlot)\n\n    expect(actual).toEqual({\n      descriptor: slot,\n      descriptor2: slot,\n      descriptor3: slot,\n    })\n  })\n})\n"
  },
  {
    "path": "packages/runtime-core/__tests__/helpers/renderList.spec.ts",
    "content": "import {\n  effect,\n  isReactive,\n  reactive,\n  readonly,\n  shallowReactive,\n} from '../../src/index'\nimport { renderList } from '../../src/helpers/renderList'\n\ndescribe('renderList', () => {\n  it('should render items in an array', () => {\n    expect(\n      renderList(['1', '2', '3'], (item, index) => `node ${index}: ${item}`),\n    ).toEqual(['node 0: 1', 'node 1: 2', 'node 2: 3'])\n  })\n\n  it('should render characters of a string', () => {\n    expect(\n      renderList('123', (item, index) => `node ${index}: ${item}`),\n    ).toEqual(['node 0: 1', 'node 1: 2', 'node 2: 3'])\n  })\n\n  it('should render integers 1 through N when given a number N', () => {\n    expect(renderList(3, (item, index) => `node ${index}: ${item}`)).toEqual([\n      'node 0: 1',\n      'node 1: 2',\n      'node 2: 3',\n    ])\n  })\n\n  it('should warn when given a non-integer N', () => {\n    expect(renderList(3.1, () => {})).toEqual([])\n    expect(\n      `The v-for range expects a positive integer value but got 3.1.`,\n    ).toHaveBeenWarned()\n  })\n\n  it('should warn when given a negative N', () => {\n    expect(renderList(-1, () => {})).toEqual([])\n    expect(\n      `The v-for range expects a positive integer value but got -1.`,\n    ).toHaveBeenWarned()\n  })\n\n  it('should not warn when given 0', () => {\n    renderList(0, () => {})\n    expect(\n      `The v-for range expects a positive integer value but got 0.`,\n    ).not.toHaveBeenWarned()\n  })\n\n  it('should render properties in an object', () => {\n    expect(\n      renderList(\n        { a: 1, b: 2, c: 3 },\n        (item, key, index) => `node ${index}/${key}: ${item}`,\n      ),\n    ).toEqual(['node 0/a: 1', 'node 1/b: 2', 'node 2/c: 3'])\n  })\n\n  it('should render an item for entry in an iterable', () => {\n    const iterable = function* () {\n      yield 1\n      yield 2\n      yield 3\n    }\n\n    expect(\n      renderList(iterable(), (item, index) => `node ${index}: ${item}`),\n    ).toEqual(['node 0: 1', 'node 1: 2', 'node 2: 3'])\n  })\n\n  it('should return empty array when source is 0', () => {\n    expect(renderList(0, (item, index) => `node ${index}: ${item}`)).toEqual([])\n  })\n\n  it('should return empty array when source is undefined', () => {\n    expect(\n      renderList(undefined, (item, index) => `node ${index}: ${item}`),\n    ).toEqual([])\n  })\n\n  it('should render items in a reactive array correctly', () => {\n    const reactiveArray = reactive([{ foo: 1 }])\n    expect(renderList(reactiveArray, isReactive)).toEqual([true])\n\n    const shallowReactiveArray = shallowReactive([{ foo: 1 }])\n    expect(renderList(shallowReactiveArray, isReactive)).toEqual([false])\n  })\n\n  it('should not allow mutation', () => {\n    const arr = readonly(reactive([{ foo: 1 }]))\n    expect(\n      renderList(arr, item => {\n        ;(item as any).foo = 0\n        return item.foo\n      }),\n    ).toEqual([1])\n    expect(\n      `Set operation on key \"foo\" failed: target is readonly.`,\n    ).toHaveBeenWarned()\n  })\n\n  it('should trigger effect for deep mutations in readonly reactive arrays', () => {\n    const arr = reactive([{ foo: 1 }])\n    const readonlyArr = readonly(arr)\n\n    let dummy\n    effect(() => {\n      dummy = renderList(readonlyArr, item => item.foo)\n    })\n    expect(dummy).toEqual([1])\n\n    arr[0].foo = 2\n    expect(dummy).toEqual([2])\n  })\n})\n"
  },
  {
    "path": "packages/runtime-core/__tests__/helpers/renderSlot.spec.ts",
    "content": "import { renderSlot } from '../../src/helpers/renderSlot'\nimport {\n  Fragment,\n  type Slot,\n  createBlock,\n  createCommentVNode,\n  createVNode,\n  h,\n  openBlock,\n  withCtx,\n} from '../../src'\nimport { PatchFlags } from '@vue/shared'\nimport { setCurrentRenderingInstance } from '../../src/componentRenderContext'\n\ndescribe('renderSlot', () => {\n  beforeEach(() => {\n    setCurrentRenderingInstance({ type: {} } as any)\n  })\n\n  afterEach(() => {\n    setCurrentRenderingInstance(null)\n  })\n\n  it('should render slot', () => {\n    let child\n    const vnode = renderSlot(\n      { default: () => [(child = h('child'))] },\n      'default',\n      { key: 'foo' },\n    )\n    expect(vnode.children).toEqual([child])\n    expect(vnode.key).toBe('foo')\n  })\n\n  it('should allow symbol values for slot prop key', () => {\n    const key = Symbol()\n    const vnode = renderSlot({ default: () => [h('div')] }, 'default', { key })\n    expect(vnode.key).toBe('_default')\n  })\n\n  it('should render slot fallback', () => {\n    const vnode = renderSlot({}, 'default', { key: 'foo' }, () => ['fallback'])\n    expect(vnode.children).toEqual(['fallback'])\n    // should attach fallback key postfix\n    expect(vnode.key).toBe('foo_fb')\n  })\n\n  it('should warn render ssr slot', () => {\n    renderSlot({ default: (_a, _b, _c) => [h('child')] }, 'default')\n    expect('SSR-optimized slot function detected').toHaveBeenWarned()\n  })\n\n  // #1745\n  it('should force enable tracking', () => {\n    const slot = withCtx(\n      () => {\n        return [createVNode('div', null, 'foo', PatchFlags.TEXT)]\n      },\n      // mock instance\n      { type: {}, appContext: {} } as any,\n    ) as Slot\n\n    // manual invocation should not track\n    const manual = (openBlock(), createBlock(Fragment, null, slot()))\n    expect(manual.dynamicChildren!.length).toBe(0)\n\n    // renderSlot should track\n    const templateRendered = renderSlot({ default: slot }, 'default')\n    expect(templateRendered.dynamicChildren!.length).toBe(1)\n  })\n\n  // #2347 #2461\n  describe('only render valid slot content', () => {\n    it('should ignore slots that are all comments', () => {\n      let fallback\n      const vnode = renderSlot(\n        { default: () => [createCommentVNode('foo')] },\n        'default',\n        undefined,\n        () => [(fallback = h('fallback'))],\n      )\n      expect(vnode.children).toEqual([fallback])\n      expect(vnode.patchFlag).toBe(PatchFlags.BAIL)\n    })\n\n    it('should ignore invalid slot content generated by nested slot', () => {\n      let fallback\n      const vnode = renderSlot(\n        { default: () => [renderSlot({}, 'foo')] },\n        'default',\n        undefined,\n        () => [(fallback = h('fallback'))],\n      )\n      expect(vnode.children).toEqual([fallback])\n      expect(vnode.patchFlag).toBe(PatchFlags.BAIL)\n    })\n  })\n})\n"
  },
  {
    "path": "packages/runtime-core/__tests__/helpers/resolveAssets.spec.ts",
    "content": "import {\n  Comment,\n  type Component,\n  type Directive,\n  type VNode,\n  createApp,\n  createVNode,\n  h,\n  nodeOps,\n  resolveComponent,\n  resolveDirective,\n  resolveDynamicComponent,\n  serializeInner,\n} from '@vue/runtime-test'\n\ndescribe('resolveAssets', () => {\n  test('should work', () => {\n    const FooBar = () => null\n    const BarBaz = { mounted: () => null }\n\n    let component1: Component | string\n    let component2: Component | string\n    let component3: Component | string\n    let component4: Component | string\n    let directive1: Directive\n    let directive2: Directive\n    let directive3: Directive\n    let directive4: Directive\n\n    const Root = {\n      components: {\n        FooBar: FooBar,\n      },\n      directives: {\n        BarBaz: BarBaz,\n      },\n      setup() {\n        return () => {\n          component1 = resolveComponent('FooBar')!\n          directive1 = resolveDirective('BarBaz')!\n          // camelize\n          component2 = resolveComponent('Foo-bar')!\n          directive2 = resolveDirective('Bar-baz')!\n          // capitalize\n          component3 = resolveComponent('fooBar')!\n          directive3 = resolveDirective('barBaz')!\n          // camelize and capitalize\n          component4 = resolveComponent('foo-bar')!\n          directive4 = resolveDirective('bar-baz')!\n        }\n      },\n    }\n\n    const app = createApp(Root)\n    const root = nodeOps.createElement('div')\n    app.mount(root)\n    expect(component1!).toBe(FooBar)\n    expect(component2!).toBe(FooBar)\n    expect(component3!).toBe(FooBar)\n    expect(component4!).toBe(FooBar)\n\n    expect(directive1!).toBe(BarBaz)\n    expect(directive2!).toBe(BarBaz)\n    expect(directive3!).toBe(BarBaz)\n    expect(directive4!).toBe(BarBaz)\n  })\n\n  test('maybeSelfReference', async () => {\n    let component1: Component | string\n    let component2: Component | string\n    let component3: Component | string\n\n    const Foo = () => null\n\n    const Root = {\n      name: 'Root',\n      components: {\n        Foo,\n        Root: Foo,\n      },\n      setup() {\n        return () => {\n          component1 = resolveComponent('Root', true)\n          component2 = resolveComponent('Foo', true)\n          component3 = resolveComponent('Bar', true)\n        }\n      },\n    }\n\n    const app = createApp(Root)\n    const root = nodeOps.createElement('div')\n    app.mount(root)\n\n    expect(component1!).toMatchObject(Root) // explicit self name reference\n    expect(component2!).toBe(Foo) // successful resolve take higher priority\n    expect(component3!).toMatchObject(Root) // fallback when resolve fails\n  })\n\n  describe('warning', () => {\n    test('used outside render() or setup()', () => {\n      resolveComponent('foo')\n      expect(\n        'resolveComponent can only be used in render() or setup().',\n      ).toHaveBeenWarned()\n\n      resolveDirective('foo')\n      expect(\n        'resolveDirective can only be used in render() or setup().',\n      ).toHaveBeenWarned()\n    })\n\n    test('not exist', () => {\n      const Root = {\n        setup() {\n          resolveComponent('foo')\n          resolveDirective('bar')\n          return () => null\n        },\n      }\n\n      const app = createApp(Root)\n      const root = nodeOps.createElement('div')\n      app.mount(root)\n      expect('Failed to resolve component: foo').toHaveBeenWarned()\n      expect('Failed to resolve directive: bar').toHaveBeenWarned()\n    })\n\n    test('resolve dynamic component', () => {\n      const dynamicComponents = {\n        foo: () => 'foo',\n        bar: () => 'bar',\n        baz: { render: () => 'baz' },\n      }\n      let foo, bar, baz // dynamic components\n      let dynamicVNode: VNode\n\n      const Child = {\n        render(this: any) {\n          return this.$slots.default()\n        },\n      }\n\n      const Root = {\n        components: { foo: dynamicComponents.foo },\n        setup() {\n          return () => {\n            foo = resolveDynamicComponent('foo') // <component is=\"foo\"/>\n            bar = resolveDynamicComponent(dynamicComponents.bar) // <component :is=\"bar\"/>, function\n            dynamicVNode = createVNode(resolveDynamicComponent(null)) // <component :is=\"null\"/>\n            return h(Child, () => {\n              // check inside child slots\n              baz = resolveDynamicComponent(dynamicComponents.baz) // <component :is=\"baz\"/>, object\n            })\n          }\n        },\n      }\n\n      const app = createApp(Root)\n      const root = nodeOps.createElement('div')\n      app.mount(root)\n      expect(foo).toBe(dynamicComponents.foo)\n      expect(bar).toBe(dynamicComponents.bar)\n      expect(baz).toBe(dynamicComponents.baz)\n      // should allow explicit falsy type to remove the component\n      expect(dynamicVNode!.type).toBe(Comment)\n    })\n\n    test('resolve dynamic component should fallback to plain element without warning', () => {\n      const Root = {\n        setup() {\n          return () => {\n            return createVNode(resolveDynamicComponent('div') as string, null, {\n              default: () => 'hello',\n            })\n          }\n        },\n      }\n\n      const app = createApp(Root)\n      const root = nodeOps.createElement('div')\n      app.mount(root)\n      expect(serializeInner(root)).toBe('<div>hello</div>')\n    })\n  })\n\n  test('resolving from mixins & extends', () => {\n    const FooBar = () => null\n    const BarBaz = { mounted: () => null }\n\n    let component1: Component | string\n    let component2: Component | string\n    let component3: Component | string\n    let component4: Component | string\n    let directive1: Directive\n    let directive2: Directive\n    let directive3: Directive\n    let directive4: Directive\n\n    const Base = {\n      components: {\n        FooBar: FooBar,\n      },\n    }\n    const Mixin = {\n      directives: {\n        BarBaz: BarBaz,\n      },\n    }\n\n    const Root = {\n      extends: Base,\n      mixins: [Mixin],\n      setup() {\n        return () => {\n          component1 = resolveComponent('FooBar')!\n          directive1 = resolveDirective('BarBaz')!\n          // camelize\n          component2 = resolveComponent('Foo-bar')!\n          directive2 = resolveDirective('Bar-baz')!\n          // capitalize\n          component3 = resolveComponent('fooBar')!\n          directive3 = resolveDirective('barBaz')!\n          // camelize and capitalize\n          component4 = resolveComponent('foo-bar')!\n          directive4 = resolveDirective('bar-baz')!\n        }\n      },\n    }\n\n    const app = createApp(Root)\n    const root = nodeOps.createElement('div')\n    app.mount(root)\n    expect(component1!).toBe(FooBar)\n    expect(component2!).toBe(FooBar)\n    expect(component3!).toBe(FooBar)\n    expect(component4!).toBe(FooBar)\n\n    expect(directive1!).toBe(BarBaz)\n    expect(directive2!).toBe(BarBaz)\n    expect(directive3!).toBe(BarBaz)\n    expect(directive4!).toBe(BarBaz)\n  })\n})\n"
  },
  {
    "path": "packages/runtime-core/__tests__/helpers/toHandlers.spec.ts",
    "content": "import { toHandlers } from '../../src/helpers/toHandlers'\n\ndescribe('toHandlers', () => {\n  it('should not accept non-objects', () => {\n    toHandlers(null as any)\n    toHandlers(undefined as any)\n\n    expect(\n      'v-on with no argument expects an object value.',\n    ).toHaveBeenWarnedTimes(2)\n  })\n\n  it('should properly change object keys', () => {\n    const input = () => {}\n    const change = () => {}\n\n    expect(toHandlers({ input, change })).toStrictEqual({\n      onInput: input,\n      onChange: change,\n    })\n  })\n})\n"
  },
  {
    "path": "packages/runtime-core/__tests__/helpers/useId.spec.ts",
    "content": "/**\n * @vitest-environment jsdom\n */\nimport {\n  type App,\n  Suspense,\n  createApp,\n  defineAsyncComponent,\n  defineComponent,\n  h,\n  onServerPrefetch,\n  useId,\n} from 'vue'\nimport { renderToString } from '@vue/server-renderer'\n\ntype FactoryRes = [App, Promise<any>[]]\ntype TestCaseFactory = () => FactoryRes | Promise<FactoryRes>\n\nasync function runOnClient(factory: TestCaseFactory) {\n  const [app, deps] = await factory()\n  const root = document.createElement('div')\n  app.mount(root)\n  await Promise.all(deps)\n  await promiseWithDelay(null, 0)\n  return root.innerHTML\n}\n\nasync function runOnServer(factory: TestCaseFactory) {\n  const [app, _] = await factory()\n  return (await renderToString(app))\n    .replace(/<!--[\\[\\]]-->/g, '') // remove fragment wrappers\n    .trim()\n}\n\nasync function getOutput(factory: TestCaseFactory) {\n  const clientResult = await runOnClient(factory)\n  const serverResult = await runOnServer(factory)\n  expect(serverResult).toBe(clientResult)\n  return clientResult\n}\n\nfunction promiseWithDelay(res: any, delay: number) {\n  return new Promise<any>(r => {\n    setTimeout(() => r(res), delay)\n  })\n}\n\nconst BasicComponentWithUseId = defineComponent({\n  setup() {\n    const id1 = useId()\n    const id2 = useId()\n    return () => [id1, ' ', id2]\n  },\n})\n\ndescribe('useId', () => {\n  test('basic', async () => {\n    expect(\n      await getOutput(() => {\n        const app = createApp(BasicComponentWithUseId)\n        return [app, []]\n      }),\n    ).toBe('v-0 v-1')\n  })\n\n  test('with config.idPrefix', async () => {\n    expect(\n      await getOutput(() => {\n        const app = createApp(BasicComponentWithUseId)\n        app.config.idPrefix = 'foo'\n        return [app, []]\n      }),\n    ).toBe('foo-0 foo-1')\n  })\n\n  test('async component', async () => {\n    const factory = (\n      delay1: number,\n      delay2: number,\n    ): ReturnType<TestCaseFactory> => {\n      const p1 = promiseWithDelay(BasicComponentWithUseId, delay1)\n      const p2 = promiseWithDelay(BasicComponentWithUseId, delay2)\n      const AsyncOne = defineAsyncComponent(() => p1)\n      const AsyncTwo = defineAsyncComponent(() => p2)\n      const app = createApp({\n        setup() {\n          const id1 = useId()\n          const id2 = useId()\n          return () => [id1, ' ', id2, ' ', h(AsyncOne), ' ', h(AsyncTwo)]\n        },\n      })\n      return [app, [p1, p2]]\n    }\n\n    const expected =\n      'v-0 v-1 ' + // root\n      'v-0-0 v-0-1 ' + // inside first async subtree\n      'v-1-0 v-1-1' // inside second async subtree\n    // assert different async resolution order does not affect id stable-ness\n    expect(await getOutput(() => factory(0, 16))).toBe(expected)\n    expect(await getOutput(() => factory(16, 0))).toBe(expected)\n  })\n\n  test('serverPrefetch', async () => {\n    const factory = (\n      delay1: number,\n      delay2: number,\n    ): ReturnType<TestCaseFactory> => {\n      const p1 = promiseWithDelay(null, delay1)\n      const p2 = promiseWithDelay(null, delay2)\n\n      const SPOne = defineComponent({\n        async serverPrefetch() {\n          await p1\n        },\n        render() {\n          return h(BasicComponentWithUseId)\n        },\n      })\n\n      const SPTwo = defineComponent({\n        async serverPrefetch() {\n          await p2\n        },\n        render() {\n          return h(BasicComponentWithUseId)\n        },\n      })\n\n      const app = createApp({\n        setup() {\n          const id1 = useId()\n          const id2 = useId()\n          return () => [id1, ' ', id2, ' ', h(SPOne), ' ', h(SPTwo)]\n        },\n      })\n      return [app, [p1, p2]]\n    }\n\n    const expected =\n      'v-0 v-1 ' + // root\n      'v-0-0 v-0-1 ' + // inside first async subtree\n      'v-1-0 v-1-1' // inside second async subtree\n    // assert different async resolution order does not affect id stable-ness\n    expect(await getOutput(() => factory(0, 16))).toBe(expected)\n    expect(await getOutput(() => factory(16, 0))).toBe(expected)\n  })\n\n  test('components with serverPrefetch', async () => {\n    const factory = (): ReturnType<TestCaseFactory> => {\n      const SPOne = defineComponent({\n        setup() {\n          onServerPrefetch(() => {})\n          return () => h(BasicComponentWithUseId)\n        },\n      })\n\n      const SPTwo = defineComponent({\n        render() {\n          return h(BasicComponentWithUseId)\n        },\n      })\n\n      const app = createApp({\n        setup() {\n          const id1 = useId()\n          const id2 = useId()\n          return () => [id1, ' ', id2, ' ', h(SPOne), ' ', h(SPTwo)]\n        },\n      })\n      return [app, []]\n    }\n\n    const expected =\n      'v-0 v-1 ' + // root\n      'v-0-0 v-0-1 ' + // inside first async subtree\n      'v-2 v-3' // inside second async subtree\n    // assert different async resolution order does not affect id stable-ness\n    expect(await getOutput(() => factory())).toBe(expected)\n    expect(await getOutput(() => factory())).toBe(expected)\n  })\n\n  test('async setup()', async () => {\n    const factory = (\n      delay1: number,\n      delay2: number,\n    ): ReturnType<TestCaseFactory> => {\n      const p1 = promiseWithDelay(null, delay1)\n      const p2 = promiseWithDelay(null, delay2)\n\n      const ASOne = defineComponent({\n        async setup() {\n          await p1\n          return {}\n        },\n        render() {\n          return h(BasicComponentWithUseId)\n        },\n      })\n\n      const ASTwo = defineComponent({\n        async setup() {\n          await p2\n          return {}\n        },\n        render() {\n          return h(BasicComponentWithUseId)\n        },\n      })\n\n      const app = createApp({\n        setup() {\n          const id1 = useId()\n          const id2 = useId()\n          return () =>\n            h(Suspense, null, {\n              default: h('div', [id1, ' ', id2, ' ', h(ASOne), ' ', h(ASTwo)]),\n            })\n        },\n      })\n      return [app, [p1, p2]]\n    }\n\n    const expected =\n      '<div>' +\n      'v-0 v-1 ' + // root\n      'v-0-0 v-0-1 ' + // inside first async subtree\n      'v-1-0 v-1-1' + // inside second async subtree\n      '</div>'\n    // assert different async resolution order does not affect id stable-ness\n    expect(await getOutput(() => factory(0, 16))).toBe(expected)\n    expect(await getOutput(() => factory(16, 0))).toBe(expected)\n  })\n\n  test('deep nested', async () => {\n    const factory = (): ReturnType<TestCaseFactory> => {\n      const p = Promise.resolve()\n      const One = {\n        async setup() {\n          const id = useId()\n          await p\n          return () => [id, ' ', h(Two), ' ', h(Three)]\n        },\n      }\n      const Two = {\n        async setup() {\n          const id = useId()\n          await p\n          return () => [id, ' ', h(Three), ' ', h(Three)]\n        },\n      }\n      const Three = {\n        async setup() {\n          const id = useId()\n          return () => id\n        },\n      }\n      const app = createApp({\n        setup() {\n          return () =>\n            h(Suspense, null, {\n              default: h(One),\n            })\n        },\n      })\n      return [app, [p]]\n    }\n\n    const expected =\n      'v-0 ' + // One\n      'v-0-0 ' + // Two\n      'v-0-0-0 v-0-0-1 ' + // Three + Three nested in Two\n      'v-0-1' // Three after Two\n    // assert different async resolution order does not affect id stable-ness\n    expect(await getOutput(() => factory())).toBe(expected)\n    expect(await getOutput(() => factory())).toBe(expected)\n  })\n\n  test('async component inside async setup, already resolved', async () => {\n    const factory = async (\n      delay1: number,\n      delay2: number,\n    ): Promise<FactoryRes> => {\n      const p1 = promiseWithDelay(null, delay1)\n      const p2 = promiseWithDelay(BasicComponentWithUseId, delay2)\n      const AsyncInner = defineAsyncComponent(() => p2)\n\n      const AsyncSetup = defineComponent({\n        async setup() {\n          await p1\n          return {}\n        },\n        render() {\n          return h(AsyncInner)\n        },\n      })\n\n      const app = createApp({\n        setup() {\n          const id1 = useId()\n          const id2 = useId()\n          return () =>\n            h(Suspense, null, {\n              default: h('div', [id1, ' ', id2, ' ', h(AsyncSetup)]),\n            })\n        },\n      })\n\n      // the async component may have already been resolved\n      await AsyncInner.__asyncLoader()\n      return [app, [p1, p2]]\n    }\n\n    const expected =\n      '<div>' +\n      'v-0 v-1 ' + // root\n      'v-0-0-0 v-0-0-1' + // async component inside async setup\n      '</div>'\n    // assert different async resolution order does not affect id stable-ness\n    expect(await getOutput(async () => factory(0, 16))).toBe(expected)\n    expect(await getOutput(() => factory(16, 0))).toBe(expected)\n  })\n})\n"
  },
  {
    "path": "packages/runtime-core/__tests__/helpers/useModel.spec.ts",
    "content": "import {\n  Fragment,\n  type Ref,\n  type TestElement,\n  createApp,\n  createBlock,\n  createElementBlock,\n  createElementVNode,\n  createVNode,\n  defineComponent,\n  h,\n  nextTick,\n  nodeOps,\n  openBlock,\n  ref,\n  render,\n  serializeInner,\n  watch,\n} from '@vue/runtime-test'\nimport { useModel } from '../../src/helpers/useModel'\n\ndescribe('useModel', () => {\n  test('basic', async () => {\n    let foo: any\n    const update = () => {\n      foo.value = 'bar'\n    }\n\n    const compRender = vi.fn()\n    const Comp = defineComponent({\n      props: ['modelValue'],\n      emits: ['update:modelValue'],\n      setup(props) {\n        foo = useModel(props, 'modelValue')\n        return () => {\n          compRender()\n          return foo.value\n        }\n      },\n    })\n\n    const msg = ref('')\n    const setValue = vi.fn(v => (msg.value = v))\n    const root = nodeOps.createElement('div')\n    createApp(() =>\n      h(Comp, {\n        modelValue: msg.value,\n        'onUpdate:modelValue': setValue,\n      }),\n    ).mount(root)\n\n    expect(foo.value).toBe('')\n    expect(msg.value).toBe('')\n    expect(setValue).not.toBeCalled()\n    expect(compRender).toBeCalledTimes(1)\n    expect(serializeInner(root)).toBe('')\n\n    // update from child\n    update()\n\n    await nextTick()\n    expect(msg.value).toBe('bar')\n    expect(foo.value).toBe('bar')\n    expect(setValue).toBeCalledTimes(1)\n    expect(compRender).toBeCalledTimes(2)\n    expect(serializeInner(root)).toBe('bar')\n\n    // update from parent\n    msg.value = 'qux'\n    expect(msg.value).toBe('qux')\n\n    await nextTick()\n    expect(msg.value).toBe('qux')\n    expect(foo.value).toBe('qux')\n    expect(setValue).toBeCalledTimes(1)\n    expect(compRender).toBeCalledTimes(3)\n    expect(serializeInner(root)).toBe('qux')\n  })\n\n  test('without parent value (local mutation)', async () => {\n    let foo: any\n    const update = () => {\n      foo.value = 'bar'\n    }\n\n    const compRender = vi.fn()\n    const Comp = defineComponent({\n      props: ['foo'],\n      emits: ['update:foo'],\n      setup(props) {\n        foo = useModel(props, 'foo')\n        return () => {\n          compRender()\n          return foo.value\n        }\n      },\n    })\n\n    const root = nodeOps.createElement('div')\n    const updateFoo = vi.fn()\n    render(h(Comp, { 'onUpdate:foo': updateFoo }), root)\n    expect(compRender).toBeCalledTimes(1)\n    expect(serializeInner(root)).toBe('<!---->')\n\n    expect(foo.value).toBeUndefined()\n    update()\n    // when parent didn't provide value, local mutation is enabled\n    expect(foo.value).toBe('bar')\n\n    await nextTick()\n    expect(updateFoo).toBeCalledTimes(1)\n    expect(compRender).toBeCalledTimes(2)\n    expect(serializeInner(root)).toBe('bar')\n  })\n\n  test('without parent listener (local mutation)', async () => {\n    let foo: any\n    const update = () => {\n      foo.value = 'bar'\n    }\n\n    const compRender = vi.fn()\n    const Comp = defineComponent({\n      props: ['foo'],\n      emits: ['update:foo'],\n      setup(props) {\n        foo = useModel(props, 'foo')\n        return () => {\n          compRender()\n          return foo.value\n        }\n      },\n    })\n\n    const root = nodeOps.createElement('div')\n    // provide initial value\n    render(h(Comp, { foo: 'initial' }), root)\n    expect(compRender).toBeCalledTimes(1)\n    expect(serializeInner(root)).toBe('initial')\n\n    expect(foo.value).toBe('initial')\n    update()\n    // when parent didn't provide value, local mutation is enabled\n    expect(foo.value).toBe('bar')\n\n    await nextTick()\n    expect(compRender).toBeCalledTimes(2)\n    expect(serializeInner(root)).toBe('bar')\n  })\n\n  test('kebab-case v-model (should not be local)', async () => {\n    let foo: any\n\n    const compRender = vi.fn()\n    const Comp = defineComponent({\n      props: ['foo-bar'],\n      emits: ['update:foo-bar'],\n      setup(props) {\n        foo = useModel(props, 'foo-bar')\n        return () => {\n          compRender()\n          return foo.value\n        }\n      },\n    })\n\n    const updateFooBar = vi.fn()\n    const root = nodeOps.createElement('div')\n    // v-model:foo-bar compiles to foo-bar and onUpdate:fooBar\n    render(\n      h(Comp, { 'foo-bar': 'initial', 'onUpdate:fooBar': updateFooBar }),\n      root,\n    )\n    expect(compRender).toBeCalledTimes(1)\n    expect(serializeInner(root)).toBe('initial')\n\n    expect(foo.value).toBe('initial')\n    foo.value = 'bar'\n    // should not be using local mode, so nothing should actually change\n    expect(foo.value).toBe('initial')\n\n    await nextTick()\n    expect(compRender).toBeCalledTimes(1)\n    expect(updateFooBar).toBeCalledTimes(1)\n    expect(updateFooBar).toHaveBeenCalledWith('bar')\n    expect(foo.value).toBe('initial')\n    expect(serializeInner(root)).toBe('initial')\n  })\n\n  test('kebab-case update listener (should not be local)', async () => {\n    let foo: any\n\n    const compRender = vi.fn()\n    const Comp = defineComponent({\n      props: ['foo-bar'],\n      emits: ['update:foo-bar'],\n      setup(props) {\n        foo = useModel(props, 'foo-bar')\n        return () => {\n          compRender()\n          return foo.value\n        }\n      },\n    })\n\n    const updateFooBar = vi.fn()\n    const root = nodeOps.createElement('div')\n    // The template compiler won't create hyphenated listeners, but it could have been passed manually\n    render(\n      h(Comp, { 'foo-bar': 'initial', 'onUpdate:foo-bar': updateFooBar }),\n      root,\n    )\n    expect(compRender).toBeCalledTimes(1)\n    expect(serializeInner(root)).toBe('initial')\n\n    expect(foo.value).toBe('initial')\n    foo.value = 'bar'\n    // should not be using local mode, so nothing should actually change\n    expect(foo.value).toBe('initial')\n\n    await nextTick()\n    expect(compRender).toBeCalledTimes(1)\n    expect(updateFooBar).toBeCalledTimes(1)\n    expect(updateFooBar).toHaveBeenCalledWith('bar')\n    expect(foo.value).toBe('initial')\n    expect(serializeInner(root)).toBe('initial')\n  })\n\n  test('default value', async () => {\n    let count: any\n    const inc = () => {\n      count.value++\n    }\n\n    const compRender = vi.fn()\n    const Comp = defineComponent({\n      props: { count: { default: 0 } },\n      emits: ['update:count'],\n      setup(props) {\n        count = useModel(props, 'count')\n        return () => {\n          compRender()\n          return count.value\n        }\n      },\n    })\n\n    const root = nodeOps.createElement('div')\n    const updateCount = vi.fn()\n    render(h(Comp, { 'onUpdate:count': updateCount }), root)\n    expect(compRender).toBeCalledTimes(1)\n    expect(serializeInner(root)).toBe('0')\n\n    expect(count.value).toBe(0)\n\n    inc()\n    // when parent didn't provide value, local mutation is enabled\n    expect(count.value).toBe(1)\n\n    await nextTick()\n\n    expect(updateCount).toBeCalledTimes(1)\n    expect(compRender).toBeCalledTimes(2)\n    expect(serializeInner(root)).toBe('1')\n  })\n\n  test('parent limiting child value', async () => {\n    let childCount: Ref<number>\n\n    const compRender = vi.fn()\n    const Comp = defineComponent({\n      props: ['count'],\n      emits: ['update:count'],\n      setup(props) {\n        childCount = useModel(props, 'count')\n        return () => {\n          compRender()\n          return childCount.value\n        }\n      },\n    })\n\n    const Parent = defineComponent({\n      setup() {\n        const count = ref(0)\n        watch(count, () => {\n          if (count.value < 0) {\n            count.value = 0\n          }\n        })\n        return () =>\n          h(Comp, {\n            count: count.value,\n            'onUpdate:count': val => {\n              count.value = val\n            },\n          })\n      },\n    })\n\n    const root = nodeOps.createElement('div')\n    render(h(Parent), root)\n    expect(serializeInner(root)).toBe('0')\n\n    // child update\n    childCount!.value = 1\n    // not yet updated\n    expect(childCount!.value).toBe(0)\n\n    await nextTick()\n    expect(childCount!.value).toBe(1)\n    expect(serializeInner(root)).toBe('1')\n\n    // child update to invalid value\n    childCount!.value = -1\n    // not yet updated\n    expect(childCount!.value).toBe(1)\n\n    await nextTick()\n    // limited to 0 by parent\n    expect(childCount!.value).toBe(0)\n    expect(serializeInner(root)).toBe('0')\n  })\n\n  test('has parent value -> no parent value', async () => {\n    let childCount: Ref<number>\n\n    const compRender = vi.fn()\n    const Comp = defineComponent({\n      props: ['count'],\n      emits: ['update:count'],\n      setup(props) {\n        childCount = useModel(props, 'count')\n        return () => {\n          compRender()\n          return childCount.value\n        }\n      },\n    })\n\n    const toggle = ref(true)\n    const Parent = defineComponent({\n      setup() {\n        const count = ref(0)\n        return () =>\n          toggle.value\n            ? h(Comp, {\n                count: count.value,\n                'onUpdate:count': val => {\n                  count.value = val\n                },\n              })\n            : h(Comp)\n      },\n    })\n\n    const root = nodeOps.createElement('div')\n    render(h(Parent), root)\n    expect(serializeInner(root)).toBe('0')\n\n    // child update\n    childCount!.value = 1\n    // not yet updated\n    expect(childCount!.value).toBe(0)\n\n    await nextTick()\n    expect(childCount!.value).toBe(1)\n    expect(serializeInner(root)).toBe('1')\n\n    // parent change\n    toggle.value = false\n\n    await nextTick()\n    // localValue should be reset\n    expect(childCount!.value).toBeUndefined()\n    expect(serializeInner(root)).toBe('<!---->')\n\n    // child local mutation should continue to work\n    childCount!.value = 2\n    expect(childCount!.value).toBe(2)\n\n    await nextTick()\n    expect(serializeInner(root)).toBe('2')\n  })\n\n  // #9838\n  test('pass modelValue to slot (optimized mode) ', async () => {\n    let foo: any\n    const update = () => {\n      foo.value = 'bar'\n    }\n\n    const Comp = {\n      render(this: any) {\n        return this.$slots.default()\n      },\n    }\n\n    const childRender = vi.fn()\n    const slotRender = vi.fn()\n    const Child = defineComponent({\n      props: ['modelValue'],\n      emits: ['update:modelValue'],\n      setup(props) {\n        foo = useModel(props, 'modelValue')\n        return () => {\n          childRender()\n          return (\n            openBlock(),\n            createElementBlock(Fragment, null, [\n              createVNode(Comp, null, {\n                default: () => {\n                  slotRender()\n                  return createElementVNode('div', null, foo.value)\n                },\n                _: 1 /* STABLE */,\n              }),\n            ])\n          )\n        }\n      },\n    })\n\n    const msg = ref('')\n    const setValue = vi.fn(v => (msg.value = v))\n    const root = nodeOps.createElement('div')\n    createApp({\n      render() {\n        return (\n          openBlock(),\n          createBlock(\n            Child,\n            {\n              modelValue: msg.value,\n              'onUpdate:modelValue': setValue,\n            },\n            null,\n            8 /* PROPS */,\n            ['modelValue'],\n          )\n        )\n      },\n    }).mount(root)\n\n    expect(foo.value).toBe('')\n    expect(msg.value).toBe('')\n    expect(setValue).not.toBeCalled()\n    expect(childRender).toBeCalledTimes(1)\n    expect(slotRender).toBeCalledTimes(1)\n    expect(serializeInner(root)).toBe('<div></div>')\n\n    // update from child\n    update()\n\n    await nextTick()\n    expect(msg.value).toBe('bar')\n    expect(foo.value).toBe('bar')\n    expect(setValue).toBeCalledTimes(1)\n    expect(childRender).toBeCalledTimes(2)\n    expect(slotRender).toBeCalledTimes(2)\n    expect(serializeInner(root)).toBe('<div>bar</div>')\n  })\n\n  test('with modifiers & transformers', async () => {\n    let childMsg: Ref<string>\n    let childModifiers: Record<string, true | undefined>\n\n    const compRender = vi.fn()\n    const Comp = defineComponent({\n      props: ['msg', 'msgModifiers'],\n      emits: ['update:msg'],\n      setup(props) {\n        ;[childMsg, childModifiers] = useModel(props, 'msg', {\n          get(val) {\n            return val.toLowerCase()\n          },\n          set(val) {\n            if (childModifiers.upper) {\n              return val.toUpperCase()\n            }\n          },\n        })\n        return () => {\n          compRender()\n          return childMsg.value\n        }\n      },\n    })\n\n    const msg = ref('HI')\n    const Parent = defineComponent({\n      setup() {\n        return () =>\n          h(Comp, {\n            msg: msg.value,\n            msgModifiers: { upper: true },\n            'onUpdate:msg': val => {\n              msg.value = val\n            },\n          })\n      },\n    })\n\n    const root = nodeOps.createElement('div')\n    render(h(Parent), root)\n\n    // should be lowered\n    expect(serializeInner(root)).toBe('hi')\n\n    // child update\n    childMsg!.value = 'Hmm'\n\n    await nextTick()\n    expect(childMsg!.value).toBe('hmm')\n    expect(serializeInner(root)).toBe('hmm')\n    // parent should get uppercase value\n    expect(msg.value).toBe('HMM')\n\n    // parent update\n    msg.value = 'Ughh'\n    await nextTick()\n    expect(serializeInner(root)).toBe('ughh')\n    expect(msg.value).toBe('Ughh')\n\n    // child update again\n    childMsg!.value = 'ughh'\n    await nextTick()\n    expect(msg.value).toBe('UGHH')\n  })\n\n  // #10279\n  test('force local update when setter formats value to the same value', async () => {\n    let childMsg: Ref<string>\n    let childModifiers: Record<string, true | undefined>\n\n    const compRender = vi.fn()\n    const parentRender = vi.fn()\n\n    const Comp = defineComponent({\n      props: ['msg', 'msgModifiers'],\n      emits: ['update:msg'],\n      setup(props) {\n        ;[childMsg, childModifiers] = useModel(props, 'msg', {\n          set(val) {\n            if (childModifiers.number) {\n              return val.replace(/\\D+/g, '')\n            }\n          },\n        })\n        return () => {\n          compRender()\n          return h('input', {\n            // simulate how v-model works\n            onVnodeBeforeMount(vnode) {\n              ;(vnode.el as TestElement).props.value = childMsg.value\n            },\n            onVnodeBeforeUpdate(vnode) {\n              ;(vnode.el as TestElement).props.value = childMsg.value\n            },\n            onInput(value: any) {\n              childMsg.value = value\n            },\n          })\n        }\n      },\n    })\n\n    const msg = ref(1)\n    const Parent = defineComponent({\n      setup() {\n        return () => {\n          parentRender()\n          return h(Comp, {\n            msg: msg.value,\n            msgModifiers: { number: true },\n            'onUpdate:msg': val => {\n              msg.value = val\n            },\n          })\n        }\n      },\n    })\n\n    const root = nodeOps.createElement('div')\n    render(h(Parent), root)\n\n    expect(parentRender).toHaveBeenCalledTimes(1)\n    expect(compRender).toHaveBeenCalledTimes(1)\n    expect(serializeInner(root)).toBe('<input value=1></input>')\n\n    const input = root.children[0] as TestElement\n\n    // simulate v-model update\n    input.props.onInput((input.props.value = '2'))\n    await nextTick()\n    expect(msg.value).toBe(2)\n    expect(parentRender).toHaveBeenCalledTimes(2)\n    expect(compRender).toHaveBeenCalledTimes(2)\n    expect(serializeInner(root)).toBe('<input value=2></input>')\n\n    input.props.onInput((input.props.value = '2a'))\n    await nextTick()\n    expect(msg.value).toBe(2)\n    expect(parentRender).toHaveBeenCalledTimes(2)\n    // should force local update\n    expect(compRender).toHaveBeenCalledTimes(3)\n    expect(serializeInner(root)).toBe('<input value=2></input>')\n\n    input.props.onInput((input.props.value = '2a'))\n    await nextTick()\n    expect(parentRender).toHaveBeenCalledTimes(2)\n    // should not force local update if set to the same value\n    expect(compRender).toHaveBeenCalledTimes(3)\n  })\n\n  test('set no change value', async () => {\n    let changeChildMsg!: (val: string) => void\n\n    const setValue = vi.fn()\n    const Comp = defineComponent({\n      props: ['msg'],\n      emits: ['update:msg'],\n      setup(props) {\n        const childMsg = useModel(props, 'msg')\n        changeChildMsg = (val: string) => (childMsg.value = val)\n        return () => {\n          return childMsg.value\n        }\n      },\n    })\n\n    const defaultVal = 'defaultVal'\n    const msg = ref(defaultVal)\n    const Parent = defineComponent({\n      setup() {\n        return () =>\n          h(Comp, {\n            msg: msg.value,\n            'onUpdate:msg': val => {\n              msg.value = val\n              setValue()\n            },\n          })\n      },\n    })\n\n    const root = nodeOps.createElement('div')\n    render(h(Parent), root)\n\n    expect(setValue).toBeCalledTimes(0)\n\n    changeChildMsg(defaultVal)\n    expect(setValue).toBeCalledTimes(0)\n\n    changeChildMsg('changed')\n    changeChildMsg(defaultVal)\n    expect(setValue).toBeCalledTimes(2)\n    expect(msg.value).toBe(defaultVal)\n  })\n\n  // #11526\n  test('custom getter', () => {\n    let changeChildMsg!: (val: boolean) => void\n    const getter = (value: boolean) => !value\n\n    const Comp = defineComponent({\n      props: ['msg'],\n      emits: ['update:msg'],\n      setup(props) {\n        const childMsg = useModel(props, 'msg', {\n          get: getter,\n          set: value => !value,\n        })\n        changeChildMsg = (val: boolean) => (childMsg.value = val)\n        return () => {\n          return childMsg.value\n        }\n      },\n    })\n\n    const defaultVal = false\n    const msg = ref(defaultVal)\n    const Parent = defineComponent({\n      setup() {\n        return () =>\n          h(Comp, {\n            msg: msg.value,\n            'onUpdate:msg': val => {\n              msg.value = val\n            },\n          })\n      },\n    })\n\n    const root = nodeOps.createElement('div')\n    render(h(Parent), root)\n\n    changeChildMsg(!getter(msg.value))\n    expect(msg.value).toBe(true)\n\n    changeChildMsg(!getter(msg.value))\n    expect(msg.value).toBe(false)\n  })\n\n  // #11541\n  test('custom setter', () => {\n    let changeChildMsg!: (val: boolean) => void\n\n    const Comp = defineComponent({\n      props: ['msg'],\n      emits: ['update:msg'],\n      setup(props) {\n        const childMsg = useModel(props, 'msg', {\n          set: value => {\n            if (value === msg.value) {\n              return null\n            } else {\n              return value\n            }\n          },\n        })\n        changeChildMsg = (val: boolean) => (childMsg.value = val)\n        return () => {\n          return childMsg.value\n        }\n      },\n    })\n\n    const defaultVal = false\n    const msg = ref(defaultVal)\n    const Parent = defineComponent({\n      setup() {\n        return () =>\n          h(Comp, {\n            msg: msg.value,\n            'onUpdate:msg': val => {\n              msg.value = val\n            },\n          })\n      },\n    })\n\n    const root = nodeOps.createElement('div')\n    render(h(Parent), root)\n\n    changeChildMsg(true)\n    expect(msg.value).toBe(true)\n\n    changeChildMsg(true)\n    expect(msg.value).toBe(null)\n  })\n})\n"
  },
  {
    "path": "packages/runtime-core/__tests__/helpers/useTemplateRef.spec.ts",
    "content": "import {\n  type ShallowRef,\n  h,\n  nextTick,\n  nodeOps,\n  onMounted,\n  ref,\n  render,\n  useTemplateRef,\n} from '@vue/runtime-test'\n\ndescribe('useTemplateRef', () => {\n  test('should work', () => {\n    let tRef\n    const key = 'refKey'\n    const Comp = {\n      setup() {\n        tRef = useTemplateRef(key)\n      },\n      render() {\n        return h('div', { ref: key })\n      },\n    }\n    const root = nodeOps.createElement('div')\n    render(h(Comp), root)\n    expect(tRef!.value).toBe(root.children[0])\n  })\n\n  test('should be readonly', () => {\n    let tRef\n    const key = 'refKey'\n    const Comp = {\n      setup() {\n        tRef = useTemplateRef(key)\n      },\n      render() {\n        return h('div', { ref: key })\n      },\n    }\n    const root = nodeOps.createElement('div')\n    render(h(Comp), root)\n\n    // @ts-expect-error\n    tRef.value = 123\n\n    expect(tRef!.value).toBe(root.children[0])\n    expect('target is readonly').toHaveBeenWarned()\n  })\n\n  test('should be updated for ref of dynamic strings', async () => {\n    let t1, t2\n    const key = ref('t1')\n    const Comp = {\n      setup() {\n        t1 = useTemplateRef<HTMLAnchorElement>('t1')\n        t2 = useTemplateRef('t2')\n      },\n      render() {\n        return h('div', { ref: key.value })\n      },\n    }\n    const root = nodeOps.createElement('div')\n    render(h(Comp), root)\n\n    expect(t1!.value).toBe(root.children[0])\n    expect(t2!.value).toBe(null)\n\n    key.value = 't2'\n    await nextTick()\n    expect(t2!.value).toBe(root.children[0])\n    expect(t1!.value).toBe(null)\n  })\n\n  test('should warn on duplicate useTemplateRef', () => {\n    const root = nodeOps.createElement('div')\n    render(\n      h(() => {\n        useTemplateRef('foo')\n        useTemplateRef('foo')\n        return ''\n      }),\n      root,\n    )\n\n    expect(`useTemplateRef('foo') already exists.`).toHaveBeenWarned()\n  })\n\n  // #11795\n  test('should not attempt to set when variable name is same as key', () => {\n    let tRef: ShallowRef\n    const key = 'refKey'\n    const Comp = {\n      setup() {\n        tRef = useTemplateRef('_')\n        return {\n          [key]: tRef,\n        }\n      },\n      render() {\n        return h('div', { ref: key })\n      },\n    }\n    const root = nodeOps.createElement('div')\n    render(h(Comp), root)\n\n    expect('target is readonly').not.toHaveBeenWarned()\n    expect(tRef!.value).toBe(null)\n  })\n\n  test('should work when used with direct ref value with ref_key', () => {\n    let tRef: ShallowRef\n    const key = 'refKey'\n    const Comp = {\n      setup() {\n        tRef = useTemplateRef(key)\n        return () => h('div', { ref: tRef, ref_key: key })\n      },\n    }\n    const root = nodeOps.createElement('div')\n    render(h(Comp), root)\n\n    expect('target is readonly').not.toHaveBeenWarned()\n    expect(tRef!.value).toBe(root.children[0])\n  })\n\n  test('should work when used with direct ref value with ref_key and ref_for', () => {\n    let tRef: ShallowRef\n    const key = 'refKey'\n    const Comp = {\n      setup() {\n        tRef = useTemplateRef(key)\n      },\n      render() {\n        return h(\n          'div',\n          [1, 2, 3].map(x =>\n            h('span', { ref: tRef, ref_key: key, ref_for: true }, x.toString()),\n          ),\n        )\n      },\n    }\n    const root = nodeOps.createElement('div')\n    render(h(Comp), root)\n\n    expect('target is readonly').not.toHaveBeenWarned()\n    expect(tRef!.value).toHaveLength(3)\n  })\n\n  test('should work when used with direct ref value with ref_key and dynamic value', async () => {\n    const refMode = ref('h1-ref')\n\n    let tRef: ShallowRef\n    const key = 'refKey'\n\n    const Comp = {\n      setup() {\n        tRef = useTemplateRef(key)\n      },\n      render() {\n        switch (refMode.value) {\n          case 'h1-ref':\n            return h('h1', { ref: tRef, ref_key: key })\n          case 'h2-ref':\n            return h('h2', { ref: tRef, ref_key: key })\n          case 'no-ref':\n            return h('span')\n          case 'nothing':\n            return null\n        }\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(Comp), root)\n\n    expect(tRef!.value.tag).toBe('h1')\n\n    refMode.value = 'h2-ref'\n    await nextTick()\n    expect(tRef!.value.tag).toBe('h2')\n\n    refMode.value = 'no-ref'\n    await nextTick()\n    expect(tRef!.value).toBeNull()\n\n    refMode.value = 'nothing'\n    await nextTick()\n    expect(tRef!.value).toBeNull()\n\n    expect('target is readonly').not.toHaveBeenWarned()\n  })\n\n  test('should work when used with dynamic direct refs and ref_keys', async () => {\n    const refKey = ref('foo')\n\n    let tRefs: Record<string, ShallowRef>\n\n    const Comp = {\n      setup() {\n        tRefs = {\n          foo: useTemplateRef('foo'),\n          bar: useTemplateRef('bar'),\n        }\n      },\n      render() {\n        return h('div', { ref: tRefs[refKey.value], ref_key: refKey.value })\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(Comp), root)\n\n    expect(tRefs!['foo'].value).toBe(root.children[0])\n    expect(tRefs!['bar'].value).toBeNull()\n\n    refKey.value = 'bar'\n    await nextTick()\n    expect(tRefs!['foo'].value).toBeNull()\n    expect(tRefs!['bar'].value).toBe(root.children[0])\n\n    expect('target is readonly').not.toHaveBeenWarned()\n  })\n\n  test('should not work when used with direct ref value without ref_key (in dev mode)', () => {\n    let tRef: ShallowRef\n    const Comp = {\n      setup() {\n        tRef = useTemplateRef('refKey')\n        return () => h('div', { ref: tRef })\n      },\n    }\n    const root = nodeOps.createElement('div')\n    render(h(Comp), root)\n\n    expect(tRef!.value).toBeNull()\n  })\n\n  test('should work when used as direct ref value (compiled in prod mode)', () => {\n    __DEV__ = false\n    try {\n      let foo: ShallowRef\n      const Comp = {\n        setup() {\n          foo = useTemplateRef('foo')\n          return () => h('div', { ref: foo })\n        },\n      }\n      const root = nodeOps.createElement('div')\n      render(h(Comp), root)\n\n      expect('target is readonly').not.toHaveBeenWarned()\n      expect(foo!.value).toBe(root.children[0])\n    } finally {\n      __DEV__ = true\n    }\n  })\n\n  // #12749\n  test(`don't update setup ref for useTemplateRef key`, () => {\n    let foo: ShallowRef\n    const Comp = {\n      setup() {\n        foo = useTemplateRef('bar')\n        const bar = ref(null)\n        onMounted(() => {\n          expect(bar.value).toBe(null)\n        })\n        return { bar }\n      },\n      render() {\n        return h('div', { ref: 'bar' })\n      },\n    }\n    const root = nodeOps.createElement('div')\n    render(h(Comp), root)\n    expect(foo!.value).toBe(root.children[0])\n  })\n\n  test(`don't update setup ref for useTemplateRef key (compiled in prod mode)`, () => {\n    __DEV__ = false\n    try {\n      let foo: ReturnType<typeof ref>\n      let fooRef: ShallowRef\n      const Comp = {\n        setup() {\n          foo = ref('hello')\n          fooRef = useTemplateRef('foo')\n          return { foo }\n        },\n        render() {\n          return h('input', { ref: foo, ref_key: 'foo' })\n        },\n      }\n      const root = nodeOps.createElement('div')\n      render(h(Comp), root)\n\n      expect(foo!.value).toBe('hello')\n      expect(fooRef!.value).toBe(root.children[0])\n    } finally {\n      __DEV__ = true\n    }\n  })\n\n  test('should work when used as direct ref value with ref_key and ref_for (compiled in prod mode)', () => {\n    __DEV__ = false\n    try {\n      let tRef: ShallowRef\n      const key = 'refKey'\n      const Comp = {\n        setup() {\n          tRef = useTemplateRef(key)\n        },\n        render() {\n          return h(\n            'div',\n            [1, 2, 3].map(x =>\n              h(\n                'span',\n                { ref: tRef, ref_key: key, ref_for: true },\n                x.toString(),\n              ),\n            ),\n          )\n        },\n      }\n\n      const root = nodeOps.createElement('div')\n      render(h(Comp), root)\n\n      expect('target is readonly').not.toHaveBeenWarned()\n      expect(tRef!.value).toHaveLength(3)\n    } finally {\n      __DEV__ = true\n    }\n  })\n\n  test('should work when used as direct ref value with ref_for but without ref_key (compiled in prod mode)', () => {\n    __DEV__ = false\n    try {\n      let tRef: ShallowRef\n      const Comp = {\n        setup() {\n          tRef = useTemplateRef('refKey')\n        },\n        render() {\n          return h(\n            'div',\n            [1, 2, 3].map(x =>\n              h('span', { ref: tRef, ref_for: true }, x.toString()),\n            ),\n          )\n        },\n      }\n\n      const root = nodeOps.createElement('div')\n      render(h(Comp), root)\n\n      expect('target is readonly').not.toHaveBeenWarned()\n      expect(tRef!.value).toHaveLength(3)\n    } finally {\n      __DEV__ = true\n    }\n  })\n})\n"
  },
  {
    "path": "packages/runtime-core/__tests__/helpers/withMemo.spec.ts",
    "content": "/**\n * @vitest-environment jsdom\n */\n\n// since v-memo really is a compiler + runtime combo feature, we are performing\n// more of an integration test here.\nimport { type ComponentOptions, createApp, nextTick } from 'vue'\n\ndescribe('v-memo', () => {\n  function mount(options: ComponentOptions): [HTMLElement, any] {\n    const app = createApp(options)\n    const el = document.createElement('div')\n    const vm = app.mount(el)\n    return [el, vm]\n  }\n\n  test('on with external array', async () => {\n    const [el, vm] = mount({\n      template: `<div v-memo=\"arr\">{{ arr[0] }} {{ arr[1] }} {{arr[2] ?? '_' }} ({{c}})</div>{{c}}`,\n      data: () => ({ arr: [0, 0], c: 0 }),\n    })\n    expect(el.innerHTML).toBe(`<div>0 0 _ (0)</div>0`)\n\n    let [x, y, z] = [0, 1, 2]\n\n    // change at index x - should update\n    vm.arr[x]++\n    vm.c++\n    await nextTick()\n    expect(el.innerHTML).toBe(`<div>1 0 _ (1)</div>1`)\n\n    // change at index y - should update\n    vm.arr[y]++\n    vm.c++\n    await nextTick()\n    expect(el.innerHTML).toBe(`<div>1 1 _ (2)</div>2`)\n\n    // noop change - should NOT update\n    vm.arr[x] = vm.arr[0]\n    vm.arr[y] = vm.arr[1]\n    vm.c++\n    await nextTick()\n    expect(el.innerHTML).toBe(`<div>1 1 _ (2)</div>3`)\n\n    // add item  3rd item - should update\n    vm.arr[z] = 0\n    vm.c++\n    await nextTick()\n    expect(el.innerHTML).toBe(`<div>1 1 0 (4)</div>4`)\n\n    // remove 3rd item - should update\n    vm.arr = vm.arr.slice(0, vm.arr.length - 1)\n    vm.c++\n    await nextTick()\n    expect(el.innerHTML).toBe(`<div>1 1 _ (5)</div>5`)\n  })\n\n  test('on normal element', async () => {\n    const [el, vm] = mount({\n      template: `<div v-memo=\"[x]\">{{ x }} {{ y }}</div>`,\n      data: () => ({ x: 0, y: 0 }),\n    })\n    expect(el.innerHTML).toBe(`<div>0 0</div>`)\n\n    vm.x++\n    // should update\n    await nextTick()\n    expect(el.innerHTML).toBe(`<div>1 0</div>`)\n\n    vm.y++\n    // should not update\n    await nextTick()\n    expect(el.innerHTML).toBe(`<div>1 0</div>`)\n\n    vm.x++\n    // should update\n    await nextTick()\n    expect(el.innerHTML).toBe(`<div>2 1</div>`)\n  })\n\n  test('on component', async () => {\n    const [el, vm] = mount({\n      template: `<Comp v-memo=\"[x]\" :x=\"x\" :y=\"y\"></Comp>`,\n      data: () => ({ x: 0, y: 0 }),\n      components: {\n        Comp: {\n          props: ['x', 'y'],\n          template: `<div>{{x}} {{y}}</div>`,\n        },\n      },\n    })\n    expect(el.innerHTML).toBe(`<div>0 0</div>`)\n\n    vm.x++\n    // should update\n    await nextTick()\n    expect(el.innerHTML).toBe(`<div>1 0</div>`)\n\n    vm.y++\n    // should not update\n    await nextTick()\n    expect(el.innerHTML).toBe(`<div>1 0</div>`)\n\n    vm.x++\n    // should update\n    await nextTick()\n    expect(el.innerHTML).toBe(`<div>2 1</div>`)\n  })\n\n  test('on v-if', async () => {\n    const [el, vm] = mount({\n      template: `<div v-if=\"ok\" v-memo=\"[x]\">{{ x }} {{ y }}</div>\n        <div v-else v-memo=\"[y]\">{{ y }} {{ x }}</div>`,\n      data: () => ({ ok: true, x: 0, y: 0 }),\n    })\n    expect(el.innerHTML).toBe(`<div>0 0</div>`)\n\n    vm.x++\n    // should update\n    await nextTick()\n    expect(el.innerHTML).toBe(`<div>1 0</div>`)\n\n    vm.y++\n    // should not update\n    await nextTick()\n    expect(el.innerHTML).toBe(`<div>1 0</div>`)\n\n    vm.x++\n    // should update\n    await nextTick()\n    expect(el.innerHTML).toBe(`<div>2 1</div>`)\n\n    vm.ok = false\n    await nextTick()\n    expect(el.innerHTML).toBe(`<div>1 2</div>`)\n\n    vm.y++\n    // should update\n    await nextTick()\n    expect(el.innerHTML).toBe(`<div>2 2</div>`)\n\n    vm.x++\n    // should not update\n    await nextTick()\n    expect(el.innerHTML).toBe(`<div>2 2</div>`)\n\n    vm.y++\n    // should update\n    await nextTick()\n    expect(el.innerHTML).toBe(`<div>3 3</div>`)\n\n    vm.ok = true\n    await nextTick()\n    vm.ok = false\n    await nextTick()\n    expect(el.innerHTML).toBe(`<div>3 3</div>`)\n\n    vm.y++\n    // should update\n    await nextTick()\n    expect(el.innerHTML).toBe(`<div>4 3</div>`)\n  })\n\n  test('on v-for', async () => {\n    const [el, vm] = mount({\n      template:\n        `<div v-for=\"{ x } in list\" :key=\"x\" v-memo=\"[x, x === y]\">` +\n        `{{ x }} {{ x === y ? 'yes' : 'no' }} {{ z }}` +\n        `</div>`,\n      data: () => ({\n        list: [{ x: 1 }, { x: 2 }, { x: 3 }],\n        y: 1,\n        z: 'z',\n      }),\n    })\n    expect(el.innerHTML).toBe(\n      `<div>1 yes z</div><div>2 no z</div><div>3 no z</div>`,\n    )\n\n    vm.y = 2\n    await nextTick()\n    expect(el.innerHTML).toBe(\n      `<div>1 no z</div><div>2 yes z</div><div>3 no z</div>`,\n    )\n\n    vm.list[0].x = 4\n    await nextTick()\n    expect(el.innerHTML).toBe(\n      `<div>4 no z</div><div>2 yes z</div><div>3 no z</div>`,\n    )\n\n    vm.list[0].x = 5\n    vm.y = 5\n    await nextTick()\n    expect(el.innerHTML).toBe(\n      `<div>5 yes z</div><div>2 no z</div><div>3 no z</div>`,\n    )\n\n    vm.z = 'zz'\n    await nextTick()\n    // should not update\n    expect(el.innerHTML).toBe(\n      `<div>5 yes z</div><div>2 no z</div><div>3 no z</div>`,\n    )\n  })\n\n  test('on v-for /w constant expression ', async () => {\n    const [el, vm] = mount({\n      template: `<div v-for=\"item in 3\"  v-memo=\"[count < 2 ? true : count]\">\n          {{count}}\n        </div>`,\n      data: () => ({\n        count: 0,\n      }),\n    })\n    expect(el.innerHTML).toBe(`<div>0</div><div>0</div><div>0</div>`)\n\n    vm.count = 1\n    await nextTick()\n    // should not update\n    expect(el.innerHTML).toBe(`<div>0</div><div>0</div><div>0</div>`)\n\n    vm.count = 2\n    await nextTick()\n    // should update\n    expect(el.innerHTML).toBe(`<div>2</div><div>2</div><div>2</div>`)\n  })\n\n  test('v-memo dependency is NaN should be equal', async () => {\n    const [el, vm] = mount({\n      template: `<div v-memo=\"[x]\">{{ y }}</div>`,\n      data: () => ({ x: NaN, y: 0 }),\n    })\n    expect(el.innerHTML).toBe(`<div>0</div>`)\n\n    vm.y++\n    // should not update\n    await nextTick()\n    expect(el.innerHTML).toBe(`<div>0</div>`)\n  })\n})\n"
  },
  {
    "path": "packages/runtime-core/__tests__/hmr.spec.ts",
    "content": "import type { HMRRuntime } from '../src/hmr'\nimport '../src/hmr'\nimport type { ComponentOptions, InternalRenderFunction } from '../src/component'\nimport {\n  type TestElement,\n  h,\n  nextTick,\n  nodeOps,\n  ref,\n  render,\n  serializeInner,\n  triggerEvent,\n} from '@vue/runtime-test'\nimport * as runtimeTest from '@vue/runtime-test'\nimport { createApp, registerRuntimeCompiler } from '@vue/runtime-test'\nimport { baseCompile } from '@vue/compiler-core'\n\ndeclare var __VUE_HMR_RUNTIME__: HMRRuntime\nconst { createRecord, rerender, reload } = __VUE_HMR_RUNTIME__\n\nregisterRuntimeCompiler(compileToFunction)\n\nfunction compileToFunction(template: string) {\n  const { code } = baseCompile(template, { hoistStatic: true, hmr: true })\n  const render = new Function('Vue', code)(\n    runtimeTest,\n  ) as InternalRenderFunction\n  render._rc = true // isRuntimeCompiled\n  return render\n}\n\nconst timeout = (n: number = 0) => new Promise(r => setTimeout(r, n))\n\ndescribe('hot module replacement', () => {\n  test('inject global runtime', () => {\n    expect(createRecord).toBeDefined()\n    expect(rerender).toBeDefined()\n    expect(reload).toBeDefined()\n  })\n\n  test('createRecord', () => {\n    expect(createRecord('test1', {})).toBe(true)\n    // if id has already been created, should return false\n    expect(createRecord('test1', {})).toBe(false)\n  })\n\n  test('rerender', async () => {\n    const root = nodeOps.createElement('div')\n    const parentId = 'test2-parent'\n    const childId = 'test2-child'\n\n    const Child: ComponentOptions = {\n      __hmrId: childId,\n      render: compileToFunction(`<div><slot/></div>`),\n    }\n    createRecord(childId, Child)\n\n    const Parent: ComponentOptions = {\n      __hmrId: parentId,\n      data() {\n        return { count: 0 }\n      },\n      components: { Child },\n      render: compileToFunction(\n        `<div @click=\"count++\">{{ count }}<Child>{{ count }}</Child></div>`,\n      ),\n    }\n    createRecord(parentId, Parent)\n\n    render(h(Parent), root)\n    expect(serializeInner(root)).toBe(`<div>0<div>0</div></div>`)\n\n    // Perform some state change. This change should be preserved after the\n    // re-render!\n    triggerEvent(root.children[0] as TestElement, 'click')\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<div>1<div>1</div></div>`)\n\n    // // Update text while preserving state\n    rerender(\n      parentId,\n      compileToFunction(\n        `<div @click=\"count++\">{{ count }}!<Child>{{ count }}</Child></div>`,\n      ),\n    )\n    expect(serializeInner(root)).toBe(`<div>1!<div>1</div></div>`)\n\n    // Should force child update on slot content change\n    rerender(\n      parentId,\n      compileToFunction(\n        `<div @click=\"count++\">{{ count }}!<Child>{{ count }}!</Child></div>`,\n      ),\n    )\n    expect(serializeInner(root)).toBe(`<div>1!<div>1!</div></div>`)\n\n    // Should force update element children despite block optimization\n    rerender(\n      parentId,\n      compileToFunction(\n        `<div @click=\"count++\">{{ count }}<span>{{ count }}</span>\n        <Child>{{ count }}!</Child>\n      </div>`,\n      ),\n    )\n    expect(serializeInner(root)).toBe(`<div>1<span>1</span><div>1!</div></div>`)\n\n    // Should force update child slot elements\n    rerender(\n      parentId,\n      compileToFunction(\n        `<div @click=\"count++\">\n        <Child><span>{{ count }}</span></Child>\n      </div>`,\n      ),\n    )\n    expect(serializeInner(root)).toBe(`<div><div><span>1</span></div></div>`)\n  })\n\n  test('reload', async () => {\n    const root = nodeOps.createElement('div')\n    const childId = 'test3-child'\n    const unmountSpy = vi.fn()\n    const mountSpy = vi.fn()\n\n    const Child: ComponentOptions = {\n      __hmrId: childId,\n      data() {\n        return { count: 0 }\n      },\n      unmounted: unmountSpy,\n      render: compileToFunction(`<div @click=\"count++\">{{ count }}</div>`),\n    }\n    createRecord(childId, Child)\n\n    const Parent: ComponentOptions = {\n      render: () => h(Child),\n    }\n\n    render(h(Parent), root)\n    expect(serializeInner(root)).toBe(`<div>0</div>`)\n\n    reload(childId, {\n      __hmrId: childId,\n      data() {\n        return { count: 1 }\n      },\n      mounted: mountSpy,\n      render: compileToFunction(`<div @click=\"count++\">{{ count }}</div>`),\n    })\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<div>1</div>`)\n    expect(unmountSpy).toHaveBeenCalledTimes(1)\n    expect(mountSpy).toHaveBeenCalledTimes(1)\n  })\n\n  // #7042\n  test('reload KeepAlive slot', async () => {\n    const root = nodeOps.createElement('div')\n    const childId = 'test-child-keep-alive'\n    const unmountSpy = vi.fn()\n    const mountSpy = vi.fn()\n    const activeSpy = vi.fn()\n    const deactiveSpy = vi.fn()\n\n    const Child: ComponentOptions = {\n      __hmrId: childId,\n      data() {\n        return { count: 0 }\n      },\n      unmounted: unmountSpy,\n      render: compileToFunction(`<div>{{ count }}</div>`),\n    }\n    createRecord(childId, Child)\n\n    const Parent: ComponentOptions = {\n      components: { Child },\n      data() {\n        return { toggle: true }\n      },\n      render: compileToFunction(\n        `<button @click=\"toggle = !toggle\" />\n        <KeepAlive><Child v-if=\"toggle\" /></KeepAlive>`,\n      ),\n    }\n\n    render(h(Parent), root)\n    expect(serializeInner(root)).toBe(`<button></button><div>0</div>`)\n\n    reload(childId, {\n      __hmrId: childId,\n      data() {\n        return { count: 1 }\n      },\n      mounted: mountSpy,\n      unmounted: unmountSpy,\n      activated: activeSpy,\n      deactivated: deactiveSpy,\n      render: compileToFunction(`<div>{{ count }}</div>`),\n    })\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<button></button><div>1</div>`)\n    expect(unmountSpy).toHaveBeenCalledTimes(1)\n    expect(mountSpy).toHaveBeenCalledTimes(1)\n    expect(activeSpy).toHaveBeenCalledTimes(1)\n    expect(deactiveSpy).toHaveBeenCalledTimes(0)\n\n    // should not unmount when toggling\n    triggerEvent(root.children[1] as TestElement, 'click')\n    await nextTick()\n    expect(unmountSpy).toHaveBeenCalledTimes(1)\n    expect(mountSpy).toHaveBeenCalledTimes(1)\n    expect(activeSpy).toHaveBeenCalledTimes(1)\n    expect(deactiveSpy).toHaveBeenCalledTimes(1)\n\n    // should not mount when toggling\n    triggerEvent(root.children[1] as TestElement, 'click')\n    await nextTick()\n    expect(unmountSpy).toHaveBeenCalledTimes(1)\n    expect(mountSpy).toHaveBeenCalledTimes(1)\n    expect(activeSpy).toHaveBeenCalledTimes(2)\n    expect(deactiveSpy).toHaveBeenCalledTimes(1)\n  })\n\n  // #7121\n  test('reload KeepAlive slot in Transition', async () => {\n    const root = nodeOps.createElement('div')\n    const childId = 'test-transition-keep-alive-reload'\n    const unmountSpy = vi.fn()\n    const mountSpy = vi.fn()\n    const activeSpy = vi.fn()\n    const deactiveSpy = vi.fn()\n\n    const Child: ComponentOptions = {\n      __hmrId: childId,\n      data() {\n        return { count: 0 }\n      },\n      unmounted: unmountSpy,\n      render: compileToFunction(`<div>{{ count }}</div>`),\n    }\n    createRecord(childId, Child)\n\n    const Parent: ComponentOptions = {\n      components: { Child },\n      data() {\n        return { toggle: true }\n      },\n      render: compileToFunction(\n        `<button @click=\"toggle = !toggle\" />\n        <BaseTransition>\n          <KeepAlive><Child v-if=\"toggle\" /></KeepAlive>\n        </BaseTransition>`,\n      ),\n    }\n\n    render(h(Parent), root)\n    expect(serializeInner(root)).toBe(`<button></button><div>0</div>`)\n\n    reload(childId, {\n      __hmrId: childId,\n      data() {\n        return { count: 1 }\n      },\n      mounted: mountSpy,\n      unmounted: unmountSpy,\n      activated: activeSpy,\n      deactivated: deactiveSpy,\n      render: compileToFunction(`<div>{{ count }}</div>`),\n    })\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<button></button><div>1</div>`)\n    expect(unmountSpy).toHaveBeenCalledTimes(1)\n    expect(mountSpy).toHaveBeenCalledTimes(1)\n    expect(activeSpy).toHaveBeenCalledTimes(1)\n    expect(deactiveSpy).toHaveBeenCalledTimes(0)\n\n    // should not unmount when toggling\n    triggerEvent(root.children[1] as TestElement, 'click')\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<button></button><!--v-if-->`)\n    expect(unmountSpy).toHaveBeenCalledTimes(1)\n    expect(mountSpy).toHaveBeenCalledTimes(1)\n    expect(activeSpy).toHaveBeenCalledTimes(1)\n    expect(deactiveSpy).toHaveBeenCalledTimes(1)\n\n    // should not mount when toggling\n    triggerEvent(root.children[1] as TestElement, 'click')\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<button></button><div>1</div>`)\n    expect(unmountSpy).toHaveBeenCalledTimes(1)\n    expect(mountSpy).toHaveBeenCalledTimes(1)\n    expect(activeSpy).toHaveBeenCalledTimes(2)\n    expect(deactiveSpy).toHaveBeenCalledTimes(1)\n  })\n\n  test('reload KeepAlive slot in Transition with out-in', async () => {\n    const root = nodeOps.createElement('div')\n    const childId = 'test-transition-keep-alive-reload-with-out-in'\n    const unmountSpy = vi.fn()\n    const mountSpy = vi.fn()\n    const activeSpy = vi.fn()\n    const deactiveSpy = vi.fn()\n\n    const Child: ComponentOptions = {\n      __hmrId: childId,\n      name: 'original',\n      data() {\n        return { count: 0 }\n      },\n      unmounted: unmountSpy,\n      render: compileToFunction(`<div>{{ count }}</div>`),\n    }\n    createRecord(childId, Child)\n\n    const Parent: ComponentOptions = {\n      components: { Child },\n      data() {\n        return { toggle: true }\n      },\n      methods: {\n        // @ts-expect-error\n        onLeave(_, done) {\n          setTimeout(done, 0)\n        },\n      },\n      render: compileToFunction(\n        `<button @click=\"toggle = !toggle\" />\n        <BaseTransition mode=\"out-in\" @leave=\"onLeave\">\n          <KeepAlive><Child v-if=\"toggle\" /></KeepAlive>\n        </BaseTransition>`,\n      ),\n    }\n\n    render(h(Parent), root)\n    expect(serializeInner(root)).toBe(`<button></button><div>0</div>`)\n\n    reload(childId, {\n      __hmrId: childId,\n      name: 'updated',\n      data() {\n        return { count: 1 }\n      },\n      mounted: mountSpy,\n      unmounted: unmountSpy,\n      activated: activeSpy,\n      deactivated: deactiveSpy,\n      render: compileToFunction(`<div>{{ count }}</div>`),\n    })\n    await nextTick()\n    await new Promise(r => setTimeout(r, 0))\n    expect(serializeInner(root)).toBe(`<button></button><div>1</div>`)\n    expect(unmountSpy).toHaveBeenCalledTimes(1)\n    expect(mountSpy).toHaveBeenCalledTimes(1)\n    expect(activeSpy).toHaveBeenCalledTimes(1)\n    expect(deactiveSpy).toHaveBeenCalledTimes(0)\n\n    // should not unmount when toggling\n    triggerEvent(root.children[1] as TestElement, 'click')\n    await nextTick()\n    await new Promise(r => setTimeout(r, 0))\n    expect(serializeInner(root)).toBe(`<button></button><!--v-if-->`)\n    expect(unmountSpy).toHaveBeenCalledTimes(1)\n    expect(mountSpy).toHaveBeenCalledTimes(1)\n    expect(activeSpy).toHaveBeenCalledTimes(1)\n    expect(deactiveSpy).toHaveBeenCalledTimes(1)\n\n    // should not mount when toggling\n    triggerEvent(root.children[1] as TestElement, 'click')\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<button></button><div>1</div>`)\n    expect(unmountSpy).toHaveBeenCalledTimes(1)\n    expect(mountSpy).toHaveBeenCalledTimes(1)\n    expect(activeSpy).toHaveBeenCalledTimes(2)\n    expect(deactiveSpy).toHaveBeenCalledTimes(1)\n  })\n\n  test('reload class component', async () => {\n    const root = nodeOps.createElement('div')\n    const childId = 'test4-child'\n    const unmountSpy = vi.fn()\n    const mountSpy = vi.fn()\n\n    class Child {\n      static __vccOpts: ComponentOptions = {\n        __hmrId: childId,\n        data() {\n          return { count: 0 }\n        },\n        unmounted: unmountSpy,\n        render: compileToFunction(`<div @click=\"count++\">{{ count }}</div>`),\n      }\n    }\n    createRecord(childId, Child)\n\n    const Parent: ComponentOptions = {\n      render: () => h(Child),\n    }\n\n    render(h(Parent), root)\n    expect(serializeInner(root)).toBe(`<div>0</div>`)\n\n    class UpdatedChild {\n      static __vccOpts: ComponentOptions = {\n        __hmrId: childId,\n        data() {\n          return { count: 1 }\n        },\n        mounted: mountSpy,\n        render: compileToFunction(`<div @click=\"count++\">{{ count }}</div>`),\n      }\n    }\n\n    reload(childId, UpdatedChild)\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<div>1</div>`)\n    expect(unmountSpy).toHaveBeenCalledTimes(1)\n    expect(mountSpy).toHaveBeenCalledTimes(1)\n  })\n\n  // #6930\n  test('reload: avoid infinite recursion', async () => {\n    const root = nodeOps.createElement('div')\n    const childId = 'test-child-6930'\n    const unmountSpy = vi.fn()\n    const mountSpy = vi.fn()\n\n    const Child: ComponentOptions = {\n      __hmrId: childId,\n      data() {\n        return { count: 0 }\n      },\n      expose: ['count'],\n      unmounted: unmountSpy,\n      render: compileToFunction(`<div @click=\"count++\">{{ count }}</div>`),\n    }\n    createRecord(childId, Child)\n\n    const Parent: ComponentOptions = {\n      setup() {\n        const com1 = ref()\n        const changeRef1 = (value: any) => (com1.value = value)\n\n        const com2 = ref()\n        const changeRef2 = (value: any) => (com2.value = value)\n\n        return () => [\n          h(Child, { ref: changeRef1 }),\n          h(Child, { ref: changeRef2 }),\n          com1.value?.count,\n        ]\n      },\n    }\n\n    render(h(Parent), root)\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<div>0</div><div>0</div>0`)\n\n    reload(childId, {\n      __hmrId: childId,\n      data() {\n        return { count: 1 }\n      },\n      mounted: mountSpy,\n      render: compileToFunction(`<div @click=\"count++\">{{ count }}</div>`),\n    })\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<div>1</div><div>1</div>1`)\n    expect(unmountSpy).toHaveBeenCalledTimes(2)\n    expect(mountSpy).toHaveBeenCalledTimes(2)\n  })\n\n  // #1156 - static nodes should retain DOM element reference across updates\n  // when HMR is active\n  test('static el reference', async () => {\n    const root = nodeOps.createElement('div')\n    const id = 'test-static-el'\n\n    const template = `<div>\n    <div>{{ count }}</div>\n    <button @click=\"count++\">++</button>\n  </div>`\n\n    const Comp: ComponentOptions = {\n      __hmrId: id,\n      data() {\n        return { count: 0 }\n      },\n      render: compileToFunction(template),\n    }\n    createRecord(id, Comp)\n\n    render(h(Comp), root)\n    expect(serializeInner(root)).toBe(\n      `<div><div>0</div><button>++</button></div>`,\n    )\n\n    // 1. click to trigger update\n    triggerEvent((root as any).children[0].children[1], 'click')\n    await nextTick()\n    expect(serializeInner(root)).toBe(\n      `<div><div>1</div><button>++</button></div>`,\n    )\n\n    // 2. trigger HMR\n    rerender(\n      id,\n      compileToFunction(template.replace(`<button`, `<button class=\"foo\"`)),\n    )\n    expect(serializeInner(root)).toBe(\n      `<div><div>1</div><button class=\"foo\">++</button></div>`,\n    )\n  })\n\n  // #1157 - component should force full props update when HMR is active\n  test('force update child component w/ static props', () => {\n    const root = nodeOps.createElement('div')\n    const parentId = 'test-force-props-parent'\n    const childId = 'test-force-props-child'\n\n    const Child: ComponentOptions = {\n      __hmrId: childId,\n      props: {\n        msg: String,\n      },\n      render: compileToFunction(`<div>{{ msg }}</div>`),\n    }\n    createRecord(childId, Child)\n\n    const Parent: ComponentOptions = {\n      __hmrId: parentId,\n      components: { Child },\n      render: compileToFunction(`<Child msg=\"foo\" />`),\n    }\n    createRecord(parentId, Parent)\n\n    render(h(Parent), root)\n    expect(serializeInner(root)).toBe(`<div>foo</div>`)\n\n    rerender(parentId, compileToFunction(`<Child msg=\"bar\" />`))\n    expect(serializeInner(root)).toBe(`<div>bar</div>`)\n  })\n\n  // #1305 - component should remove class\n  test('remove static class from parent', () => {\n    const root = nodeOps.createElement('div')\n    const parentId = 'test-force-class-parent'\n    const childId = 'test-force-class-child'\n\n    const Child: ComponentOptions = {\n      __hmrId: childId,\n      render: compileToFunction(`<div>child</div>`),\n    }\n    createRecord(childId, Child)\n\n    const Parent: ComponentOptions = {\n      __hmrId: parentId,\n      components: { Child },\n      render: compileToFunction(`<Child class=\"test\" />`),\n    }\n    createRecord(parentId, Parent)\n\n    render(h(Parent), root)\n    expect(serializeInner(root)).toBe(`<div class=\"test\">child</div>`)\n\n    rerender(parentId, compileToFunction(`<Child/>`))\n    expect(serializeInner(root)).toBe(`<div>child</div>`)\n  })\n\n  test('rerender if any parent in the parent chain', () => {\n    const root = nodeOps.createElement('div')\n    const parent = 'test-force-props-parent-'\n    const childId = 'test-force-props-child'\n\n    const numberOfParents = 5\n\n    const Child: ComponentOptions = {\n      __hmrId: childId,\n      render: compileToFunction(`<div>child</div>`),\n    }\n    createRecord(childId, Child)\n\n    const components: ComponentOptions[] = []\n\n    for (let i = 0; i < numberOfParents; i++) {\n      const parentId = `${parent}${i}`\n      const parentComp: ComponentOptions = {\n        __hmrId: parentId,\n      }\n      components.push(parentComp)\n      if (i === 0) {\n        parentComp.render = compileToFunction(`<Child />`)\n        parentComp.components = {\n          Child,\n        }\n      } else {\n        parentComp.render = compileToFunction(`<Parent />`)\n        parentComp.components = {\n          Parent: components[i - 1],\n        }\n      }\n\n      createRecord(parentId, parentComp)\n    }\n\n    const last = components[components.length - 1]\n\n    render(h(last), root)\n    expect(serializeInner(root)).toBe(`<div>child</div>`)\n\n    rerender(last.__hmrId!, compileToFunction(`<Parent class=\"test\"/>`))\n    expect(serializeInner(root)).toBe(`<div class=\"test\">child</div>`)\n  })\n\n  // #3302\n  test('rerender with Teleport', () => {\n    const root = nodeOps.createElement('div')\n    const target = nodeOps.createElement('div')\n    const parentId = 'parent-teleport'\n\n    const Child: ComponentOptions = {\n      data() {\n        return {\n          // style is used to ensure that the div tag will be tracked by Teleport\n          style: {},\n          target,\n        }\n      },\n      render: compileToFunction(`\n        <teleport :to=\"target\">\n          <div :style=\"style\">\n            <slot/>\n          </div>\n        </teleport>\n      `),\n    }\n\n    const Parent: ComponentOptions = {\n      __hmrId: parentId,\n      components: { Child },\n      render: compileToFunction(`\n        <Child>\n          <template #default>\n            <div>1</div>\n          </template>\n        </Child>\n      `),\n    }\n    createRecord(parentId, Parent)\n\n    render(h(Parent), root)\n    expect(serializeInner(root)).toBe(\n      `<!--teleport start--><!--teleport end-->`,\n    )\n    expect(serializeInner(target)).toBe(`<div style={}><div>1</div></div>`)\n\n    rerender(\n      parentId,\n      compileToFunction(`\n      <Child>\n        <template #default>\n          <div>1</div>\n          <div>2</div>\n        </template>\n      </Child>\n    `),\n    )\n    expect(serializeInner(root)).toBe(\n      `<!--teleport start--><!--teleport end-->`,\n    )\n    expect(serializeInner(target)).toBe(\n      `<div style={}><div>1</div><div>2</div></div>`,\n    )\n  })\n\n  // #4174\n  test('with global mixins', async () => {\n    const childId = 'hmr-global-mixin'\n    const createSpy1 = vi.fn()\n    const createSpy2 = vi.fn()\n\n    const Child: ComponentOptions = {\n      __hmrId: childId,\n      created: createSpy1,\n      render() {\n        return h('div')\n      },\n    }\n    createRecord(childId, Child)\n\n    const Parent: ComponentOptions = {\n      render: () => h(Child),\n    }\n\n    const app = createApp(Parent)\n    app.mixin({})\n\n    const root = nodeOps.createElement('div')\n    app.mount(root)\n    expect(createSpy1).toHaveBeenCalledTimes(1)\n    expect(createSpy2).toHaveBeenCalledTimes(0)\n\n    reload(childId, {\n      __hmrId: childId,\n      created: createSpy2,\n      render() {\n        return h('div')\n      },\n    })\n    await nextTick()\n    expect(createSpy1).toHaveBeenCalledTimes(1)\n    expect(createSpy2).toHaveBeenCalledTimes(1)\n  })\n\n  // #4757\n  test('rerender for component that has no active instance yet', () => {\n    const id = 'no-active-instance-rerender'\n    const Foo: ComponentOptions = {\n      __hmrId: id,\n      render: () => 'foo',\n    }\n\n    createRecord(id, Foo)\n    rerender(id, () => 'bar')\n\n    const root = nodeOps.createElement('div')\n    render(h(Foo), root)\n    expect(serializeInner(root)).toBe('bar')\n  })\n\n  test('reload for component that has no active instance yet', () => {\n    const id = 'no-active-instance-reload'\n    const Foo: ComponentOptions = {\n      __hmrId: id,\n      render: () => 'foo',\n    }\n\n    createRecord(id, Foo)\n    reload(id, {\n      __hmrId: id,\n      render: () => 'bar',\n    })\n\n    const root = nodeOps.createElement('div')\n    render(h(Foo), root)\n    expect(serializeInner(root)).toBe('bar')\n  })\n\n  // #7155 - force HMR on slots content update\n  test('force update slot content change', () => {\n    const root = nodeOps.createElement('div')\n    const parentId = 'test-force-computed-parent'\n    const childId = 'test-force-computed-child'\n\n    const Child: ComponentOptions = {\n      __hmrId: childId,\n      computed: {\n        slotContent() {\n          return this.$slots.default?.()\n        },\n      },\n      render: compileToFunction(`<component :is=\"() => slotContent\" />`),\n    }\n    createRecord(childId, Child)\n\n    const Parent: ComponentOptions = {\n      __hmrId: parentId,\n      components: { Child },\n      render: compileToFunction(`<Child>1</Child>`),\n    }\n    createRecord(parentId, Parent)\n\n    render(h(Parent), root)\n    expect(serializeInner(root)).toBe(`1`)\n\n    rerender(parentId, compileToFunction(`<Child>2</Child>`))\n    expect(serializeInner(root)).toBe(`2`)\n  })\n\n  // #6978, #7138, #7114\n  test('hoisted children array inside v-for', () => {\n    const root = nodeOps.createElement('div')\n    const appId = 'test-app-id'\n    const App: ComponentOptions = {\n      __hmrId: appId,\n      render: compileToFunction(\n        `<div v-for=\"item of 2\">\n          <div>1</div>\n        </div>\n        <p>2</p>\n        <p>3</p>`,\n      ),\n    }\n    createRecord(appId, App)\n\n    render(h(App), root)\n    expect(serializeInner(root)).toBe(\n      `<div><div>1</div></div><div><div>1</div></div><p>2</p><p>3</p>`,\n    )\n\n    // move the <p>3</p> into the <div>1</div>\n    rerender(\n      appId,\n      compileToFunction(\n        `<div v-for=\"item of 2\">\n          <div>1<p>3</p></div>\n        </div>\n        <p>2</p>`,\n      ),\n    )\n    expect(serializeInner(root)).toBe(\n      `<div><div>1<p>3</p></div></div><div><div>1<p>3</p></div></div><p>2</p>`,\n    )\n  })\n\n  // #11248\n  test('reload async component with multiple instances', async () => {\n    const root = nodeOps.createElement('div')\n    const childId = 'test-child-id'\n    const Child: ComponentOptions = {\n      __hmrId: childId,\n      data() {\n        return { count: 0 }\n      },\n      render: compileToFunction(`<div>{{ count }}</div>`),\n    }\n    const Comp = runtimeTest.defineAsyncComponent(() => Promise.resolve(Child))\n    const appId = 'test-app-id'\n    const App: ComponentOptions = {\n      __hmrId: appId,\n      render: () => [h(Comp), h(Comp)],\n    }\n    createRecord(appId, App)\n\n    render(h(App), root)\n\n    await timeout()\n\n    expect(serializeInner(root)).toBe(`<div>0</div><div>0</div>`)\n\n    // change count to 1\n    reload(childId, {\n      __hmrId: childId,\n      data() {\n        return { count: 1 }\n      },\n      render: compileToFunction(`<div>{{ count }}</div>`),\n    })\n\n    await timeout()\n\n    expect(serializeInner(root)).toBe(`<div>1</div><div>1</div>`)\n  })\n\n  test('reload async child wrapped in Suspense + KeepAlive', async () => {\n    const id = 'async-child-reload'\n    const AsyncChild: ComponentOptions = {\n      __hmrId: id,\n      async setup() {\n        await nextTick()\n        return () => 'foo'\n      },\n    }\n    createRecord(id, AsyncChild)\n\n    const appId = 'test-app-id'\n    const App: ComponentOptions = {\n      __hmrId: appId,\n      components: { AsyncChild },\n      render: compileToFunction(`\n        <div>\n        <Suspense>\n          <KeepAlive>\n            <AsyncChild />\n          </KeepAlive>\n        </Suspense>\n      </div>\n      `),\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(App), root)\n    expect(serializeInner(root)).toBe('<div><!----></div>')\n    await timeout()\n    expect(serializeInner(root)).toBe('<div>foo</div>')\n\n    reload(id, {\n      __hmrId: id,\n      async setup() {\n        await nextTick()\n        return () => 'bar'\n      },\n    })\n    await timeout()\n    expect(serializeInner(root)).toBe('<div>bar</div>')\n  })\n\n  test('multi reload child wrapped in Suspense + KeepAlive', async () => {\n    const id = 'test-child-reload-3'\n    const Child: ComponentOptions = {\n      __hmrId: id,\n      setup() {\n        const count = ref(0)\n        return { count }\n      },\n      render: compileToFunction(`<div>{{ count }}</div>`),\n    }\n    createRecord(id, Child)\n\n    const appId = 'test-app-id'\n    const App: ComponentOptions = {\n      __hmrId: appId,\n      components: { Child },\n      render: compileToFunction(`\n        <KeepAlive>\n          <Suspense>\n            <Child />\n          </Suspense>\n        </KeepAlive>\n      `),\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(App), root)\n    expect(serializeInner(root)).toBe('<div>0</div>')\n    await timeout()\n    reload(id, {\n      __hmrId: id,\n      setup() {\n        const count = ref(1)\n        return { count }\n      },\n      render: compileToFunction(`<div>{{ count }}</div>`),\n    })\n    await timeout()\n    expect(serializeInner(root)).toBe('<div>1</div>')\n\n    reload(id, {\n      __hmrId: id,\n      setup() {\n        const count = ref(2)\n        return { count }\n      },\n      render: compileToFunction(`<div>{{ count }}</div>`),\n    })\n    await timeout()\n    expect(serializeInner(root)).toBe('<div>2</div>')\n  })\n\n  test('rerender for nested component', () => {\n    const id = 'child-nested-rerender'\n    const Foo: ComponentOptions = {\n      __hmrId: id,\n      render() {\n        return this.$slots.default()\n      },\n    }\n    createRecord(id, Foo)\n\n    const parentId = 'parent-nested-rerender'\n    const Parent: ComponentOptions = {\n      __hmrId: parentId,\n      render() {\n        return h(Foo, null, {\n          default: () => this.$slots.default(),\n          _: 3 /* FORWARDED */,\n        })\n      },\n    }\n\n    const appId = 'app-nested-rerender'\n    const App: ComponentOptions = {\n      __hmrId: appId,\n      render: () =>\n        h(Parent, null, {\n          default: () => [\n            h(Foo, null, {\n              default: () => ['foo'],\n            }),\n          ],\n        }),\n    }\n    createRecord(parentId, App)\n\n    const root = nodeOps.createElement('div')\n    render(h(App), root)\n    expect(serializeInner(root)).toBe('foo')\n\n    rerender(id, () => 'bar')\n    expect(serializeInner(root)).toBe('bar')\n  })\n\n  // https://github.com/vitejs/vite-plugin-vue/issues/599\n  // Both Outer and Inner are reloaded when './server.js' changes\n  test('reload nested components from single update', async () => {\n    const innerId = 'nested-reload-inner'\n    const outerId = 'nested-reload-outer'\n\n    let Inner = {\n      __hmrId: innerId,\n      render() {\n        return h('div', 'foo')\n      },\n    }\n    let Outer = {\n      __hmrId: outerId,\n      render() {\n        return h(Inner)\n      },\n    }\n\n    createRecord(innerId, Inner)\n    createRecord(outerId, Outer)\n\n    const App = {\n      render: () => h(Outer),\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(App), root)\n    expect(serializeInner(root)).toBe('<div>foo</div>')\n\n    Inner = {\n      __hmrId: innerId,\n      render() {\n        return h('div', 'bar')\n      },\n    }\n    Outer = {\n      __hmrId: outerId,\n      render() {\n        return h(Inner)\n      },\n    }\n\n    // trigger reload for both Outer and Inner\n    reload(outerId, Outer)\n    reload(innerId, Inner)\n    await nextTick()\n\n    expect(serializeInner(root)).toBe('<div>bar</div>')\n  })\n\n  // #14127\n  test('update cached text nodes', async () => {\n    const root = nodeOps.createElement('div')\n    const appId = 'test-cached-text-nodes'\n    const App: ComponentOptions = {\n      __hmrId: appId,\n      data() {\n        return {\n          count: 0,\n        }\n      },\n      render: compileToFunction(\n        `{{count}}\n        <button @click=\"count++\">++</button> \n        static text`,\n      ),\n    }\n    createRecord(appId, App)\n    render(h(App), root)\n    expect(serializeInner(root)).toBe(`0 <button>++</button> static text`)\n\n    // trigger count update\n    triggerEvent((root as any).children[2], 'click')\n    await nextTick()\n    expect(serializeInner(root)).toBe(`1 <button>++</button> static text`)\n\n    // trigger HMR update\n    rerender(\n      appId,\n      compileToFunction(\n        `{{count}}\n        <button @click=\"count++\">++</button> \n        static text updated`,\n      ),\n    )\n    expect(serializeInner(root)).toBe(\n      `1 <button>++</button> static text updated`,\n    )\n\n    // trigger HMR update again\n    rerender(\n      appId,\n      compileToFunction(\n        `{{count}}\n        <button @click=\"count++\">++</button> \n        static text updated2`,\n      ),\n    )\n    expect(serializeInner(root)).toBe(\n      `1 <button>++</button> static text updated2`,\n    )\n  })\n})\n"
  },
  {
    "path": "packages/runtime-core/__tests__/hydration.spec.ts",
    "content": "/**\n * @vitest-environment jsdom\n */\n\nimport {\n  type ObjectDirective,\n  Suspense,\n  Teleport,\n  Transition,\n  type VNode,\n  createBlock,\n  createCommentVNode,\n  createElementBlock,\n  createElementVNode,\n  createSSRApp,\n  createStaticVNode,\n  createTextVNode,\n  createVNode,\n  defineAsyncComponent,\n  defineComponent,\n  h,\n  nextTick,\n  onMounted,\n  onServerPrefetch,\n  openBlock,\n  reactive,\n  ref,\n  renderSlot,\n  useCssVars,\n  vModelCheckbox,\n  vShow,\n  withCtx,\n  withDirectives,\n} from '@vue/runtime-dom'\nimport type { HMRRuntime } from '../src/hmr'\nimport { type SSRContext, renderToString } from '@vue/server-renderer'\nimport { PatchFlags, normalizeStyle } from '@vue/shared'\nimport { vShowOriginalDisplay } from '../../runtime-dom/src/directives/vShow'\n\ndeclare var __VUE_HMR_RUNTIME__: HMRRuntime\nconst { createRecord, reload } = __VUE_HMR_RUNTIME__\n\nfunction mountWithHydration(html: string, render: () => any) {\n  const container = document.createElement('div')\n  container.innerHTML = html\n  const app = createSSRApp({\n    render,\n  })\n  return {\n    vnode: app.mount(container).$.subTree as VNode<Node, Element> & {\n      el: Element\n    },\n    container,\n  }\n}\n\nconst triggerEvent = (type: string, el: Element) => {\n  const event = new Event(type)\n  el.dispatchEvent(event)\n}\n\ndescribe('SSR hydration', () => {\n  beforeEach(() => {\n    document.body.innerHTML = ''\n  })\n\n  test('text', async () => {\n    const msg = ref('foo')\n    const { vnode, container } = mountWithHydration('foo', () => msg.value)\n    expect(vnode.el).toBe(container.firstChild)\n    expect(container.textContent).toBe('foo')\n    msg.value = 'bar'\n    await nextTick()\n    expect(container.textContent).toBe('bar')\n  })\n\n  test('empty text', async () => {\n    const { container } = mountWithHydration('<div></div>', () =>\n      h('div', createTextVNode('')),\n    )\n    expect(container.textContent).toBe('')\n    expect(`Hydration children mismatch in <div>`).not.toHaveBeenWarned()\n  })\n\n  test('text w/ newlines', async () => {\n    mountWithHydration('<div>1\\n2\\n3</div>', () => h('div', '1\\r\\n2\\r3'))\n    expect(`Hydration text mismatch`).not.toHaveBeenWarned()\n  })\n\n  test('comment', () => {\n    const { vnode, container } = mountWithHydration('<!---->', () => null)\n    expect(vnode.el).toBe(container.firstChild)\n    expect(vnode.el.nodeType).toBe(8) // comment\n  })\n\n  test('static', () => {\n    const html = '<div><span>hello</span></div>'\n    const { vnode, container } = mountWithHydration(html, () =>\n      createStaticVNode('', 1),\n    )\n    expect(vnode.el).toBe(container.firstChild)\n    expect(vnode.el.outerHTML).toBe(html)\n    expect(vnode.anchor).toBe(container.firstChild)\n    expect(vnode.children).toBe(html)\n  })\n\n  test('static (multiple elements)', () => {\n    const staticContent = '<div></div><span>hello</span>'\n    const html = `<div><div>hi</div>` + staticContent + `<div>ho</div></div>`\n\n    const n1 = h('div', 'hi')\n    const s = createStaticVNode('', 2)\n    const n2 = h('div', 'ho')\n\n    const { container } = mountWithHydration(html, () => h('div', [n1, s, n2]))\n\n    const div = container.firstChild!\n\n    expect(n1.el).toBe(div.firstChild)\n    expect(n2.el).toBe(div.lastChild)\n    expect(s.el).toBe(div.childNodes[1])\n    expect(s.anchor).toBe(div.childNodes[2])\n    expect(s.children).toBe(staticContent)\n  })\n\n  // #6008\n  test('static (with text node as starting node)', () => {\n    const html = ` A <span>foo</span> B`\n    const { vnode, container } = mountWithHydration(html, () =>\n      createStaticVNode(` A <span>foo</span> B`, 3),\n    )\n    expect(vnode.el).toBe(container.firstChild)\n    expect(vnode.anchor).toBe(container.lastChild)\n    expect(`Hydration node mismatch`).not.toHaveBeenWarned()\n  })\n\n  test('static with content adoption', () => {\n    const html = ` A <span>foo</span> B`\n    const { vnode, container } = mountWithHydration(html, () =>\n      createStaticVNode(``, 3),\n    )\n    expect(vnode.el).toBe(container.firstChild)\n    expect(vnode.anchor).toBe(container.lastChild)\n    expect(vnode.children).toBe(html)\n    expect(`Hydration node mismatch`).not.toHaveBeenWarned()\n  })\n\n  test('element with text children', async () => {\n    const msg = ref('foo')\n    const { vnode, container } = mountWithHydration(\n      '<div class=\"foo\">foo</div>',\n      () => h('div', { class: msg.value }, msg.value),\n    )\n    expect(vnode.el).toBe(container.firstChild)\n    expect(container.firstChild!.textContent).toBe('foo')\n    msg.value = 'bar'\n    await nextTick()\n    expect(container.innerHTML).toBe(`<div class=\"bar\">bar</div>`)\n  })\n\n  // #7285\n  test('element with multiple continuous text vnodes', async () => {\n    // should no mismatch warning\n    const { container } = mountWithHydration('<div>foo0o</div>', () =>\n      h('div', ['fo', createTextVNode('o'), 0, 'o']),\n    )\n    expect(container.textContent).toBe('foo0o')\n  })\n\n  test('element with elements children', async () => {\n    const msg = ref('foo')\n    const fn = vi.fn()\n    const { vnode, container } = mountWithHydration(\n      '<div><span>foo</span><span class=\"foo\"></span></div>',\n      () =>\n        h('div', [\n          h('span', msg.value),\n          h('span', { class: msg.value, onClick: fn }),\n        ]),\n    )\n    expect(vnode.el).toBe(container.firstChild)\n    expect((vnode.children as VNode[])[0].el).toBe(\n      container.firstChild!.childNodes[0],\n    )\n    expect((vnode.children as VNode[])[1].el).toBe(\n      container.firstChild!.childNodes[1],\n    )\n\n    // event handler\n    triggerEvent('click', vnode.el.querySelector('.foo')!)\n    expect(fn).toHaveBeenCalled()\n\n    msg.value = 'bar'\n    await nextTick()\n    expect(vnode.el.innerHTML).toBe(`<span>bar</span><span class=\"bar\"></span>`)\n  })\n\n  test('element with ref', () => {\n    const el = ref()\n    const { vnode, container } = mountWithHydration('<div></div>', () =>\n      h('div', { ref: el }),\n    )\n    expect(vnode.el).toBe(container.firstChild)\n    expect(el.value).toBe(vnode.el)\n  })\n\n  test('Fragment', async () => {\n    const msg = ref('foo')\n    const fn = vi.fn()\n    const { vnode, container } = mountWithHydration(\n      '<div><!--[--><span>foo</span><!--[--><span class=\"foo\"></span><!--]--><!--]--></div>',\n      () =>\n        h('div', [\n          [\n            h('span', msg.value),\n            [h('span', { class: msg.value, onClick: fn })],\n          ],\n        ]),\n    )\n    expect(vnode.el).toBe(container.firstChild)\n\n    expect(vnode.el.innerHTML).toBe(\n      `<!--[--><span>foo</span><!--[--><span class=\"foo\"></span><!--]--><!--]-->`,\n    )\n\n    // start fragment 1\n    const fragment1 = (vnode.children as VNode[])[0]\n    expect(fragment1.el).toBe(vnode.el.childNodes[0])\n    const fragment1Children = fragment1.children as VNode[]\n\n    // first <span>\n    expect(fragment1Children[0].el!.tagName).toBe('SPAN')\n    expect(fragment1Children[0].el).toBe(vnode.el.childNodes[1])\n\n    // start fragment 2\n    const fragment2 = fragment1Children[1]\n    expect(fragment2.el).toBe(vnode.el.childNodes[2])\n    const fragment2Children = fragment2.children as VNode[]\n\n    // second <span>\n    expect(fragment2Children[0].el!.tagName).toBe('SPAN')\n    expect(fragment2Children[0].el).toBe(vnode.el.childNodes[3])\n\n    // end fragment 2\n    expect(fragment2.anchor).toBe(vnode.el.childNodes[4])\n\n    // end fragment 1\n    expect(fragment1.anchor).toBe(vnode.el.childNodes[5])\n\n    // event handler\n    triggerEvent('click', vnode.el.querySelector('.foo')!)\n    expect(fn).toHaveBeenCalled()\n\n    msg.value = 'bar'\n    await nextTick()\n    expect(vnode.el.innerHTML).toBe(\n      `<!--[--><span>bar</span><!--[--><span class=\"bar\"></span><!--]--><!--]-->`,\n    )\n  })\n\n  // #7285\n  test('Fragment (multiple continuous text vnodes)', async () => {\n    // should no mismatch warning\n    const { container } = mountWithHydration('<!--[-->fooo<!--]-->', () => [\n      'fo',\n      createTextVNode('o'),\n      'o',\n    ])\n    expect(container.textContent).toBe('fooo')\n  })\n\n  test('Teleport', async () => {\n    const msg = ref('foo')\n    const fn = vi.fn()\n    const teleportContainer = document.createElement('div')\n    teleportContainer.id = 'teleport'\n    teleportContainer.innerHTML = `<!--teleport start anchor--><span>foo</span><span class=\"foo\"></span><!--teleport anchor-->`\n    document.body.appendChild(teleportContainer)\n\n    const { vnode, container } = mountWithHydration(\n      '<!--teleport start--><!--teleport end-->',\n      () =>\n        h(Teleport, { to: '#teleport' }, [\n          h('span', msg.value),\n          h('span', { class: msg.value, onClick: fn }),\n        ]),\n    )\n\n    expect(vnode.el).toBe(container.firstChild)\n    expect(vnode.anchor).toBe(container.lastChild)\n\n    expect(vnode.target).toBe(teleportContainer)\n    expect(vnode.targetStart).toBe(teleportContainer.childNodes[0])\n    expect((vnode.children as VNode[])[0].el).toBe(\n      teleportContainer.childNodes[1],\n    )\n    expect((vnode.children as VNode[])[1].el).toBe(\n      teleportContainer.childNodes[2],\n    )\n    expect(vnode.targetAnchor).toBe(teleportContainer.childNodes[3])\n\n    // event handler\n    triggerEvent('click', teleportContainer.querySelector('.foo')!)\n    expect(fn).toHaveBeenCalled()\n\n    msg.value = 'bar'\n    await nextTick()\n    expect(teleportContainer.innerHTML).toBe(\n      `<!--teleport start anchor--><span>bar</span><span class=\"bar\"></span><!--teleport anchor-->`,\n    )\n  })\n\n  test('Teleport (multiple + integration)', async () => {\n    const msg = ref('foo')\n    const fn1 = vi.fn()\n    const fn2 = vi.fn()\n\n    const Comp = () => [\n      h(Teleport, { to: '#teleport2' }, [\n        h('span', msg.value),\n        h('span', { class: msg.value, onClick: fn1 }),\n      ]),\n      h(Teleport, { to: '#teleport2' }, [\n        h('span', msg.value + '2'),\n        h('span', { class: msg.value + '2', onClick: fn2 }),\n      ]),\n    ]\n\n    const teleportContainer = document.createElement('div')\n    teleportContainer.id = 'teleport2'\n    const ctx: SSRContext = {}\n    const mainHtml = await renderToString(h(Comp), ctx)\n    expect(mainHtml).toMatchInlineSnapshot(\n      `\"<!--[--><!--teleport start--><!--teleport end--><!--teleport start--><!--teleport end--><!--]-->\"`,\n    )\n\n    const teleportHtml = ctx.teleports!['#teleport2']\n    expect(teleportHtml).toMatchInlineSnapshot(\n      `\"<!--teleport start anchor--><span>foo</span><span class=\"foo\"></span><!--teleport anchor--><!--teleport start anchor--><span>foo2</span><span class=\"foo2\"></span><!--teleport anchor-->\"`,\n    )\n\n    teleportContainer.innerHTML = teleportHtml\n    document.body.appendChild(teleportContainer)\n\n    const { vnode, container } = mountWithHydration(mainHtml, Comp)\n    expect(vnode.el).toBe(container.firstChild)\n    const teleportVnode1 = (vnode.children as VNode[])[0]\n    const teleportVnode2 = (vnode.children as VNode[])[1]\n    expect(teleportVnode1.el).toBe(container.childNodes[1])\n    expect(teleportVnode1.anchor).toBe(container.childNodes[2])\n    expect(teleportVnode2.el).toBe(container.childNodes[3])\n    expect(teleportVnode2.anchor).toBe(container.childNodes[4])\n\n    expect(teleportVnode1.target).toBe(teleportContainer)\n    expect(teleportVnode1.targetStart).toBe(teleportContainer.childNodes[0])\n    expect((teleportVnode1 as any).children[0].el).toBe(\n      teleportContainer.childNodes[1],\n    )\n    expect(teleportVnode1.targetAnchor).toBe(teleportContainer.childNodes[3])\n\n    expect(teleportVnode2.target).toBe(teleportContainer)\n    expect(teleportVnode2.targetStart).toBe(teleportContainer.childNodes[4])\n    expect((teleportVnode2 as any).children[0].el).toBe(\n      teleportContainer.childNodes[5],\n    )\n    expect(teleportVnode2.targetAnchor).toBe(teleportContainer.childNodes[7])\n\n    // // event handler\n    triggerEvent('click', teleportContainer.querySelector('.foo')!)\n    expect(fn1).toHaveBeenCalled()\n\n    triggerEvent('click', teleportContainer.querySelector('.foo2')!)\n    expect(fn2).toHaveBeenCalled()\n\n    msg.value = 'bar'\n    await nextTick()\n    expect(teleportContainer.innerHTML).toMatchInlineSnapshot(\n      `\"<!--teleport start anchor--><span>bar</span><span class=\"bar\"></span><!--teleport anchor--><!--teleport start anchor--><span>bar2</span><span class=\"bar2\"></span><!--teleport anchor-->\"`,\n    )\n  })\n\n  test('Teleport (disabled)', async () => {\n    const msg = ref('foo')\n    const fn1 = vi.fn()\n    const fn2 = vi.fn()\n\n    const Comp = () => [\n      h('div', 'foo'),\n      h(Teleport, { to: '#teleport3', disabled: true }, [\n        h('span', msg.value),\n        h('span', { class: msg.value, onClick: fn1 }),\n      ]),\n      h('div', { class: msg.value + '2', onClick: fn2 }, 'bar'),\n    ]\n\n    const teleportContainer = document.createElement('div')\n    teleportContainer.id = 'teleport3'\n    const ctx: SSRContext = {}\n    const mainHtml = await renderToString(h(Comp), ctx)\n    expect(mainHtml).toMatchInlineSnapshot(\n      `\"<!--[--><div>foo</div><!--teleport start--><span>foo</span><span class=\"foo\"></span><!--teleport end--><div class=\"foo2\">bar</div><!--]-->\"`,\n    )\n\n    const teleportHtml = ctx.teleports!['#teleport3']\n    expect(teleportHtml).toMatchInlineSnapshot(\n      `\"<!--teleport start anchor--><!--teleport anchor-->\"`,\n    )\n\n    teleportContainer.innerHTML = teleportHtml\n    document.body.appendChild(teleportContainer)\n\n    const { vnode, container } = mountWithHydration(mainHtml, Comp)\n    expect(vnode.el).toBe(container.firstChild)\n    const children = vnode.children as VNode[]\n\n    expect(children[0].el).toBe(container.childNodes[1])\n\n    const teleportVnode = children[1]\n    expect(teleportVnode.el).toBe(container.childNodes[2])\n    expect((teleportVnode.children as VNode[])[0].el).toBe(\n      container.childNodes[3],\n    )\n    expect((teleportVnode.children as VNode[])[1].el).toBe(\n      container.childNodes[4],\n    )\n    expect(teleportVnode.anchor).toBe(container.childNodes[5])\n    expect(children[2].el).toBe(container.childNodes[6])\n\n    expect(teleportVnode.target).toBe(teleportContainer)\n    expect(teleportVnode.targetStart).toBe(teleportContainer.childNodes[0])\n    expect(teleportVnode.targetAnchor).toBe(teleportContainer.childNodes[1])\n\n    // // event handler\n    triggerEvent('click', container.querySelector('.foo')!)\n    expect(fn1).toHaveBeenCalled()\n\n    triggerEvent('click', container.querySelector('.foo2')!)\n    expect(fn2).toHaveBeenCalled()\n\n    msg.value = 'bar'\n    await nextTick()\n    expect(container.innerHTML).toMatchInlineSnapshot(\n      `\"<!--[--><div>foo</div><!--teleport start--><span>bar</span><span class=\"bar\"></span><!--teleport end--><div class=\"bar2\">bar</div><!--]-->\"`,\n    )\n  })\n\n  // #6152\n  test('Teleport (disabled + as component root)', () => {\n    const { container } = mountWithHydration(\n      '<!--[--><div>Parent fragment</div><!--teleport start--><div>Teleport content</div><!--teleport end--><!--]-->',\n      () => [\n        h('div', 'Parent fragment'),\n        h(() =>\n          h(Teleport, { to: 'body', disabled: true }, [\n            h('div', 'Teleport content'),\n          ]),\n        ),\n      ],\n    )\n    expect(document.body.innerHTML).toBe('')\n    expect(container.innerHTML).toBe(\n      '<!--[--><div>Parent fragment</div><!--teleport start--><div>Teleport content</div><!--teleport end--><!--]-->',\n    )\n    expect(\n      `Hydration completed but contains mismatches.`,\n    ).not.toHaveBeenWarned()\n  })\n\n  test('Teleport (as component root)', () => {\n    const teleportContainer = document.createElement('div')\n    teleportContainer.id = 'teleport4'\n    teleportContainer.innerHTML = `<!--teleport start anchor-->hello<!--teleport anchor-->`\n    document.body.appendChild(teleportContainer)\n\n    const wrapper = {\n      render() {\n        return h(Teleport, { to: '#teleport4' }, ['hello'])\n      },\n    }\n\n    const { vnode, container } = mountWithHydration(\n      '<div><!--teleport start--><!--teleport end--><div></div></div>',\n      () => h('div', [h(wrapper), h('div')]),\n    )\n    expect(vnode.el).toBe(container.firstChild)\n    // component el\n    const wrapperVNode = (vnode as any).children[0]\n    const tpStart = container.firstChild?.firstChild\n    const tpEnd = tpStart?.nextSibling\n    expect(wrapperVNode.el).toBe(tpStart)\n    expect(wrapperVNode.component.subTree.el).toBe(tpStart)\n    expect(wrapperVNode.component.subTree.anchor).toBe(tpEnd)\n    // next node hydrate properly\n    const nextVNode = (vnode as any).children[1]\n    expect(nextVNode.el).toBe(container.firstChild?.lastChild)\n  })\n\n  test('Teleport (nested)', () => {\n    const teleportContainer = document.createElement('div')\n    teleportContainer.id = 'teleport5'\n    teleportContainer.innerHTML = `<!--teleport start anchor--><div><!--teleport start--><!--teleport end--></div><!--teleport anchor--><!--teleport start anchor--><div>child</div><!--teleport anchor-->`\n    document.body.appendChild(teleportContainer)\n\n    const { vnode, container } = mountWithHydration(\n      '<!--teleport start--><!--teleport end-->',\n      () =>\n        h(Teleport, { to: '#teleport5' }, [\n          h('div', [h(Teleport, { to: '#teleport5' }, [h('div', 'child')])]),\n        ]),\n    )\n\n    expect(vnode.el).toBe(container.firstChild)\n    expect(vnode.anchor).toBe(container.lastChild)\n\n    const childDivVNode = (vnode as any).children[0]\n    const div = teleportContainer.childNodes[1]\n    expect(childDivVNode.el).toBe(div)\n    expect(vnode.targetAnchor).toBe(div?.nextSibling)\n\n    const childTeleportVNode = childDivVNode.children[0]\n    expect(childTeleportVNode.el).toBe(div?.firstChild)\n    expect(childTeleportVNode.anchor).toBe(div?.lastChild)\n\n    expect(childTeleportVNode.targetAnchor).toBe(teleportContainer.lastChild)\n    expect(childTeleportVNode.children[0].el).toBe(\n      teleportContainer.lastChild?.previousSibling,\n    )\n  })\n\n  test('with data-allow-mismatch component when using onServerPrefetch', async () => {\n    const Comp = {\n      template: `\n        <div>Comp2</div>\n      `,\n    }\n    let foo: any\n    const App = {\n      setup() {\n        const flag = ref(true)\n        foo = () => {\n          flag.value = false\n        }\n        onServerPrefetch(() => (flag.value = false))\n        return { flag }\n      },\n      components: {\n        Comp,\n      },\n      template: `\n        <span data-allow-mismatch>\n          <Comp v-if=\"flag\"></Comp>\n        </span>\n      `,\n    }\n    // hydrate\n    const container = document.createElement('div')\n    container.innerHTML = await renderToString(h(App))\n    createSSRApp(App).mount(container)\n    expect(container.innerHTML).toBe(\n      '<span data-allow-mismatch=\"\"><div>Comp2</div></span>',\n    )\n    foo()\n    await nextTick()\n    expect(container.innerHTML).toBe(\n      '<span data-allow-mismatch=\"\"><!--v-if--></span>',\n    )\n  })\n\n  test('Teleport unmount (full integration)', async () => {\n    const Comp1 = {\n      template: `\n        <Teleport to=\"#target\"> \n          <span>Teleported Comp1</span>\n        </Teleport>\n      `,\n    }\n    const Comp2 = {\n      template: `\n        <div>Comp2</div>\n      `,\n    }\n\n    const toggle = ref(true)\n    const App = {\n      template: `\n        <div>\n          <Comp1 v-if=\"toggle\"/>\n          <Comp2 v-else/>\n        </div>\n      `,\n      components: {\n        Comp1,\n        Comp2,\n      },\n      setup() {\n        return { toggle }\n      },\n    }\n\n    const container = document.createElement('div')\n    const teleportContainer = document.createElement('div')\n    teleportContainer.id = 'target'\n    document.body.appendChild(teleportContainer)\n\n    // server render\n    const ctx: SSRContext = {}\n    container.innerHTML = await renderToString(h(App), ctx)\n    expect(container.innerHTML).toBe(\n      '<div><!--teleport start--><!--teleport end--></div>',\n    )\n    teleportContainer.innerHTML = ctx.teleports!['#target']\n\n    // hydrate\n    createSSRApp(App).mount(container)\n    expect(container.innerHTML).toBe(\n      '<div><!--teleport start--><!--teleport end--></div>',\n    )\n    expect(teleportContainer.innerHTML).toBe(\n      '<!--teleport start anchor--><span>Teleported Comp1</span><!--teleport anchor-->',\n    )\n    expect(`Hydration children mismatch`).not.toHaveBeenWarned()\n\n    toggle.value = false\n    await nextTick()\n    expect(container.innerHTML).toBe('<div><div>Comp2</div></div>')\n    expect(teleportContainer.innerHTML).toBe('')\n  })\n\n  test('Teleport unmount (mismatch + full integration)', async () => {\n    const Comp1 = {\n      template: `\n        <Teleport to=\"#target\"> \n          <span>Teleported Comp1</span>\n        </Teleport>\n      `,\n    }\n    const Comp2 = {\n      template: `\n        <div>Comp2</div>\n      `,\n    }\n\n    const toggle = ref(true)\n    const App = {\n      template: `\n        <div>\n          <Comp1 v-if=\"toggle\"/>\n          <Comp2 v-else/>\n        </div>\n      `,\n      components: {\n        Comp1,\n        Comp2,\n      },\n      setup() {\n        return { toggle }\n      },\n    }\n\n    const container = document.createElement('div')\n    const teleportContainer = document.createElement('div')\n    teleportContainer.id = 'target'\n    document.body.appendChild(teleportContainer)\n\n    // server render\n    container.innerHTML = await renderToString(h(App))\n    expect(container.innerHTML).toBe(\n      '<div><!--teleport start--><!--teleport end--></div>',\n    )\n    expect(teleportContainer.innerHTML).toBe('')\n\n    // hydrate\n    createSSRApp(App).mount(container)\n    expect(container.innerHTML).toBe(\n      '<div><!--teleport start--><!--teleport end--></div>',\n    )\n    expect(teleportContainer.innerHTML).toBe('<span>Teleported Comp1</span>')\n    expect(`Hydration children mismatch`).toHaveBeenWarned()\n\n    toggle.value = false\n    await nextTick()\n    expect(container.innerHTML).toBe('<div><div>Comp2</div></div>')\n    expect(teleportContainer.innerHTML).toBe('')\n  })\n\n  test('Teleport unmount (disabled + full integration)', async () => {\n    const disabled = ref(true)\n    const target = ref('#teleport001')\n    const toggle = ref(true)\n\n    const Comp = {\n      template: `\n      <div>\n        <div id=\"teleport001\">\n          <Teleport\n            :to=\"target\"\n            :disabled=\"disabled\"\n          >\n            <template v-for=\"section in order\">\n              <div>{{section}}</div>\n            </template>\n          </Teleport>\n        </div>\n        <div id=\"teleport002\"></div>\n      </div>\n      `,\n      setup() {\n        const order = ref(['A', 'B', 'C'])\n        return { target, disabled, order }\n      },\n    }\n    const App = {\n      template: `<Comp v-if=\"toggle\"/>`,\n      components: {\n        Comp,\n      },\n      setup() {\n        return { toggle }\n      },\n    }\n\n    const container = document.createElement('div')\n    document.body.appendChild(container)\n\n    // server render\n    container.innerHTML = await renderToString(h(App))\n    expect(container.innerHTML).toBe(\n      `<div>` +\n        `<div id=\"teleport001\">` +\n        `<!--teleport start-->` +\n        `<!--[--><div>A</div><div>B</div><div>C</div><!--]-->` +\n        `<!--teleport end-->` +\n        `</div>` +\n        `<div id=\"teleport002\"></div>` +\n        `</div>`,\n    )\n\n    // hydrate\n    createSSRApp(App).mount(container)\n    expect(`Hydration children mismatch`).not.toHaveBeenWarned()\n\n    target.value = '#teleport002'\n    disabled.value = false\n    await nextTick()\n    expect(container.querySelector('#teleport001')!.innerHTML).toBe(\n      '<!--teleport start--><!--teleport end-->',\n    )\n    expect(container.querySelector('#teleport002')!.innerHTML).toBe(\n      '<!--[--><div>A</div><div>B</div><div>C</div><!--]-->',\n    )\n\n    toggle.value = false\n    await nextTick()\n    expect(container.innerHTML).toBe('<!--v-if-->')\n  })\n\n  test('Teleport target change (mismatch + full integration)', async () => {\n    const target = ref('#target1')\n    const Comp = {\n      template: `\n        <Teleport :to=\"target\"> \n          <span>Teleported</span>\n        </Teleport>\n      `,\n      setup() {\n        return { target }\n      },\n    }\n\n    const App = {\n      template: `\n        <div>\n          <Comp />\n        </div>\n      `,\n      components: {\n        Comp,\n      },\n    }\n\n    const container = document.createElement('div')\n    const teleportContainer1 = document.createElement('div')\n    teleportContainer1.id = 'target1'\n    const teleportContainer2 = document.createElement('div')\n    teleportContainer2.id = 'target2'\n    document.body.appendChild(teleportContainer1)\n    document.body.appendChild(teleportContainer2)\n\n    // server render\n    container.innerHTML = await renderToString(h(App))\n    expect(container.innerHTML).toBe(\n      '<div><!--teleport start--><!--teleport end--></div>',\n    )\n    expect(teleportContainer1.innerHTML).toBe('')\n    expect(teleportContainer2.innerHTML).toBe('')\n\n    // hydrate\n    createSSRApp(App).mount(container)\n    expect(container.innerHTML).toBe(\n      '<div><!--teleport start--><!--teleport end--></div>',\n    )\n    expect(teleportContainer1.innerHTML).toBe('<span>Teleported</span>')\n    expect(teleportContainer2.innerHTML).toBe('')\n    expect(`Hydration children mismatch`).toHaveBeenWarned()\n\n    target.value = '#target2'\n    await nextTick()\n    expect(teleportContainer1.innerHTML).toBe('')\n    expect(teleportContainer2.innerHTML).toBe('<span>Teleported</span>')\n  })\n\n  // compile SSR + client render fn from the same template & hydrate\n  test('full compiler integration', async () => {\n    const mounted: string[] = []\n    const log = vi.fn()\n    const toggle = ref(true)\n\n    const Child = {\n      data() {\n        return {\n          count: 0,\n          text: 'hello',\n          style: {\n            color: 'red',\n          },\n        }\n      },\n      mounted() {\n        mounted.push('child')\n      },\n      template: `\n      <div>\n        <span class=\"count\" :style=\"style\">{{ count }}</span>\n        <button class=\"inc\" @click=\"count++\">inc</button>\n        <button class=\"change\" @click=\"style.color = 'green'\" >change color</button>\n        <button class=\"emit\" @click=\"$emit('foo')\">emit</button>\n        <span class=\"text\">{{ text }}</span>\n        <input v-model=\"text\">\n      </div>\n      `,\n    }\n\n    const App = {\n      setup() {\n        return { toggle }\n      },\n      mounted() {\n        mounted.push('parent')\n      },\n      template: `\n        <div>\n          <span>hello</span>\n          <template v-if=\"toggle\">\n            <Child @foo=\"log('child')\"/>\n            <template v-if=\"true\">\n              <button class=\"parent-click\" @click=\"log('click')\">click me</button>\n            </template>\n          </template>\n          <span>hello</span>\n        </div>`,\n      components: {\n        Child,\n      },\n      methods: {\n        log,\n      },\n    }\n\n    const container = document.createElement('div')\n    // server render\n    container.innerHTML = await renderToString(h(App))\n    // hydrate\n    createSSRApp(App).mount(container)\n\n    // assert interactions\n    // 1. parent button click\n    triggerEvent('click', container.querySelector('.parent-click')!)\n    expect(log).toHaveBeenCalledWith('click')\n\n    // 2. child inc click + text interpolation\n    const count = container.querySelector('.count') as HTMLElement\n    expect(count.textContent).toBe(`0`)\n    triggerEvent('click', container.querySelector('.inc')!)\n    await nextTick()\n    expect(count.textContent).toBe(`1`)\n\n    // 3. child color click + style binding\n    expect(count.style.color).toBe('red')\n    triggerEvent('click', container.querySelector('.change')!)\n    await nextTick()\n    expect(count.style.color).toBe('green')\n\n    // 4. child event emit\n    triggerEvent('click', container.querySelector('.emit')!)\n    expect(log).toHaveBeenCalledWith('child')\n\n    // 5. child v-model\n    const text = container.querySelector('.text')!\n    const input = container.querySelector('input')!\n    expect(text.textContent).toBe('hello')\n    input.value = 'bye'\n    triggerEvent('input', input)\n    await nextTick()\n    expect(text.textContent).toBe('bye')\n  })\n\n  test('handle click error in ssr mode', async () => {\n    const App = {\n      setup() {\n        const throwError = () => {\n          throw new Error('Sentry Error')\n        }\n        return { throwError }\n      },\n      template: `\n        <div>\n          <button class=\"parent-click\" @click=\"throwError\">click me</button>\n        </div>`,\n    }\n\n    const container = document.createElement('div')\n    // server render\n    container.innerHTML = await renderToString(h(App))\n    // hydrate\n    const app = createSSRApp(App)\n    const handler = (app.config.errorHandler = vi.fn())\n    app.mount(container)\n    // assert interactions\n    // parent button click\n    triggerEvent('click', container.querySelector('.parent-click')!)\n    expect(handler).toHaveBeenCalled()\n  })\n\n  test('handle blur error in ssr mode', async () => {\n    const App = {\n      setup() {\n        const throwError = () => {\n          throw new Error('Sentry Error')\n        }\n        return { throwError }\n      },\n      template: `\n        <div>\n          <input class=\"parent-click\" @blur=\"throwError\"/>\n        </div>`,\n    }\n\n    const container = document.createElement('div')\n    // server render\n    container.innerHTML = await renderToString(h(App))\n    // hydrate\n    const app = createSSRApp(App)\n    const handler = (app.config.errorHandler = vi.fn())\n    app.mount(container)\n    // assert interactions\n    // parent blur event\n    triggerEvent('blur', container.querySelector('.parent-click')!)\n    expect(handler).toHaveBeenCalled()\n  })\n\n  test('Suspense', async () => {\n    const AsyncChild = {\n      async setup() {\n        const count = ref(0)\n        return () =>\n          h(\n            'span',\n            {\n              onClick: () => {\n                count.value++\n              },\n            },\n            count.value,\n          )\n      },\n    }\n    const { vnode, container } = mountWithHydration('<span>0</span>', () =>\n      h(Suspense, () => h(AsyncChild)),\n    )\n    expect(vnode.el).toBe(container.firstChild)\n    // wait for hydration to finish\n    await new Promise(r => setTimeout(r))\n    triggerEvent('click', container.querySelector('span')!)\n    await nextTick()\n    expect(container.innerHTML).toBe(`<span>1</span>`)\n  })\n\n  // #6638\n  test('Suspense + async component', async () => {\n    let isSuspenseResolved = false\n    let isSuspenseResolvedInChild: any\n    const AsyncChild = defineAsyncComponent(() =>\n      Promise.resolve(\n        defineComponent({\n          setup() {\n            isSuspenseResolvedInChild = isSuspenseResolved\n            const count = ref(0)\n            return () =>\n              h(\n                'span',\n                {\n                  onClick: () => {\n                    count.value++\n                  },\n                },\n                count.value,\n              )\n          },\n        }),\n      ),\n    )\n    const { vnode, container } = mountWithHydration('<span>0</span>', () =>\n      h(\n        Suspense,\n        {\n          onResolve() {\n            isSuspenseResolved = true\n          },\n        },\n        () => h(AsyncChild),\n      ),\n    )\n    expect(vnode.el).toBe(container.firstChild)\n    // wait for hydration to finish\n    await new Promise(r => setTimeout(r))\n\n    expect(isSuspenseResolvedInChild).toBe(false)\n    expect(isSuspenseResolved).toBe(true)\n\n    // assert interaction\n    triggerEvent('click', container.querySelector('span')!)\n    await nextTick()\n    expect(container.innerHTML).toBe(`<span>1</span>`)\n  })\n\n  test('Suspense (full integration)', async () => {\n    const mountedCalls: number[] = []\n    const asyncDeps: Promise<any>[] = []\n\n    const AsyncChild = defineComponent({\n      props: ['n'],\n      async setup(props) {\n        const count = ref(props.n)\n        onMounted(() => {\n          mountedCalls.push(props.n)\n        })\n        const p = new Promise(r => setTimeout(r, props.n * 10))\n        asyncDeps.push(p)\n        await p\n        return () =>\n          h(\n            'span',\n            {\n              onClick: () => {\n                count.value++\n              },\n            },\n            count.value,\n          )\n      },\n    })\n\n    const done = vi.fn()\n    const App = {\n      template: `\n      <Suspense @resolve=\"done\">\n        <div>\n          <AsyncChild :n=\"1\" />\n          <AsyncChild :n=\"2\" />\n        </div>\n      </Suspense>`,\n      components: {\n        AsyncChild,\n      },\n      methods: {\n        done,\n      },\n    }\n\n    const container = document.createElement('div')\n    // server render\n    container.innerHTML = await renderToString(h(App))\n    expect(container.innerHTML).toMatchInlineSnapshot(\n      `\"<div><span>1</span><span>2</span></div>\"`,\n    )\n    // reset asyncDeps from ssr\n    asyncDeps.length = 0\n    // hydrate\n    createSSRApp(App).mount(container)\n\n    expect(mountedCalls.length).toBe(0)\n    expect(asyncDeps.length).toBe(2)\n\n    // wait for hydration to complete\n    await Promise.all(asyncDeps)\n    await new Promise(r => setTimeout(r))\n\n    // should flush buffered effects\n    expect(mountedCalls).toMatchObject([1, 2])\n    expect(container.innerHTML).toMatch(\n      `<div><span>1</span><span>2</span></div>`,\n    )\n\n    const span1 = container.querySelector('span')!\n    triggerEvent('click', span1)\n    await nextTick()\n    expect(container.innerHTML).toMatch(\n      `<div><span>2</span><span>2</span></div>`,\n    )\n\n    const span2 = span1.nextSibling as Element\n    triggerEvent('click', span2)\n    await nextTick()\n    expect(container.innerHTML).toMatch(\n      `<div><span>2</span><span>3</span></div>`,\n    )\n  })\n\n  test('async component', async () => {\n    const spy = vi.fn()\n    const Comp = () =>\n      h(\n        'button',\n        {\n          onClick: spy,\n        },\n        'hello!',\n      )\n\n    let serverResolve: any\n    let AsyncComp = defineAsyncComponent(\n      () =>\n        new Promise(r => {\n          serverResolve = r\n        }),\n    )\n\n    const App = {\n      render() {\n        return ['hello', h(AsyncComp), 'world']\n      },\n    }\n\n    // server render\n    const htmlPromise = renderToString(h(App))\n    serverResolve(Comp)\n    const html = await htmlPromise\n    expect(html).toMatchInlineSnapshot(\n      `\"<!--[-->hello<button>hello!</button>world<!--]-->\"`,\n    )\n\n    // hydration\n    let clientResolve: any\n    AsyncComp = defineAsyncComponent(\n      () =>\n        new Promise(r => {\n          clientResolve = r\n        }),\n    )\n\n    const container = document.createElement('div')\n    container.innerHTML = html\n    createSSRApp(App).mount(container)\n\n    // hydration not complete yet\n    triggerEvent('click', container.querySelector('button')!)\n    expect(spy).not.toHaveBeenCalled()\n\n    // resolve\n    clientResolve(Comp)\n    await new Promise(r => setTimeout(r))\n\n    // should be hydrated now\n    triggerEvent('click', container.querySelector('button')!)\n    expect(spy).toHaveBeenCalled()\n  })\n\n  test('update async wrapper before resolve', async () => {\n    const Comp = {\n      render() {\n        return h('h1', 'Async component')\n      },\n    }\n    let serverResolve: any\n    let AsyncComp = defineAsyncComponent(\n      () =>\n        new Promise(r => {\n          serverResolve = r\n        }),\n    )\n\n    const toggle = ref(true)\n    const App = {\n      setup() {\n        onMounted(() => {\n          // change state, this makes updateComponent(AsyncComp) execute before\n          // the async component is resolved\n          toggle.value = false\n        })\n\n        return () => {\n          return [toggle.value ? 'hello' : 'world', h(AsyncComp)]\n        }\n      },\n    }\n\n    // server render\n    const htmlPromise = renderToString(h(App))\n    serverResolve(Comp)\n    const html = await htmlPromise\n    expect(html).toMatchInlineSnapshot(\n      `\"<!--[-->hello<h1>Async component</h1><!--]-->\"`,\n    )\n\n    // hydration\n    let clientResolve: any\n    AsyncComp = defineAsyncComponent(\n      () =>\n        new Promise(r => {\n          clientResolve = r\n        }),\n    )\n\n    const container = document.createElement('div')\n    container.innerHTML = html\n    createSSRApp(App).mount(container)\n\n    // resolve\n    clientResolve(Comp)\n    await new Promise(r => setTimeout(r))\n\n    // should be hydrated now\n    expect(`Hydration node mismatch`).not.toHaveBeenWarned()\n    expect(container.innerHTML).toMatchInlineSnapshot(\n      `\"<!--[-->world<h1>Async component</h1><!--]-->\"`,\n    )\n  })\n\n  // #13510\n  test('update async component after parent mount before async component resolve', async () => {\n    const Comp = {\n      props: ['toggle'],\n      render(this: any) {\n        return h('h1', [\n          this.toggle ? 'Async component' : 'Updated async component',\n        ])\n      },\n    }\n    let serverResolve: any\n    let AsyncComp = defineAsyncComponent(\n      () =>\n        new Promise(r => {\n          serverResolve = r\n        }),\n    )\n\n    const toggle = ref(true)\n    const App = {\n      setup() {\n        onMounted(() => {\n          // change state, after mount and before async component resolve\n          nextTick(() => (toggle.value = false))\n        })\n\n        return () => {\n          return h(AsyncComp, { toggle: toggle.value })\n        }\n      },\n    }\n\n    // server render\n    const htmlPromise = renderToString(h(App))\n    serverResolve(Comp)\n    const html = await htmlPromise\n    expect(html).toMatchInlineSnapshot(`\"<h1>Async component</h1>\"`)\n\n    // hydration\n    let clientResolve: any\n    AsyncComp = defineAsyncComponent(\n      () =>\n        new Promise(r => {\n          clientResolve = r\n        }),\n    )\n\n    const container = document.createElement('div')\n    container.innerHTML = html\n    createSSRApp(App).mount(container)\n\n    // resolve\n    clientResolve(Comp)\n    await new Promise(r => setTimeout(r))\n\n    // prevent lazy hydration since the component has been patched\n    expect('Skipping lazy hydration for component').toHaveBeenWarned()\n    expect(`Hydration node mismatch`).not.toHaveBeenWarned()\n    expect(container.innerHTML).toMatchInlineSnapshot(\n      `\"<h1>Updated async component</h1>\"`,\n    )\n  })\n\n  test('hydrate safely when property used by async setup changed before render', async () => {\n    const toggle = ref(true)\n\n    const AsyncComp = {\n      async setup() {\n        await new Promise<void>(r => setTimeout(r, 10))\n        return () => h('h1', 'Async component')\n      },\n    }\n\n    const AsyncWrapper = {\n      render() {\n        return h(AsyncComp)\n      },\n    }\n\n    const SiblingComp = {\n      setup() {\n        toggle.value = false\n        return () => h('span')\n      },\n    }\n\n    const App = {\n      setup() {\n        return () =>\n          h(\n            Suspense,\n            {},\n            {\n              default: () => [\n                h('main', {}, [\n                  h(AsyncWrapper, {\n                    prop: toggle.value ? 'hello' : 'world',\n                  }),\n                  h(SiblingComp),\n                ]),\n              ],\n            },\n          )\n      },\n    }\n\n    // server render\n    const html = await renderToString(h(App))\n\n    expect(html).toMatchInlineSnapshot(\n      `\"<main><h1 prop=\"hello\">Async component</h1><span></span></main>\"`,\n    )\n\n    expect(toggle.value).toBe(false)\n\n    // hydration\n\n    // reset the value\n    toggle.value = true\n    expect(toggle.value).toBe(true)\n\n    const container = document.createElement('div')\n    container.innerHTML = html\n    createSSRApp(App).mount(container)\n\n    await new Promise(r => setTimeout(r, 10))\n\n    expect(toggle.value).toBe(false)\n\n    // should be hydrated now\n    expect(container.innerHTML).toMatchInlineSnapshot(\n      `\"<main><h1 prop=\"world\">Async component</h1><span></span></main>\"`,\n    )\n  })\n\n  test('hydrate safely when property used by deep nested async setup changed before render', async () => {\n    const toggle = ref(true)\n\n    const AsyncComp = {\n      async setup() {\n        await new Promise<void>(r => setTimeout(r, 10))\n        return () => h('h1', 'Async component')\n      },\n    }\n\n    const AsyncWrapper = { render: () => h(AsyncComp) }\n    const AsyncWrapperWrapper = { render: () => h(AsyncWrapper) }\n\n    const SiblingComp = {\n      setup() {\n        toggle.value = false\n        return () => h('span')\n      },\n    }\n\n    const App = {\n      setup() {\n        return () =>\n          h(\n            Suspense,\n            {},\n            {\n              default: () => [\n                h('main', {}, [\n                  h(AsyncWrapperWrapper, {\n                    prop: toggle.value ? 'hello' : 'world',\n                  }),\n                  h(SiblingComp),\n                ]),\n              ],\n            },\n          )\n      },\n    }\n\n    // server render\n    const html = await renderToString(h(App))\n\n    expect(html).toMatchInlineSnapshot(\n      `\"<main><h1 prop=\"hello\">Async component</h1><span></span></main>\"`,\n    )\n\n    expect(toggle.value).toBe(false)\n\n    // hydration\n\n    // reset the value\n    toggle.value = true\n    expect(toggle.value).toBe(true)\n\n    const container = document.createElement('div')\n    container.innerHTML = html\n    createSSRApp(App).mount(container)\n\n    await new Promise(r => setTimeout(r, 10))\n\n    expect(toggle.value).toBe(false)\n\n    // should be hydrated now\n    expect(container.innerHTML).toMatchInlineSnapshot(\n      `\"<main><h1 prop=\"world\">Async component</h1><span></span></main>\"`,\n    )\n  })\n\n  // #3787\n  test('unmount async wrapper before load', async () => {\n    let resolve: any\n    const AsyncComp = defineAsyncComponent(\n      () =>\n        new Promise(r => {\n          resolve = r\n        }),\n    )\n\n    const show = ref(true)\n    const root = document.createElement('div')\n    root.innerHTML = '<div><div>async</div></div>'\n\n    createSSRApp({\n      render() {\n        return h('div', [show.value ? h(AsyncComp) : h('div', 'hi')])\n      },\n    }).mount(root)\n\n    show.value = false\n    await nextTick()\n    expect(root.innerHTML).toBe('<div><div>hi</div></div>')\n    resolve({})\n  })\n\n  //#12362\n  test('nested async wrapper', async () => {\n    const Toggle = defineAsyncComponent(\n      () =>\n        new Promise(r => {\n          r(\n            defineComponent({\n              setup(_, { slots }) {\n                const show = ref(false)\n                onMounted(() => {\n                  nextTick(() => {\n                    show.value = true\n                  })\n                })\n                return () =>\n                  withDirectives(\n                    h('div', null, [renderSlot(slots, 'default')]),\n                    [[vShow, show.value]],\n                  )\n              },\n            }) as any,\n          )\n        }),\n    )\n\n    const Wrapper = defineAsyncComponent(() => {\n      return new Promise(r => {\n        r(\n          defineComponent({\n            render(this: any) {\n              return renderSlot(this.$slots, 'default')\n            },\n          }) as any,\n        )\n      })\n    })\n\n    const count = ref(0)\n    const fn = vi.fn()\n    const Child = {\n      setup() {\n        onMounted(() => {\n          fn()\n          count.value++\n        })\n        return () => h('div', count.value)\n      },\n    }\n\n    const App = {\n      render() {\n        return h(Toggle, null, {\n          default: () =>\n            h(Wrapper, null, {\n              default: () =>\n                h(Wrapper, null, {\n                  default: () => h(Child),\n                }),\n            }),\n        })\n      },\n    }\n\n    const root = document.createElement('div')\n    root.innerHTML = await renderToString(h(App))\n    expect(root.innerHTML).toMatchInlineSnapshot(\n      `\"<div style=\"display:none;\"><!--[--><!--[--><!--[--><div>0</div><!--]--><!--]--><!--]--></div>\"`,\n    )\n\n    createSSRApp(App).mount(root)\n    await nextTick()\n    await nextTick()\n    expect(root.innerHTML).toMatchInlineSnapshot(\n      `\"<div style=\"\"><!--[--><!--[--><!--[--><div>1</div><!--]--><!--]--><!--]--></div>\"`,\n    )\n    expect(fn).toBeCalledTimes(1)\n  })\n\n  test('unmount async wrapper before load (fragment)', async () => {\n    let resolve: any\n    const AsyncComp = defineAsyncComponent(\n      () =>\n        new Promise(r => {\n          resolve = r\n        }),\n    )\n\n    const show = ref(true)\n    const root = document.createElement('div')\n    root.innerHTML = '<div><!--[-->async<!--]--></div>'\n\n    createSSRApp({\n      render() {\n        return h('div', [show.value ? h(AsyncComp) : h('div', 'hi')])\n      },\n    }).mount(root)\n\n    show.value = false\n    await nextTick()\n    expect(root.innerHTML).toBe('<div><div>hi</div></div>')\n    resolve({})\n  })\n\n  test('elements with camel-case in svg ', () => {\n    const { vnode, container } = mountWithHydration(\n      '<animateTransform></animateTransform>',\n      () => h('animateTransform'),\n    )\n    expect(vnode.el).toBe(container.firstChild)\n    expect(`Hydration node mismatch`).not.toHaveBeenWarned()\n  })\n\n  test('SVG as a mount container', () => {\n    const svgContainer = document.createElement('svg')\n    svgContainer.innerHTML = '<g></g>'\n    const app = createSSRApp({\n      render: () => h('g'),\n    })\n\n    expect(\n      (\n        app.mount(svgContainer).$.subTree as VNode<Node, Element> & {\n          el: Element\n        }\n      ).el instanceof SVGElement,\n    )\n  })\n\n  test('force hydrate prop with `.prop` modifier', () => {\n    const { container } = mountWithHydration('<input type=\"checkbox\">', () =>\n      h('input', {\n        type: 'checkbox',\n        '.indeterminate': true,\n      }),\n    )\n    expect((container.firstChild! as any).indeterminate).toBe(true)\n  })\n\n  test('force hydrate input v-model with non-string value bindings', () => {\n    const { container } = mountWithHydration(\n      '<input type=\"checkbox\" value=\"true\">',\n      () =>\n        withDirectives(\n          createVNode(\n            'input',\n            { type: 'checkbox', 'true-value': true },\n            null,\n            PatchFlags.PROPS,\n            ['true-value'],\n          ),\n          [[vModelCheckbox, true]],\n        ),\n    )\n    expect((container.firstChild as any)._trueValue).toBe(true)\n  })\n\n  test('force hydrate checkbox with indeterminate', () => {\n    const { container } = mountWithHydration(\n      '<input type=\"checkbox\" indeterminate>',\n      () =>\n        createVNode(\n          'input',\n          { type: 'checkbox', indeterminate: '' },\n          null,\n          PatchFlags.CACHED,\n        ),\n    )\n    expect((container.firstChild as any).indeterminate).toBe(true)\n  })\n\n  test('force hydrate select option with non-string value bindings', () => {\n    const { container } = mountWithHydration(\n      '<select><option value=\"true\">ok</option></select>',\n      () =>\n        h('select', [\n          // hoisted because bound value is a constant...\n          createVNode('option', { value: true }, null, -1 /* HOISTED */),\n        ]),\n    )\n    expect((container.firstChild!.firstChild as any)._value).toBe(true)\n  })\n\n  // #7203\n  test('force hydrate custom element with dynamic props', () => {\n    class MyElement extends HTMLElement {\n      foo = ''\n      constructor() {\n        super()\n      }\n    }\n    customElements.define('my-element-7203', MyElement)\n\n    const msg = ref('bar')\n    const container = document.createElement('div')\n    container.innerHTML = '<my-element-7203></my-element-7203>'\n    const app = createSSRApp({\n      render: () => h('my-element-7203', { foo: msg.value }),\n    })\n    app.mount(container)\n    expect((container.firstChild as any).foo).toBe(msg.value)\n  })\n\n  // #14274\n  test('should not render ref on custom element during hydration', () => {\n    const container = document.createElement('div')\n    container.innerHTML = '<my-element>hello</my-element>'\n    const root = ref()\n    const app = createSSRApp({\n      render: () =>\n        h('my-element', {\n          ref: root,\n          innerHTML: 'hello',\n        }),\n    })\n    app.mount(container)\n    expect(container.innerHTML).toBe('<my-element>hello</my-element>')\n    expect((container.firstChild as Element).hasAttribute('ref')).toBe(false)\n    expect(root.value).toBe(container.firstChild)\n  })\n\n  // #5728\n  test('empty text node in slot', () => {\n    const Comp = {\n      render(this: any) {\n        return renderSlot(this.$slots, 'default', {}, () => [\n          createTextVNode(''),\n        ])\n      },\n    }\n    const { container, vnode } = mountWithHydration('<!--[--><!--]-->', () =>\n      h(Comp),\n    )\n    expect(container.childNodes.length).toBe(3)\n    const text = container.childNodes[1]\n    expect(text.nodeType).toBe(3)\n    expect(vnode.el).toBe(container.childNodes[0])\n    // component => slot fragment => text node\n    expect((vnode as any).component?.subTree.children[0].el).toBe(text)\n  })\n\n  // #7215\n  test('empty text node', () => {\n    const Comp = {\n      render(this: any) {\n        return h('p', [''])\n      },\n    }\n    const { container } = mountWithHydration('<p></p>', () => h(Comp))\n    expect(container.childNodes.length).toBe(1)\n    const p = container.childNodes[0]\n    expect(p.childNodes.length).toBe(1)\n    const text = p.childNodes[0]\n    expect(text.nodeType).toBe(3)\n  })\n\n  // #11372\n  test('object style value tracking in prod', async () => {\n    __DEV__ = false\n    try {\n      const style = reactive({ color: 'red' })\n      const Comp = {\n        render(this: any) {\n          return (\n            openBlock(),\n            createElementBlock(\n              'div',\n              {\n                style: normalizeStyle(style),\n              },\n              null,\n              4 /* STYLE */,\n            )\n          )\n        },\n      }\n      const { container } = mountWithHydration(\n        `<div style=\"color: red;\"></div>`,\n        () => h(Comp),\n      )\n      style.color = 'green'\n      await nextTick()\n      expect(container.innerHTML).toBe(`<div style=\"color: green;\"></div>`)\n    } finally {\n      __DEV__ = true\n    }\n  })\n\n  test('app.unmount()', async () => {\n    const container = document.createElement('DIV')\n    container.innerHTML = '<button></button>'\n    const App = defineComponent({\n      setup(_, { expose }) {\n        const count = ref(0)\n\n        expose({ count })\n\n        return () =>\n          h('button', {\n            onClick: () => count.value++,\n          })\n      },\n    })\n\n    const app = createSSRApp(App)\n    const vm = app.mount(container)\n    await nextTick()\n    expect((container as any)._vnode).toBeDefined()\n    // @ts-expect-error - expose()'d properties are not available on vm type\n    expect(vm.count).toBe(0)\n\n    app.unmount()\n    expect((container as any)._vnode).toBe(null)\n  })\n\n  // #6637\n  test('stringified root fragment', () => {\n    mountWithHydration(`<!--[--><div></div><!--]-->`, () =>\n      createStaticVNode(`<div></div>`, 1),\n    )\n    expect(`mismatch`).not.toHaveBeenWarned()\n  })\n\n  test('transition appear', () => {\n    const { vnode, container } = mountWithHydration(\n      `<template><div>foo</div></template>`,\n      () =>\n        h(\n          Transition,\n          { appear: true },\n          {\n            default: () => h('div', 'foo'),\n          },\n        ),\n    )\n    expect(container.firstChild).toMatchInlineSnapshot(`\n      <div\n        class=\"v-enter-from v-enter-active\"\n      >\n        foo\n      </div>\n    `)\n    expect(vnode.el).toBe(container.firstChild)\n    expect(`mismatch`).not.toHaveBeenWarned()\n  })\n\n  test('transition appear work with pre-existing class', () => {\n    const { vnode, container } = mountWithHydration(\n      `<template><div class=\"foo\">foo</div></template>`,\n      () =>\n        h(\n          Transition,\n          { appear: true },\n          {\n            default: () => h('div', { class: 'foo' }, 'foo'),\n          },\n        ),\n    )\n    expect(container.firstChild).toMatchInlineSnapshot(`\n      <div\n        class=\"foo v-enter-from v-enter-active\"\n      >\n        foo\n      </div>\n    `)\n    expect(vnode.el).toBe(container.firstChild)\n    expect(`mismatch`).not.toHaveBeenWarned()\n  })\n\n  // #13394\n  test('transition appear work with empty content', async () => {\n    const show = ref(true)\n    const { vnode, container } = mountWithHydration(\n      `<template><!----></template>`,\n      function (this: any) {\n        return h(\n          Transition,\n          { appear: true },\n          {\n            default: () =>\n              show.value\n                ? renderSlot(this.$slots, 'default')\n                : createTextVNode('foo'),\n          },\n        )\n      },\n    )\n\n    // empty slot render as a comment node\n    expect(container.firstChild!.nodeType).toBe(Node.COMMENT_NODE)\n    expect(vnode.el).toBe(container.firstChild)\n    expect(`mismatch`).not.toHaveBeenWarned()\n\n    show.value = false\n    await nextTick()\n    expect(container.innerHTML).toBe('foo')\n  })\n\n  test('transition appear with v-if', () => {\n    const show = false\n    const { vnode, container } = mountWithHydration(\n      `<template><!----></template>`,\n      () =>\n        h(\n          Transition,\n          { appear: true },\n          {\n            default: () => (show ? h('div', 'foo') : createCommentVNode('')),\n          },\n        ),\n    )\n    expect(container.firstChild).toMatchInlineSnapshot('<!---->')\n    expect(vnode.el).toBe(container.firstChild)\n    expect(`mismatch`).not.toHaveBeenWarned()\n  })\n\n  test('transition appear with v-show', () => {\n    const show = false\n    const { vnode, container } = mountWithHydration(\n      `<template><div style=\"display: none;\">foo</div></template>`,\n      () =>\n        h(\n          Transition,\n          { appear: true },\n          {\n            default: () =>\n              withDirectives(createVNode('div', null, 'foo'), [[vShow, show]]),\n          },\n        ),\n    )\n    expect(container.firstChild).toMatchInlineSnapshot(`\n      <div\n        class=\"v-enter-from v-enter-active\"\n        style=\"display: none;\"\n      >\n        foo\n      </div>\n    `)\n    expect((container.firstChild as any)[vShowOriginalDisplay]).toBe('')\n    expect(vnode.el).toBe(container.firstChild)\n    expect(`mismatch`).not.toHaveBeenWarned()\n  })\n\n  test('transition appear w/ event listener', async () => {\n    const container = document.createElement('div')\n    container.innerHTML = `<template><button>0</button></template>`\n    createSSRApp({\n      data() {\n        return {\n          count: 0,\n        }\n      },\n      template: `\n        <Transition appear>\n          <button @click=\"count++\">{{count}}</button>\n        </Transition>\n      `,\n    }).mount(container)\n\n    expect(container.firstChild).toMatchInlineSnapshot(`\n      <button\n        class=\"v-enter-from v-enter-active\"\n      >\n        0\n      </button>\n    `)\n\n    triggerEvent('click', container.querySelector('button')!)\n    await nextTick()\n    expect(container.firstChild).toMatchInlineSnapshot(`\n      <button\n        class=\"v-enter-from v-enter-active\"\n      >\n        1\n      </button>\n    `)\n  })\n\n  test('Suspense + transition appear', async () => {\n    const { vnode, container } = mountWithHydration(\n      `<template><div>foo</div></template>`,\n      () =>\n        h(Suspense, {}, () =>\n          h(\n            Transition,\n            { appear: true },\n            {\n              default: () => h('div', 'foo'),\n            },\n          ),\n        ),\n    )\n\n    expect(vnode.el).toBe(container.firstChild)\n    // wait for hydration to finish\n    await new Promise(r => setTimeout(r))\n\n    expect(container.firstChild).toMatchInlineSnapshot(`\n      <div\n        class=\"v-enter-from v-enter-active\"\n      >\n        foo\n      </div>\n    `)\n    await nextTick()\n    expect(vnode.el).toBe(container.firstChild)\n  })\n\n  // #10607\n  test('update component stable slot (prod + optimized mode)', async () => {\n    __DEV__ = false\n    try {\n      const container = document.createElement('div')\n      container.innerHTML = `<template><div show=\"false\"><!--[--><div><div><!----></div></div><div>0</div><!--]--></div></template>`\n      const Comp = {\n        render(this: any) {\n          return (\n            openBlock(),\n            createElementBlock('div', null, [\n              renderSlot(this.$slots, 'default'),\n            ])\n          )\n        },\n      }\n      const show = ref(false)\n      const clicked = ref(false)\n\n      const Wrapper = {\n        setup() {\n          const items = ref<number[]>([])\n          onMounted(() => {\n            items.value = [1]\n          })\n          return () => {\n            return (\n              openBlock(),\n              createBlock(Comp, null, {\n                default: withCtx(() => [\n                  createElementVNode('div', null, [\n                    createElementVNode('div', null, [\n                      clicked.value\n                        ? (openBlock(),\n                          createElementBlock('div', { key: 0 }, 'foo'))\n                        : createCommentVNode('v-if', true),\n                    ]),\n                  ]),\n                  createElementVNode(\n                    'div',\n                    null,\n                    items.value.length,\n                    1 /* TEXT */,\n                  ),\n                ]),\n                _: 1 /* STABLE */,\n              })\n            )\n          }\n        },\n      }\n      createSSRApp({\n        components: { Wrapper },\n        data() {\n          return { show }\n        },\n        template: `<Wrapper :show=\"show\"/>`,\n      }).mount(container)\n\n      await nextTick()\n      expect(container.innerHTML).toBe(\n        `<div show=\"false\"><!--[--><div><div><!----></div></div><div>1</div><!--]--></div>`,\n      )\n\n      show.value = true\n      await nextTick()\n      expect(async () => {\n        clicked.value = true\n        await nextTick()\n      }).not.toThrow(\"Cannot read properties of null (reading 'insertBefore')\")\n\n      await nextTick()\n      expect(container.innerHTML).toBe(\n        `<div show=\"true\"><!--[--><div><div><div>foo</div></div></div><div>1</div><!--]--></div>`,\n      )\n    } catch (e) {\n      throw e\n    } finally {\n      __DEV__ = true\n    }\n  })\n\n  test('hmr reload child wrapped in KeepAlive', async () => {\n    const id = 'child-reload'\n    const Child = {\n      __hmrId: id,\n      template: `<div>foo</div>`,\n    }\n    createRecord(id, Child)\n\n    const appId = 'test-app-id'\n    const App = {\n      __hmrId: appId,\n      components: { Child },\n      template: `\n      <div>\n        <KeepAlive>\n          <Child />\n        </KeepAlive>\n      </div>\n      `,\n    }\n\n    const root = document.createElement('div')\n    root.innerHTML = await renderToString(h(App))\n    createSSRApp(App).mount(root)\n    expect(root.innerHTML).toBe('<div><div>foo</div></div>')\n\n    reload(id, {\n      __hmrId: id,\n      template: `<div>bar</div>`,\n    })\n    await nextTick()\n    expect(root.innerHTML).toBe('<div><div>bar</div></div>')\n  })\n\n  test('hmr root reload', async () => {\n    const appId = 'test-app-id'\n    const App = {\n      __hmrId: appId,\n      template: `<div>foo</div>`,\n    }\n\n    const root = document.createElement('div')\n    root.innerHTML = await renderToString(h(App))\n    createSSRApp(App).mount(root)\n    expect(root.innerHTML).toBe('<div>foo</div>')\n\n    reload(appId, {\n      __hmrId: appId,\n      template: `<div>bar</div>`,\n    })\n    await nextTick()\n    expect(root.innerHTML).toBe('<div>bar</div>')\n  })\n\n  describe('mismatch handling', () => {\n    test('text node', () => {\n      const { container } = mountWithHydration(`foo`, () => 'bar')\n      expect(container.textContent).toBe('bar')\n      expect(`Hydration text mismatch`).toHaveBeenWarned()\n    })\n\n    test('element text content', () => {\n      const { container } = mountWithHydration(`<div>foo</div>`, () =>\n        h('div', 'bar'),\n      )\n      expect(container.innerHTML).toBe('<div>bar</div>')\n      expect(`Hydration text content mismatch`).toHaveBeenWarned()\n    })\n\n    test('not enough children', () => {\n      const { container } = mountWithHydration(`<div></div>`, () =>\n        h('div', [h('span', 'foo'), h('span', 'bar')]),\n      )\n      expect(container.innerHTML).toBe(\n        '<div><span>foo</span><span>bar</span></div>',\n      )\n      expect(`Hydration children mismatch`).toHaveBeenWarned()\n    })\n\n    test('too many children', () => {\n      const { container } = mountWithHydration(\n        `<div><span>foo</span><span>bar</span></div>`,\n        () => h('div', [h('span', 'foo')]),\n      )\n      expect(container.innerHTML).toBe('<div><span>foo</span></div>')\n      expect(`Hydration children mismatch`).toHaveBeenWarned()\n    })\n\n    test('complete mismatch', () => {\n      const { container } = mountWithHydration(\n        `<div><span>foo</span><span>bar</span></div>`,\n        () => h('div', [h('div', 'foo'), h('p', 'bar')]),\n      )\n      expect(container.innerHTML).toBe('<div><div>foo</div><p>bar</p></div>')\n      expect(`Hydration node mismatch`).toHaveBeenWarnedTimes(2)\n    })\n\n    test('fragment mismatch removal', () => {\n      const { container } = mountWithHydration(\n        `<div><!--[--><div>foo</div><div>bar</div><!--]--></div>`,\n        () => h('div', [h('span', 'replaced')]),\n      )\n      expect(container.innerHTML).toBe('<div><span>replaced</span></div>')\n      expect(`Hydration node mismatch`).toHaveBeenWarned()\n    })\n\n    test('fragment not enough children', () => {\n      const { container } = mountWithHydration(\n        `<div><!--[--><div>foo</div><!--]--><div>baz</div></div>`,\n        () => h('div', [[h('div', 'foo'), h('div', 'bar')], h('div', 'baz')]),\n      )\n      expect(container.innerHTML).toBe(\n        '<div><!--[--><div>foo</div><div>bar</div><!--]--><div>baz</div></div>',\n      )\n      expect(`Hydration node mismatch`).toHaveBeenWarned()\n    })\n\n    test('fragment too many children', () => {\n      const { container } = mountWithHydration(\n        `<div><!--[--><div>foo</div><div>bar</div><!--]--><div>baz</div></div>`,\n        () => h('div', [[h('div', 'foo')], h('div', 'baz')]),\n      )\n      expect(container.innerHTML).toBe(\n        '<div><!--[--><div>foo</div><!--]--><div>baz</div></div>',\n      )\n      // fragment ends early and attempts to hydrate the extra <div>bar</div>\n      // as 2nd fragment child.\n      expect(`Hydration text content mismatch`).toHaveBeenWarned()\n      // excessive children removal\n      expect(`Hydration children mismatch`).toHaveBeenWarned()\n    })\n\n    test('Teleport target has empty children', () => {\n      const teleportContainer = document.createElement('div')\n      teleportContainer.id = 'teleport'\n      document.body.appendChild(teleportContainer)\n\n      mountWithHydration('<!--teleport start--><!--teleport end-->', () =>\n        h(Teleport, { to: '#teleport' }, [h('span', 'value')]),\n      )\n      expect(teleportContainer.innerHTML).toBe(`<span>value</span>`)\n      expect(`Hydration children mismatch`).toHaveBeenWarned()\n    })\n\n    test('comment mismatch (element)', () => {\n      const { container } = mountWithHydration(`<div><span></span></div>`, () =>\n        h('div', [createCommentVNode('hi')]),\n      )\n      expect(container.innerHTML).toBe('<div><!--hi--></div>')\n      expect(`Hydration node mismatch`).toHaveBeenWarned()\n    })\n\n    test('comment mismatch (text)', () => {\n      const { container } = mountWithHydration(`<div>foobar</div>`, () =>\n        h('div', [createCommentVNode('hi')]),\n      )\n      expect(container.innerHTML).toBe('<div><!--hi--></div>')\n      expect(`Hydration node mismatch`).toHaveBeenWarned()\n    })\n\n    test('class mismatch', () => {\n      mountWithHydration(`<div class=\"foo bar\"></div>`, () =>\n        h('div', { class: ['foo', 'bar'] }),\n      )\n      mountWithHydration(`<div class=\"foo bar\"></div>`, () =>\n        h('div', { class: { foo: true, bar: true } }),\n      )\n      mountWithHydration(`<div class=\"foo bar\"></div>`, () =>\n        h('div', { class: 'foo bar' }),\n      )\n      // SVG classes\n      mountWithHydration(`<svg class=\"foo bar\"></svg>`, () =>\n        h('svg', { class: 'foo bar' }),\n      )\n      // class with different order\n      mountWithHydration(`<div class=\"foo bar\"></div>`, () =>\n        h('div', { class: 'bar foo' }),\n      )\n      expect(`Hydration class mismatch`).not.toHaveBeenWarned()\n      mountWithHydration(`<div class=\"foo bar\"></div>`, () =>\n        h('div', { class: 'foo' }),\n      )\n      expect(`Hydration class mismatch`).toHaveBeenWarned()\n    })\n\n    test('style mismatch', () => {\n      mountWithHydration(`<div style=\"color:red;\"></div>`, () =>\n        h('div', { style: { color: 'red' } }),\n      )\n      mountWithHydration(`<div style=\"color:red;\"></div>`, () =>\n        h('div', { style: `color:red;` }),\n      )\n      mountWithHydration(\n        `<div style=\"color:red; font-size: 12px;\"></div>`,\n        () => h('div', { style: `font-size: 12px; color:red;` }),\n      )\n      mountWithHydration(`<div style=\"color:red;display:none;\"></div>`, () =>\n        withDirectives(createVNode('div', { style: 'color: red' }, ''), [\n          [vShow, false],\n        ]),\n      )\n      expect(`Hydration style mismatch`).not.toHaveBeenWarned()\n      mountWithHydration(`<div style=\"color:red;\"></div>`, () =>\n        h('div', { style: { color: 'green' } }),\n      )\n      expect(`Hydration style mismatch`).toHaveBeenWarnedTimes(1)\n    })\n\n    test('style mismatch when no style attribute is present', () => {\n      mountWithHydration(`<div></div>`, () =>\n        h('div', { style: { color: 'red' } }),\n      )\n      expect(`Hydration style mismatch`).toHaveBeenWarnedTimes(1)\n    })\n\n    test('style mismatch w/ v-show', () => {\n      mountWithHydration(`<div style=\"color:red;display:none\"></div>`, () =>\n        withDirectives(createVNode('div', { style: 'color: red' }, ''), [\n          [vShow, false],\n        ]),\n      )\n      expect(`Hydration style mismatch`).not.toHaveBeenWarned()\n      mountWithHydration(`<div style=\"color:red;\"></div>`, () =>\n        withDirectives(createVNode('div', { style: 'color: red' }, ''), [\n          [vShow, false],\n        ]),\n      )\n      expect(`Hydration style mismatch`).toHaveBeenWarnedTimes(1)\n    })\n\n    test('attr mismatch', () => {\n      mountWithHydration(`<div id=\"foo\"></div>`, () => h('div', { id: 'foo' }))\n      mountWithHydration(`<div spellcheck></div>`, () =>\n        h('div', { spellcheck: '' }),\n      )\n      mountWithHydration(`<div></div>`, () => h('div', { id: undefined }))\n      // boolean\n      mountWithHydration(`<select multiple></div>`, () =>\n        h('select', { multiple: true }),\n      )\n      mountWithHydration(`<select multiple></div>`, () =>\n        h('select', { multiple: 'multiple' }),\n      )\n      expect(`Hydration attribute mismatch`).not.toHaveBeenWarned()\n\n      mountWithHydration(`<div></div>`, () => h('div', { id: 'foo' }))\n      expect(`Hydration attribute mismatch`).toHaveBeenWarnedTimes(1)\n\n      mountWithHydration(`<div id=\"bar\"></div>`, () => h('div', { id: 'foo' }))\n      expect(`Hydration attribute mismatch`).toHaveBeenWarnedTimes(2)\n    })\n\n    test('attr special case: textarea value', () => {\n      mountWithHydration(`<textarea>foo</textarea>`, () =>\n        h('textarea', { value: 'foo' }),\n      )\n      mountWithHydration(`<textarea></textarea>`, () =>\n        h('textarea', { value: '' }),\n      )\n      expect(`Hydration attribute mismatch`).not.toHaveBeenWarned()\n\n      mountWithHydration(`<textarea>foo</textarea>`, () =>\n        h('textarea', { value: 'bar' }),\n      )\n      expect(`Hydration attribute mismatch`).toHaveBeenWarned()\n    })\n\n    // #11873\n    test('<textarea> with newlines at the beginning', async () => {\n      const render = () => h('textarea', null, '\\nhello')\n      const html = await renderToString(createSSRApp({ render }))\n      mountWithHydration(html, render)\n      expect(`Hydration text content mismatch`).not.toHaveBeenWarned()\n    })\n\n    test('<pre> with newlines at the beginning', async () => {\n      const render = () => h('pre', null, '\\n')\n      const html = await renderToString(createSSRApp({ render }))\n      mountWithHydration(html, render)\n      expect(`Hydration text content mismatch`).not.toHaveBeenWarned()\n    })\n\n    test('boolean attr handling', () => {\n      mountWithHydration(`<input />`, () => h('input', { readonly: false }))\n      expect(`Hydration attribute mismatch`).not.toHaveBeenWarned()\n\n      mountWithHydration(`<input readonly />`, () =>\n        h('input', { readonly: true }),\n      )\n      expect(`Hydration attribute mismatch`).not.toHaveBeenWarned()\n\n      mountWithHydration(`<input readonly=\"readonly\" />`, () =>\n        h('input', { readonly: true }),\n      )\n      expect(`Hydration attribute mismatch`).not.toHaveBeenWarned()\n    })\n\n    test('client value is null or undefined', () => {\n      mountWithHydration(`<div></div>`, () =>\n        h('div', { draggable: undefined }),\n      )\n      expect(`Hydration attribute mismatch`).not.toHaveBeenWarned()\n\n      mountWithHydration(`<input />`, () => h('input', { type: null }))\n      expect(`Hydration attribute mismatch`).not.toHaveBeenWarned()\n    })\n\n    test('should not warn against object values', () => {\n      mountWithHydration(`<input />`, () => h('input', { from: {} }))\n      expect(`Hydration attribute mismatch`).not.toHaveBeenWarned()\n    })\n\n    test('should not warn on falsy bindings of non-property keys', () => {\n      mountWithHydration(`<button />`, () => h('button', { href: undefined }))\n      expect(`Hydration attribute mismatch`).not.toHaveBeenWarned()\n    })\n\n    test('should not warn on non-renderable option values', () => {\n      mountWithHydration(`<select><option>hello</option></select>`, () =>\n        h('select', [h('option', { value: ['foo'] }, 'hello')]),\n      )\n      expect(`Hydration attribute mismatch`).not.toHaveBeenWarned()\n    })\n\n    test('should not warn css v-bind', () => {\n      const container = document.createElement('div')\n      container.innerHTML = `<div style=\"--foo:red;color:var(--foo);\" />`\n      const app = createSSRApp({\n        setup() {\n          useCssVars(() => ({\n            foo: 'red',\n          }))\n          return () => h('div', { style: { color: 'var(--foo)' } })\n        },\n      })\n      app.mount(container)\n      expect(`Hydration style mismatch`).not.toHaveBeenWarned()\n    })\n\n    // #10317 - test case from #10325\n    test('css vars should only be added to expected on component root dom', () => {\n      const container = document.createElement('div')\n      container.innerHTML = `<div style=\"--foo:red;\"><div style=\"color:var(--foo);\" /></div>`\n      const app = createSSRApp({\n        setup() {\n          useCssVars(() => ({\n            foo: 'red',\n          }))\n          return () =>\n            h('div', null, [h('div', { style: { color: 'var(--foo)' } })])\n        },\n      })\n      app.mount(container)\n      expect(`Hydration style mismatch`).not.toHaveBeenWarned()\n    })\n\n    // #11188\n    test('css vars support fallthrough', () => {\n      const container = document.createElement('div')\n      container.innerHTML = `<div style=\"padding: 4px;--foo:red;\"></div>`\n      const app = createSSRApp({\n        setup() {\n          useCssVars(() => ({\n            foo: 'red',\n          }))\n          return () => h(Child)\n        },\n      })\n      const Child = {\n        setup() {\n          return () => h('div', { style: 'padding: 4px' })\n        },\n      }\n      app.mount(container)\n      expect(`Hydration style mismatch`).not.toHaveBeenWarned()\n    })\n\n    // #11189\n    test('should not warn for directives that mutate DOM in created', () => {\n      const container = document.createElement('div')\n      container.innerHTML = `<div class=\"test red\"></div>`\n      const vColor: ObjectDirective = {\n        created(el, binding) {\n          el.classList.add(binding.value)\n        },\n      }\n      const app = createSSRApp({\n        setup() {\n          return () =>\n            withDirectives(h('div', { class: 'test' }), [[vColor, 'red']])\n        },\n      })\n      app.mount(container)\n      expect(`Hydration style mismatch`).not.toHaveBeenWarned()\n    })\n\n    test('with disabled teleport + undefined target', async () => {\n      const container = document.createElement('div')\n      const isOpen = ref(false)\n      const App = {\n        setup() {\n          return { isOpen }\n        },\n        template: `\n          <Teleport :to=\"undefined\" :disabled=\"true\">\n            <div v-if=\"isOpen\">\n              Menu is open...\n            </div>\n          </Teleport>`,\n      }\n      container.innerHTML = await renderToString(h(App))\n      const app = createSSRApp(App)\n      app.mount(container)\n      isOpen.value = true\n      await nextTick()\n      expect(container.innerHTML).toBe(\n        `<!--teleport start--><div> Menu is open... </div><!--teleport end-->`,\n      )\n    })\n\n    test('escape css var name', () => {\n      const container = document.createElement('div')\n      container.innerHTML = `<div style=\"padding: 4px;--foo\\\\.bar:red;\"></div>`\n      const app = createSSRApp({\n        setup() {\n          useCssVars(() => ({\n            'foo.bar': 'red',\n          }))\n          return () => h(Child)\n        },\n      })\n      const Child = {\n        setup() {\n          return () => h('div', { style: 'padding: 4px' })\n        },\n      }\n      app.mount(container)\n      expect(`Hydration style mismatch`).not.toHaveBeenWarned()\n    })\n  })\n\n  describe('data-allow-mismatch', () => {\n    test('element text content', () => {\n      const { container } = mountWithHydration(\n        `<div data-allow-mismatch=\"text\">foo</div>`,\n        () => h('div', 'bar'),\n      )\n      expect(container.innerHTML).toBe(\n        '<div data-allow-mismatch=\"text\">bar</div>',\n      )\n      expect(`Hydration text content mismatch`).not.toHaveBeenWarned()\n    })\n\n    test('not enough children', () => {\n      const { container } = mountWithHydration(\n        `<div data-allow-mismatch=\"children\"></div>`,\n        () => h('div', [h('span', 'foo'), h('span', 'bar')]),\n      )\n      expect(container.innerHTML).toBe(\n        '<div data-allow-mismatch=\"children\"><span>foo</span><span>bar</span></div>',\n      )\n      expect(`Hydration children mismatch`).not.toHaveBeenWarned()\n    })\n\n    test('too many children', () => {\n      const { container } = mountWithHydration(\n        `<div data-allow-mismatch=\"children\"><span>foo</span><span>bar</span></div>`,\n        () => h('div', [h('span', 'foo')]),\n      )\n      expect(container.innerHTML).toBe(\n        '<div data-allow-mismatch=\"children\"><span>foo</span></div>',\n      )\n      expect(`Hydration children mismatch`).not.toHaveBeenWarned()\n    })\n\n    test('complete mismatch', () => {\n      const { container } = mountWithHydration(\n        `<div data-allow-mismatch=\"children\"><span>foo</span><span>bar</span></div>`,\n        () => h('div', [h('div', 'foo'), h('p', 'bar')]),\n      )\n      expect(container.innerHTML).toBe(\n        '<div data-allow-mismatch=\"children\"><div>foo</div><p>bar</p></div>',\n      )\n      expect(`Hydration node mismatch`).not.toHaveBeenWarned()\n    })\n\n    test('fragment mismatch removal', () => {\n      const { container } = mountWithHydration(\n        `<div data-allow-mismatch=\"children\"><!--[--><div>foo</div><div>bar</div><!--]--></div>`,\n        () => h('div', [h('span', 'replaced')]),\n      )\n      expect(container.innerHTML).toBe(\n        '<div data-allow-mismatch=\"children\"><span>replaced</span></div>',\n      )\n      expect(`Hydration node mismatch`).not.toHaveBeenWarned()\n    })\n\n    test('fragment not enough children', () => {\n      const { container } = mountWithHydration(\n        `<div data-allow-mismatch=\"children\"><!--[--><div>foo</div><!--]--><div>baz</div></div>`,\n        () => h('div', [[h('div', 'foo'), h('div', 'bar')], h('div', 'baz')]),\n      )\n      expect(container.innerHTML).toBe(\n        '<div data-allow-mismatch=\"children\"><!--[--><div>foo</div><div>bar</div><!--]--><div>baz</div></div>',\n      )\n      expect(`Hydration node mismatch`).not.toHaveBeenWarned()\n    })\n\n    test('fragment too many children', () => {\n      const { container } = mountWithHydration(\n        `<div data-allow-mismatch=\"children\"><!--[--><div>foo</div><div>bar</div><!--]--><div>baz</div></div>`,\n        () => h('div', [[h('div', 'foo')], h('div', 'baz')]),\n      )\n      expect(container.innerHTML).toBe(\n        '<div data-allow-mismatch=\"children\"><!--[--><div>foo</div><!--]--><div>baz</div></div>',\n      )\n      // fragment ends early and attempts to hydrate the extra <div>bar</div>\n      // as 2nd fragment child.\n      expect(`Hydration text content mismatch`).not.toHaveBeenWarned()\n      // excessive children removal\n      expect(`Hydration children mismatch`).not.toHaveBeenWarned()\n    })\n\n    test('comment mismatch (element)', () => {\n      const { container } = mountWithHydration(\n        `<div data-allow-mismatch=\"children\"><span></span></div>`,\n        () => h('div', [createCommentVNode('hi')]),\n      )\n      expect(container.innerHTML).toBe(\n        '<div data-allow-mismatch=\"children\"><!--hi--></div>',\n      )\n      expect(`Hydration node mismatch`).not.toHaveBeenWarned()\n    })\n\n    test('comment mismatch (text)', () => {\n      const { container } = mountWithHydration(\n        `<div data-allow-mismatch=\"children\">foobar</div>`,\n        () => h('div', [createCommentVNode('hi')]),\n      )\n      expect(container.innerHTML).toBe(\n        '<div data-allow-mismatch=\"children\"><!--hi--></div>',\n      )\n      expect(`Hydration node mismatch`).not.toHaveBeenWarned()\n    })\n\n    test('class mismatch', () => {\n      mountWithHydration(\n        `<div class=\"foo bar\" data-allow-mismatch=\"class\"></div>`,\n        () => h('div', { class: 'foo' }),\n      )\n      expect(`Hydration class mismatch`).not.toHaveBeenWarned()\n    })\n\n    test('style mismatch', () => {\n      mountWithHydration(\n        `<div style=\"color:red;\" data-allow-mismatch=\"style\"></div>`,\n        () => h('div', { style: { color: 'green' } }),\n      )\n      expect(`Hydration style mismatch`).not.toHaveBeenWarned()\n    })\n\n    test('attr mismatch', () => {\n      mountWithHydration(`<div data-allow-mismatch=\"attribute\"></div>`, () =>\n        h('div', { id: 'foo' }),\n      )\n      mountWithHydration(\n        `<div id=\"bar\" data-allow-mismatch=\"attribute\"></div>`,\n        () => h('div', { id: 'foo' }),\n      )\n      expect(`Hydration attribute mismatch`).not.toHaveBeenWarned()\n    })\n  })\n})\n"
  },
  {
    "path": "packages/runtime-core/__tests__/misc.spec.ts",
    "content": "import { h, isReactive, nodeOps, reactive, render } from '@vue/runtime-test'\n\ndescribe('misc', () => {\n  test('component public instance should not be observable', () => {\n    let instance: any\n    const Comp = {\n      render() {},\n      mounted() {\n        instance = this\n      },\n    }\n    render(h(Comp), nodeOps.createElement('div'))\n    expect(instance).toBeDefined()\n    const r = reactive(instance)\n    expect(r).toBe(instance)\n    expect(isReactive(r)).toBe(false)\n  })\n})\n"
  },
  {
    "path": "packages/runtime-core/__tests__/rendererAttrsFallthrough.spec.ts",
    "content": "/**\n * @vitest-environment jsdom\n */\n// using DOM renderer because this case is mostly DOM-specific\n\nimport {\n  Fragment,\n  type FunctionalComponent,\n  Teleport,\n  createBlock,\n  createCommentVNode,\n  createElementBlock,\n  createElementVNode,\n  defineComponent,\n  h,\n  mergeProps,\n  nextTick,\n  onUpdated,\n  openBlock,\n  ref,\n  render,\n  withModifiers,\n} from '@vue/runtime-dom'\nimport { createApp } from 'vue'\nimport { PatchFlags } from '@vue/shared'\n\ndescribe('attribute fallthrough', () => {\n  it('should allow attrs to fallthrough', async () => {\n    const click = vi.fn()\n    const childUpdated = vi.fn()\n\n    const Hello = {\n      setup() {\n        const count = ref(0)\n\n        function inc() {\n          count.value++\n          click()\n        }\n\n        return () =>\n          h(Child, {\n            foo: count.value + 1,\n            id: 'test',\n            class: 'c' + count.value,\n            style: { color: count.value ? 'red' : 'green' },\n            onClick: inc,\n            'data-id': count.value + 1,\n          })\n      },\n    }\n\n    const Child = {\n      setup(props: any) {\n        onUpdated(childUpdated)\n        return () =>\n          h(\n            'div',\n            {\n              class: 'c2',\n              style: { fontWeight: 'bold' },\n            },\n            props.foo,\n          )\n      },\n    }\n\n    const root = document.createElement('div')\n    document.body.appendChild(root)\n    render(h(Hello), root)\n\n    const node = root.children[0] as HTMLElement\n\n    expect(node.getAttribute('id')).toBe('test')\n    expect(node.getAttribute('foo')).toBe('1')\n    expect(node.getAttribute('class')).toBe('c2 c0')\n    expect(node.style.color).toBe('green')\n    expect(node.style.fontWeight).toBe('bold')\n    expect(node.dataset.id).toBe('1')\n    node.dispatchEvent(new CustomEvent('click'))\n    expect(click).toHaveBeenCalled()\n\n    await nextTick()\n    expect(childUpdated).toHaveBeenCalled()\n    expect(node.getAttribute('id')).toBe('test')\n    expect(node.getAttribute('foo')).toBe('2')\n    expect(node.getAttribute('class')).toBe('c2 c1')\n    expect(node.style.color).toBe('red')\n    expect(node.style.fontWeight).toBe('bold')\n    expect(node.dataset.id).toBe('2')\n  })\n\n  it('should only allow whitelisted fallthrough on functional component with optional props', async () => {\n    const click = vi.fn()\n    const childUpdated = vi.fn()\n\n    const count = ref(0)\n\n    function inc() {\n      count.value++\n      click()\n    }\n\n    const Hello = () =>\n      h(Child, {\n        foo: count.value + 1,\n        id: 'test',\n        class: 'c' + count.value,\n        style: { color: count.value ? 'red' : 'green' },\n        onClick: inc,\n      })\n\n    const Child = (props: any) => {\n      childUpdated()\n      return h(\n        'div',\n        {\n          class: 'c2',\n          style: { fontWeight: 'bold' },\n        },\n        props.foo,\n      )\n    }\n\n    const root = document.createElement('div')\n    document.body.appendChild(root)\n    render(h(Hello), root)\n\n    const node = root.children[0] as HTMLElement\n\n    // not whitelisted\n    expect(node.getAttribute('id')).toBe(null)\n    expect(node.getAttribute('foo')).toBe(null)\n\n    // whitelisted: style, class, event listeners\n    expect(node.getAttribute('class')).toBe('c2 c0')\n    expect(node.style.color).toBe('green')\n    expect(node.style.fontWeight).toBe('bold')\n    node.dispatchEvent(new CustomEvent('click'))\n    expect(click).toHaveBeenCalled()\n\n    await nextTick()\n    expect(childUpdated).toHaveBeenCalled()\n    expect(node.getAttribute('id')).toBe(null)\n    expect(node.getAttribute('foo')).toBe(null)\n    expect(node.getAttribute('class')).toBe('c2 c1')\n    expect(node.style.color).toBe('red')\n    expect(node.style.fontWeight).toBe('bold')\n  })\n\n  it('should allow all attrs on functional component with declared props', async () => {\n    const click = vi.fn()\n    const childUpdated = vi.fn()\n\n    const count = ref(0)\n\n    function inc() {\n      count.value++\n      click()\n    }\n\n    const Hello = () =>\n      h(Child, {\n        foo: count.value + 1,\n        id: 'test',\n        class: 'c' + count.value,\n        style: { color: count.value ? 'red' : 'green' },\n        onClick: inc,\n      })\n\n    const Child = (props: { foo: number }) => {\n      childUpdated()\n      return h(\n        'div',\n        {\n          class: 'c2',\n          style: { fontWeight: 'bold' },\n        },\n        props.foo,\n      )\n    }\n    Child.props = ['foo']\n\n    const root = document.createElement('div')\n    document.body.appendChild(root)\n    render(h(Hello), root)\n\n    const node = root.children[0] as HTMLElement\n\n    expect(node.getAttribute('id')).toBe('test')\n    expect(node.getAttribute('foo')).toBe(null) // declared as prop\n    expect(node.getAttribute('class')).toBe('c2 c0')\n    expect(node.style.color).toBe('green')\n    expect(node.style.fontWeight).toBe('bold')\n    node.dispatchEvent(new CustomEvent('click'))\n    expect(click).toHaveBeenCalled()\n\n    await nextTick()\n    expect(childUpdated).toHaveBeenCalled()\n    expect(node.getAttribute('id')).toBe('test')\n    expect(node.getAttribute('foo')).toBe(null)\n    expect(node.getAttribute('class')).toBe('c2 c1')\n    expect(node.style.color).toBe('red')\n    expect(node.style.fontWeight).toBe('bold')\n  })\n\n  it('should fallthrough for nested components', async () => {\n    const click = vi.fn()\n    const childUpdated = vi.fn()\n    const grandChildUpdated = vi.fn()\n\n    const Hello = {\n      setup() {\n        const count = ref(0)\n\n        function inc() {\n          count.value++\n          click()\n        }\n\n        return () =>\n          h(Child, {\n            foo: 1,\n            id: 'test',\n            class: 'c' + count.value,\n            style: { color: count.value ? 'red' : 'green' },\n            onClick: inc,\n          })\n      },\n    }\n\n    const Child = {\n      setup(props: any) {\n        onUpdated(childUpdated)\n        // HOC simply passing props down.\n        // this will result in merging the same attrs, but should be deduped by\n        // `mergeProps`.\n        return () => h(GrandChild, props)\n      },\n    }\n\n    const GrandChild = defineComponent({\n      props: {\n        id: String,\n        foo: Number,\n      },\n      setup(props) {\n        onUpdated(grandChildUpdated)\n        return () =>\n          h(\n            'div',\n            {\n              id: props.id,\n              class: 'c2',\n              style: { fontWeight: 'bold' },\n            },\n            props.foo,\n          )\n      },\n    })\n\n    const root = document.createElement('div')\n    document.body.appendChild(root)\n    render(h(Hello), root)\n\n    const node = root.children[0] as HTMLElement\n\n    // with declared props, any parent attr that isn't a prop falls through\n    expect(node.getAttribute('id')).toBe('test')\n    expect(node.getAttribute('class')).toBe('c2 c0')\n    expect(node.style.color).toBe('green')\n    expect(node.style.fontWeight).toBe('bold')\n    node.dispatchEvent(new CustomEvent('click'))\n    expect(click).toHaveBeenCalled()\n\n    // ...while declared ones remain props\n    expect(node.hasAttribute('foo')).toBe(false)\n\n    await nextTick()\n    expect(childUpdated).toHaveBeenCalled()\n    expect(grandChildUpdated).toHaveBeenCalled()\n    expect(node.getAttribute('id')).toBe('test')\n    expect(node.getAttribute('class')).toBe('c2 c1')\n    expect(node.style.color).toBe('red')\n    expect(node.style.fontWeight).toBe('bold')\n\n    expect(node.hasAttribute('foo')).toBe(false)\n  })\n\n  it('should not fallthrough with inheritAttrs: false', () => {\n    const Parent = {\n      render() {\n        return h(Child, { foo: 1, class: 'parent' })\n      },\n    }\n\n    const Child = defineComponent({\n      props: ['foo'],\n      inheritAttrs: false,\n      render() {\n        return h('div', this.foo)\n      },\n    })\n\n    const root = document.createElement('div')\n    document.body.appendChild(root)\n    render(h(Parent), root)\n\n    // should not contain class\n    expect(root.innerHTML).toMatch(`<div>1</div>`)\n  })\n\n  // #3741\n  it('should not fallthrough with inheritAttrs: false from mixins', () => {\n    const Parent = {\n      render() {\n        return h(Child, { foo: 1, class: 'parent' })\n      },\n    }\n\n    const mixin = {\n      inheritAttrs: false,\n    }\n\n    const Child = defineComponent({\n      mixins: [mixin],\n      props: ['foo'],\n      render() {\n        return h('div', this.foo)\n      },\n    })\n\n    const root = document.createElement('div')\n    document.body.appendChild(root)\n    render(h(Parent), root)\n\n    // should not contain class\n    expect(root.innerHTML).toMatch(`<div>1</div>`)\n  })\n\n  it('explicit spreading with inheritAttrs: false', () => {\n    const Parent = {\n      render() {\n        return h(Child, { foo: 1, class: 'parent' })\n      },\n    }\n\n    const Child = defineComponent({\n      props: ['foo'],\n      inheritAttrs: false,\n      render() {\n        return h(\n          'div',\n          mergeProps(\n            {\n              class: 'child',\n            },\n            this.$attrs,\n          ),\n          this.foo,\n        )\n      },\n    })\n\n    const root = document.createElement('div')\n    document.body.appendChild(root)\n    render(h(Parent), root)\n\n    // should merge parent/child classes\n    expect(root.innerHTML).toMatch(`<div class=\"child parent\">1</div>`)\n  })\n\n  it('should warn when fallthrough fails on non-single-root', () => {\n    const Parent = {\n      render() {\n        return h(Child, { foo: 1, class: 'parent', onBar: () => {} })\n      },\n    }\n\n    const Child = defineComponent({\n      props: ['foo'],\n      render() {\n        return [h('div'), h('div')]\n      },\n    })\n\n    const root = document.createElement('div')\n    document.body.appendChild(root)\n    render(h(Parent), root)\n\n    expect(`Extraneous non-props attributes (class)`).toHaveBeenWarned()\n    expect(`Extraneous non-emits event listeners`).toHaveBeenWarned()\n  })\n\n  it('should warn when fallthrough fails on teleport root node', () => {\n    const Parent = {\n      render() {\n        return h(Child, { class: 'parent' })\n      },\n    }\n    const root = document.createElement('div')\n\n    const Child = defineComponent({\n      render() {\n        return h(Teleport, { to: root }, h('div'))\n      },\n    })\n\n    document.body.appendChild(root)\n    render(h(Parent), root)\n\n    expect(`Extraneous non-props attributes (class)`).toHaveBeenWarned()\n  })\n\n  it('should dedupe same listeners when $attrs is used during render', () => {\n    const click = vi.fn()\n    const count = ref(0)\n\n    function inc() {\n      count.value++\n      click()\n    }\n\n    const Parent = {\n      render() {\n        return h(Child, { onClick: inc })\n      },\n    }\n\n    const Child = defineComponent({\n      render() {\n        return h(\n          'div',\n          mergeProps(\n            {\n              onClick: withModifiers(() => {}, ['prevent', 'stop']),\n            },\n            this.$attrs,\n          ),\n        )\n      },\n    })\n\n    const root = document.createElement('div')\n    document.body.appendChild(root)\n    render(h(Parent), root)\n\n    const node = root.children[0] as HTMLElement\n    node.dispatchEvent(new CustomEvent('click'))\n    expect(click).toHaveBeenCalledTimes(1)\n    expect(count.value).toBe(1)\n  })\n\n  it('should not warn when $attrs is used during render', () => {\n    const Parent = {\n      render() {\n        return h(Child, { foo: 1, class: 'parent', onBar: () => {} })\n      },\n    }\n\n    const Child = defineComponent({\n      props: ['foo'],\n      render() {\n        return [h('div'), h('div', this.$attrs)]\n      },\n    })\n\n    const root = document.createElement('div')\n    document.body.appendChild(root)\n    render(h(Parent), root)\n\n    expect(`Extraneous non-props attributes`).not.toHaveBeenWarned()\n    expect(`Extraneous non-emits event listeners`).not.toHaveBeenWarned()\n\n    expect(root.innerHTML).toBe(`<div></div><div class=\"parent\"></div>`)\n  })\n\n  it('should not warn when context.attrs is used during render', () => {\n    const Parent = {\n      render() {\n        return h(Child, { foo: 1, class: 'parent', onBar: () => {} })\n      },\n    }\n\n    const Child = defineComponent({\n      props: ['foo'],\n      setup(_props, { attrs }) {\n        return () => [h('div'), h('div', attrs)]\n      },\n    })\n\n    const root = document.createElement('div')\n    document.body.appendChild(root)\n    render(h(Parent), root)\n\n    expect(`Extraneous non-props attributes`).not.toHaveBeenWarned()\n    expect(`Extraneous non-emits event listeners`).not.toHaveBeenWarned()\n\n    expect(root.innerHTML).toBe(`<div></div><div class=\"parent\"></div>`)\n  })\n\n  it('should not warn when context.attrs is used during render (functional)', () => {\n    const Parent = {\n      render() {\n        return h(Child, { foo: 1, class: 'parent', onBar: () => {} })\n      },\n    }\n\n    const Child: FunctionalComponent = (_, { attrs }) => [\n      h('div'),\n      h('div', attrs),\n    ]\n\n    Child.props = ['foo']\n\n    const root = document.createElement('div')\n    document.body.appendChild(root)\n    render(h(Parent), root)\n\n    expect(`Extraneous non-props attributes`).not.toHaveBeenWarned()\n    expect(`Extraneous non-emits event listeners`).not.toHaveBeenWarned()\n    expect(root.innerHTML).toBe(`<div></div><div class=\"parent\"></div>`)\n  })\n\n  it('should not warn when functional component has optional props', () => {\n    const Parent = {\n      render() {\n        return h(Child, { foo: 1, class: 'parent', onBar: () => {} })\n      },\n    }\n\n    const Child = (props: any) => [h('div'), h('div', { class: props.class })]\n\n    const root = document.createElement('div')\n    document.body.appendChild(root)\n    render(h(Parent), root)\n\n    expect(`Extraneous non-props attributes`).not.toHaveBeenWarned()\n    expect(`Extraneous non-emits event listeners`).not.toHaveBeenWarned()\n    expect(root.innerHTML).toBe(`<div></div><div class=\"parent\"></div>`)\n  })\n\n  it('should warn when functional component has props and does not use attrs', () => {\n    const Parent = {\n      render() {\n        return h(Child, { foo: 1, class: 'parent', onBar: () => {} })\n      },\n    }\n\n    const Child: FunctionalComponent = () => [h('div'), h('div')]\n\n    Child.props = ['foo']\n\n    const root = document.createElement('div')\n    document.body.appendChild(root)\n    render(h(Parent), root)\n\n    expect(`Extraneous non-props attributes`).toHaveBeenWarned()\n    expect(`Extraneous non-emits event listeners`).toHaveBeenWarned()\n    expect(root.innerHTML).toBe(`<div></div><div></div>`)\n  })\n\n  // #677\n  it('should update merged dynamic attrs on optimized child root', async () => {\n    const aria = ref('true')\n    const cls = ref('bar')\n    const Parent = {\n      render() {\n        return h(Child, { 'aria-hidden': aria.value, class: cls.value })\n      },\n    }\n\n    const Child = {\n      props: [],\n      render() {\n        return (openBlock(), createBlock('div'))\n      },\n    }\n\n    const root = document.createElement('div')\n    document.body.appendChild(root)\n    render(h(Parent), root)\n\n    expect(root.innerHTML).toBe(`<div aria-hidden=\"true\" class=\"bar\"></div>`)\n\n    aria.value = 'false'\n    await nextTick()\n    expect(root.innerHTML).toBe(`<div aria-hidden=\"false\" class=\"bar\"></div>`)\n\n    cls.value = 'barr'\n    await nextTick()\n    expect(root.innerHTML).toBe(`<div aria-hidden=\"false\" class=\"barr\"></div>`)\n  })\n\n  it('should not let listener fallthrough when declared in emits (stateful)', () => {\n    const Child = defineComponent({\n      emits: ['click'],\n      render() {\n        return h(\n          'button',\n          {\n            onClick: () => {\n              this.$emit('click', 'custom')\n            },\n          },\n          'hello',\n        )\n      },\n    })\n\n    const onClick = vi.fn()\n    const App = {\n      render() {\n        return h(Child, {\n          onClick,\n        })\n      },\n    }\n\n    const root = document.createElement('div')\n    document.body.appendChild(root)\n    render(h(App), root)\n\n    const node = root.children[0] as HTMLElement\n    node.dispatchEvent(new CustomEvent('click'))\n    expect(onClick).toHaveBeenCalledTimes(1)\n    expect(onClick).toHaveBeenCalledWith('custom')\n  })\n\n  it('should not let listener fallthrough when declared in emits (functional)', () => {\n    const Child: FunctionalComponent<{}, { click: any }> = (_, { emit }) => {\n      // should not be in props\n      expect((_ as any).onClick).toBeUndefined()\n      return h('button', {\n        onClick: () => {\n          emit('click', 'custom')\n        },\n      })\n    }\n    Child.emits = ['click']\n\n    const onClick = vi.fn()\n    const App = {\n      render() {\n        return h(Child, {\n          onClick,\n        })\n      },\n    }\n\n    const root = document.createElement('div')\n    document.body.appendChild(root)\n    render(h(App), root)\n\n    const node = root.children[0] as HTMLElement\n    node.dispatchEvent(new CustomEvent('click'))\n    expect(onClick).toHaveBeenCalledTimes(1)\n    expect(onClick).toHaveBeenCalledWith('custom')\n  })\n\n  it('should support fallthrough for fragments with single element + comments', () => {\n    const click = vi.fn()\n\n    const Hello = {\n      setup() {\n        return () => h(Child, { class: 'foo', onClick: click })\n      },\n    }\n\n    const Child = {\n      setup() {\n        return () => (\n          openBlock(),\n          createBlock(\n            Fragment,\n            null,\n            [\n              createCommentVNode('hello'),\n              h('button'),\n              createCommentVNode('world'),\n            ],\n            PatchFlags.STABLE_FRAGMENT | PatchFlags.DEV_ROOT_FRAGMENT,\n          )\n        )\n      },\n    }\n\n    const root = document.createElement('div')\n    document.body.appendChild(root)\n    render(h(Hello), root)\n\n    expect(root.innerHTML).toBe(\n      `<!--hello--><button class=\"foo\"></button><!--world-->`,\n    )\n    const button = root.children[0] as HTMLElement\n    button.dispatchEvent(new CustomEvent('click'))\n    expect(click).toHaveBeenCalled()\n  })\n\n  it('should support fallthrough for nested dev root fragments', async () => {\n    const toggle = ref(false)\n\n    const Child = {\n      setup() {\n        return () => (\n          openBlock(),\n          createElementBlock(\n            Fragment,\n            null,\n            [\n              createCommentVNode(' comment A '),\n              toggle.value\n                ? (openBlock(), createElementBlock('span', { key: 0 }, 'Foo'))\n                : (openBlock(),\n                  createElementBlock(\n                    Fragment,\n                    { key: 1 },\n                    [\n                      createCommentVNode(' comment B '),\n                      createElementVNode('div', null, 'Bar'),\n                    ],\n                    PatchFlags.STABLE_FRAGMENT | PatchFlags.DEV_ROOT_FRAGMENT,\n                  )),\n            ],\n            PatchFlags.STABLE_FRAGMENT | PatchFlags.DEV_ROOT_FRAGMENT,\n          )\n        )\n      },\n    }\n\n    const Root = {\n      setup() {\n        return () => (openBlock(), createBlock(Child, { class: 'red' }))\n      },\n    }\n\n    const root = document.createElement('div')\n    document.body.appendChild(root)\n    render(h(Root), root)\n\n    expect(root.innerHTML).toBe(\n      `<!-- comment A --><!-- comment B --><div class=\"red\">Bar</div>`,\n    )\n\n    toggle.value = true\n    await nextTick()\n    expect(root.innerHTML).toBe(\n      `<!-- comment A --><span class=\\\"red\\\">Foo</span>`,\n    )\n  })\n\n  // #1989\n  it('should not fallthrough v-model listeners with corresponding declared prop', () => {\n    let textFoo = ''\n    let textBar = ''\n    const click = vi.fn()\n\n    const App = defineComponent({\n      setup() {\n        return () =>\n          h(Child, {\n            modelValue: textFoo,\n            'onUpdate:modelValue': (val: string) => {\n              textFoo = val\n            },\n          })\n      },\n    })\n\n    const Child = defineComponent({\n      props: ['modelValue'],\n      setup(_props, { emit }) {\n        return () =>\n          h(GrandChild, {\n            modelValue: textBar,\n            'onUpdate:modelValue': (val: string) => {\n              textBar = val\n              emit('update:modelValue', 'from Child')\n            },\n          })\n      },\n    })\n\n    const GrandChild = defineComponent({\n      props: ['modelValue'],\n      setup(_props, { emit }) {\n        return () =>\n          h('button', {\n            onClick() {\n              click()\n              emit('update:modelValue', 'from GrandChild')\n            },\n          })\n      },\n    })\n\n    const root = document.createElement('div')\n    document.body.appendChild(root)\n    render(h(App), root)\n\n    const node = root.children[0] as HTMLElement\n\n    node.dispatchEvent(new CustomEvent('click'))\n    expect(click).toHaveBeenCalled()\n    expect(textBar).toBe('from GrandChild')\n    expect(textFoo).toBe('from Child')\n  })\n\n  // covers uncaught regression #10710\n  it('should track this.$attrs access in slots', async () => {\n    const GrandChild = {\n      template: `<slot/>`,\n    }\n    const Child = {\n      components: { GrandChild },\n      template: `<div><GrandChild>{{ $attrs.foo }}</GrandChild></div>`,\n    }\n\n    const obj = ref(1)\n    const App = {\n      render() {\n        return h(Child, { foo: obj.value })\n      },\n    }\n\n    const root = document.createElement('div')\n    createApp(App).mount(root)\n\n    expect(root.innerHTML).toBe('<div foo=\"1\">1</div>')\n\n    obj.value = 2\n    await nextTick()\n    expect(root.innerHTML).toBe('<div foo=\"2\">2</div>')\n  })\n})\n"
  },
  {
    "path": "packages/runtime-core/__tests__/rendererChildren.spec.ts",
    "content": "// reference: https://github.com/vuejs/vue/blob/dev/test/unit/modules/vdom/patch/children.spec.js\nimport {\n  type TestElement,\n  TestNodeTypes,\n  h,\n  nodeOps,\n  render,\n  serialize,\n  serializeInner,\n} from '@vue/runtime-test'\nfunction toSpan(content: any) {\n  if (typeof content === 'string') {\n    return h('span', content.toString())\n  } else {\n    return h('span', { key: content }, content.toString())\n  }\n}\n\nconst inner = (c: TestElement) => serializeInner(c)\n\nfunction shuffle(array: Array<any>) {\n  let currentIndex = array.length\n  let temporaryValue\n  let randomIndex\n\n  // while there remain elements to shuffle...\n  while (currentIndex !== 0) {\n    // pick a remaining element...\n    randomIndex = Math.floor(Math.random() * currentIndex)\n    currentIndex -= 1\n    // and swap it with the current element.\n    temporaryValue = array[currentIndex]\n    array[currentIndex] = array[randomIndex]\n    array[randomIndex] = temporaryValue\n  }\n  return array\n}\n\ntest('should patch previously empty children', () => {\n  const root = nodeOps.createElement('div')\n\n  render(h('div', []), root)\n  expect(inner(root)).toBe('<div></div>')\n\n  render(h('div', ['hello']), root)\n  expect(inner(root)).toBe('<div>hello</div>')\n})\n\ntest('should patch previously null children', () => {\n  const root = nodeOps.createElement('div')\n\n  render(h('div'), root)\n  expect(inner(root)).toBe('<div></div>')\n\n  render(h('div', ['hello']), root)\n  expect(inner(root)).toBe('<div>hello</div>')\n})\n\ntest('array children -> text children', () => {\n  const root = nodeOps.createElement('div')\n  render(h('div', [h('div')]), root)\n  expect(inner(root)).toBe('<div><div></div></div>')\n\n  render(h('div', 'hello'), root)\n  expect(inner(root)).toBe('<div>hello</div>')\n})\n\ntest('plain object child', () => {\n  const root = nodeOps.createElement('div')\n  const foo = { foo: '1' }\n  // @ts-expect-error\n  render(h('div', null, [foo]), root)\n  expect('Invalid VNode type').not.toHaveBeenWarned()\n  expect(inner(root)).toBe('<div>[object Object]</div>')\n})\n\ndescribe('renderer: keyed children', () => {\n  let root: TestElement\n  let elm: TestElement\n  const renderChildren = (arr: number[]) => {\n    render(h('div', arr.map(toSpan)), root)\n    return root.children[0] as TestElement\n  }\n\n  beforeEach(() => {\n    root = nodeOps.createElement('div')\n    render(h('div', { id: 1 }, 'hello'), root)\n  })\n\n  test('append', () => {\n    elm = renderChildren([1])\n    expect(elm.children.length).toBe(1)\n\n    elm = renderChildren([1, 2, 3])\n    expect(elm.children.length).toBe(3)\n    expect(serialize(elm.children[1])).toBe('<span>2</span>')\n    expect(serialize(elm.children[2])).toBe('<span>3</span>')\n  })\n\n  test('prepend', () => {\n    elm = renderChildren([4, 5])\n    expect(elm.children.length).toBe(2)\n\n    elm = renderChildren([1, 2, 3, 4, 5])\n    expect(elm.children.length).toBe(5)\n    expect((elm.children as TestElement[]).map(inner)).toEqual([\n      '1',\n      '2',\n      '3',\n      '4',\n      '5',\n    ])\n  })\n\n  test('insert in middle', () => {\n    elm = renderChildren([1, 2, 4, 5])\n    expect(elm.children.length).toBe(4)\n\n    elm = renderChildren([1, 2, 3, 4, 5])\n    expect(elm.children.length).toBe(5)\n    expect((elm.children as TestElement[]).map(inner)).toEqual([\n      '1',\n      '2',\n      '3',\n      '4',\n      '5',\n    ])\n  })\n\n  test('insert at beginning and end', () => {\n    elm = renderChildren([2, 3, 4])\n    expect(elm.children.length).toBe(3)\n\n    elm = renderChildren([1, 2, 3, 4, 5])\n    expect(elm.children.length).toBe(5)\n    expect((elm.children as TestElement[]).map(inner)).toEqual([\n      '1',\n      '2',\n      '3',\n      '4',\n      '5',\n    ])\n  })\n\n  test('insert to empty parent', () => {\n    elm = renderChildren([])\n    expect(elm.children.length).toBe(0)\n\n    elm = renderChildren([1, 2, 3, 4, 5])\n    expect(elm.children.length).toBe(5)\n    expect((elm.children as TestElement[]).map(inner)).toEqual([\n      '1',\n      '2',\n      '3',\n      '4',\n      '5',\n    ])\n  })\n\n  test('remove all children from parent', () => {\n    elm = renderChildren([1, 2, 3, 4, 5])\n    expect(elm.children.length).toBe(5)\n    expect((elm.children as TestElement[]).map(inner)).toEqual([\n      '1',\n      '2',\n      '3',\n      '4',\n      '5',\n    ])\n\n    render(h('div'), root)\n    expect(elm.children.length).toBe(0)\n  })\n\n  test('remove from beginning', () => {\n    elm = renderChildren([1, 2, 3, 4, 5])\n    expect(elm.children.length).toBe(5)\n\n    elm = renderChildren([3, 4, 5])\n    expect(elm.children.length).toBe(3)\n    expect((elm.children as TestElement[]).map(inner)).toEqual(['3', '4', '5'])\n  })\n\n  test('remove from end', () => {\n    elm = renderChildren([1, 2, 3, 4, 5])\n    expect(elm.children.length).toBe(5)\n\n    elm = renderChildren([1, 2, 3])\n    expect(elm.children.length).toBe(3)\n    expect((elm.children as TestElement[]).map(inner)).toEqual(['1', '2', '3'])\n  })\n\n  test('remove from middle', () => {\n    elm = renderChildren([1, 2, 3, 4, 5])\n    expect(elm.children.length).toBe(5)\n\n    elm = renderChildren([1, 2, 4, 5])\n    expect(elm.children.length).toBe(4)\n    expect((elm.children as TestElement[]).map(inner)).toEqual([\n      '1',\n      '2',\n      '4',\n      '5',\n    ])\n  })\n\n  test('moving single child forward', () => {\n    elm = renderChildren([1, 2, 3, 4])\n    expect(elm.children.length).toBe(4)\n\n    elm = renderChildren([2, 3, 1, 4])\n    expect(elm.children.length).toBe(4)\n    expect((elm.children as TestElement[]).map(inner)).toEqual([\n      '2',\n      '3',\n      '1',\n      '4',\n    ])\n  })\n\n  test('moving single child backwards', () => {\n    elm = renderChildren([1, 2, 3, 4])\n    expect(elm.children.length).toBe(4)\n\n    elm = renderChildren([1, 4, 2, 3])\n    expect(elm.children.length).toBe(4)\n    expect((elm.children as TestElement[]).map(inner)).toEqual([\n      '1',\n      '4',\n      '2',\n      '3',\n    ])\n  })\n\n  test('moving single child to end', () => {\n    elm = renderChildren([1, 2, 3])\n    expect(elm.children.length).toBe(3)\n\n    elm = renderChildren([2, 3, 1])\n    expect(elm.children.length).toBe(3)\n    expect((elm.children as TestElement[]).map(inner)).toEqual(['2', '3', '1'])\n  })\n\n  test('swap first and last', () => {\n    elm = renderChildren([1, 2, 3, 4])\n    expect(elm.children.length).toBe(4)\n\n    elm = renderChildren([4, 2, 3, 1])\n    expect(elm.children.length).toBe(4)\n    expect((elm.children as TestElement[]).map(inner)).toEqual([\n      '4',\n      '2',\n      '3',\n      '1',\n    ])\n  })\n\n  test('move to left & replace', () => {\n    elm = renderChildren([1, 2, 3, 4, 5])\n    expect(elm.children.length).toBe(5)\n\n    elm = renderChildren([4, 1, 2, 3, 6])\n    expect(elm.children.length).toBe(5)\n    expect((elm.children as TestElement[]).map(inner)).toEqual([\n      '4',\n      '1',\n      '2',\n      '3',\n      '6',\n    ])\n  })\n\n  test('move to left and leaves hold', () => {\n    elm = renderChildren([1, 4, 5])\n    expect(elm.children.length).toBe(3)\n\n    elm = renderChildren([4, 6])\n    expect((elm.children as TestElement[]).map(inner)).toEqual(['4', '6'])\n  })\n\n  test('moved and set to undefined element ending at the end', () => {\n    elm = renderChildren([2, 4, 5])\n    expect(elm.children.length).toBe(3)\n\n    elm = renderChildren([4, 5, 3])\n    expect(elm.children.length).toBe(3)\n    expect((elm.children as TestElement[]).map(inner)).toEqual(['4', '5', '3'])\n  })\n\n  test('reverse element', () => {\n    elm = renderChildren([1, 2, 3, 4, 5, 6, 7, 8])\n    expect(elm.children.length).toBe(8)\n\n    elm = renderChildren([8, 7, 6, 5, 4, 3, 2, 1])\n    expect((elm.children as TestElement[]).map(inner)).toEqual([\n      '8',\n      '7',\n      '6',\n      '5',\n      '4',\n      '3',\n      '2',\n      '1',\n    ])\n  })\n\n  test('something', () => {\n    elm = renderChildren([0, 1, 2, 3, 4, 5])\n    expect(elm.children.length).toBe(6)\n\n    elm = renderChildren([4, 3, 2, 1, 5, 0])\n    expect((elm.children as TestElement[]).map(inner)).toEqual([\n      '4',\n      '3',\n      '2',\n      '1',\n      '5',\n      '0',\n    ])\n  })\n\n  test('random shuffle', () => {\n    const elms = 14\n    const samples = 5\n    const arr = [...Array(elms).keys()]\n    const opacities: string[] = []\n\n    function spanNumWithOpacity(n: number, o: string) {\n      return h('span', { key: n, style: { opacity: o } }, n.toString())\n    }\n\n    for (let n = 0; n < samples; ++n) {\n      render(\n        h(\n          'span',\n          arr.map(n => spanNumWithOpacity(n, '1')),\n        ),\n        root,\n      )\n      elm = root.children[0] as TestElement\n\n      for (let i = 0; i < elms; ++i) {\n        expect(serializeInner(elm.children[i] as TestElement)).toBe(\n          i.toString(),\n        )\n        opacities[i] = Math.random().toFixed(5).toString()\n      }\n\n      const shufArr = shuffle(arr.slice(0))\n      render(\n        h(\n          'span',\n          arr.map(n => spanNumWithOpacity(shufArr[n], opacities[n])),\n        ),\n        root,\n      )\n      elm = root.children[0] as TestElement\n      for (let i = 0; i < elms; ++i) {\n        expect(serializeInner(elm.children[i] as TestElement)).toBe(\n          shufArr[i].toString(),\n        )\n        expect(elm.children[i]).toMatchObject({\n          props: {\n            style: {\n              opacity: opacities[i],\n            },\n          },\n        })\n      }\n    }\n  })\n\n  test('children with the same key but with different tag', () => {\n    render(\n      h('div', [\n        h('div', { key: 1 }, 'one'),\n        h('div', { key: 2 }, 'two'),\n        h('div', { key: 3 }, 'three'),\n        h('div', { key: 4 }, 'four'),\n      ]),\n      root,\n    )\n    elm = root.children[0] as TestElement\n    expect((elm.children as TestElement[]).map(c => c.tag)).toEqual([\n      'div',\n      'div',\n      'div',\n      'div',\n    ])\n    expect((elm.children as TestElement[]).map(inner)).toEqual([\n      'one',\n      'two',\n      'three',\n      'four',\n    ])\n\n    render(\n      h('div', [\n        h('div', { key: 4 }, 'four'),\n        h('span', { key: 3 }, 'three'),\n        h('span', { key: 2 }, 'two'),\n        h('div', { key: 1 }, 'one'),\n      ]),\n      root,\n    )\n    expect((elm.children as TestElement[]).map(c => c.tag)).toEqual([\n      'div',\n      'span',\n      'span',\n      'div',\n    ])\n    expect((elm.children as TestElement[]).map(inner)).toEqual([\n      'four',\n      'three',\n      'two',\n      'one',\n    ])\n  })\n\n  test('children with the same tag, same key, but one with data and one without data', () => {\n    render(h('div', [h('div', { class: 'hi' }, 'one')]), root)\n    elm = root.children[0] as TestElement\n    expect(elm.children[0]).toMatchObject({\n      props: {\n        class: 'hi',\n      },\n    })\n\n    render(h('div', [h('div', 'four')]), root)\n    elm = root.children[0] as TestElement\n    expect(elm.children[0] as TestElement).toMatchObject({\n      props: {\n        // in the DOM renderer this will be ''\n        // but the test renderer simply sets whatever value it receives.\n        class: null,\n      },\n    })\n    expect(serialize(elm.children[0])).toBe(`<div>four</div>`)\n  })\n\n  test('should warn with duplicate keys', () => {\n    renderChildren([1, 2, 3, 4, 5])\n    renderChildren([1, 6, 6, 3, 5])\n    expect(`Duplicate keys`).toHaveBeenWarned()\n  })\n})\n\ndescribe('renderer: unkeyed children', () => {\n  let root: TestElement\n  let elm: TestElement\n  const renderChildren = (arr: Array<number | string>) => {\n    render(h('div', arr.map(toSpan)), root)\n    return root.children[0] as TestElement\n  }\n\n  beforeEach(() => {\n    root = nodeOps.createElement('div')\n    render(h('div', { id: 1 }, 'hello'), root)\n  })\n\n  test('move a key in non-keyed nodes with a size up', () => {\n    elm = renderChildren([1, 'a', 'b', 'c'])\n    expect(elm.children.length).toBe(4)\n    expect((elm.children as TestElement[]).map(inner)).toEqual([\n      '1',\n      'a',\n      'b',\n      'c',\n    ])\n\n    elm = renderChildren(['d', 'a', 'b', 'c', 1, 'e'])\n    expect(elm.children.length).toBe(6)\n    expect((elm.children as TestElement[]).map(inner)).toEqual([\n      'd',\n      'a',\n      'b',\n      'c',\n      '1',\n      'e',\n    ])\n  })\n\n  test('append elements with updating children without keys', () => {\n    elm = renderChildren(['hello'])\n    expect((elm.children as TestElement[]).map(inner)).toEqual(['hello'])\n\n    elm = renderChildren(['hello', 'world'])\n    expect((elm.children as TestElement[]).map(inner)).toEqual([\n      'hello',\n      'world',\n    ])\n  })\n\n  test('unmoved text nodes with updating children without keys', () => {\n    render(h('div', ['text', h('span', ['hello'])]), root)\n\n    elm = root.children[0] as TestElement\n    expect(elm.children[0]).toMatchObject({\n      type: TestNodeTypes.TEXT,\n      text: 'text',\n    })\n\n    render(h('div', ['text', h('span', ['hello'])]), root)\n\n    elm = root.children[0] as TestElement\n    expect(elm.children[0]).toMatchObject({\n      type: TestNodeTypes.TEXT,\n      text: 'text',\n    })\n  })\n\n  test('changing text children with updating children without keys', () => {\n    render(h('div', ['text', h('span', ['hello'])]), root)\n\n    elm = root.children[0] as TestElement\n    expect(elm.children[0]).toMatchObject({\n      type: TestNodeTypes.TEXT,\n      text: 'text',\n    })\n\n    render(h('div', ['text2', h('span', ['hello'])]), root)\n\n    elm = root.children[0] as TestElement\n    expect(elm.children[0]).toMatchObject({\n      type: TestNodeTypes.TEXT,\n      text: 'text2',\n    })\n  })\n\n  test('prepend element with updating children without keys', () => {\n    render(h('div', [h('span', ['world'])]), root)\n    elm = root.children[0] as TestElement\n    expect((elm.children as TestElement[]).map(inner)).toEqual(['world'])\n\n    render(h('div', [h('span', ['hello']), h('span', ['world'])]), root)\n    expect((elm.children as TestElement[]).map(inner)).toEqual([\n      'hello',\n      'world',\n    ])\n  })\n\n  test('prepend element of different tag type with updating children without keys', () => {\n    render(h('div', [h('span', ['world'])]), root)\n    elm = root.children[0] as TestElement\n    expect((elm.children as TestElement[]).map(inner)).toEqual(['world'])\n\n    render(h('div', [h('div', ['hello']), h('span', ['world'])]), root)\n    expect((elm.children as TestElement[]).map(c => c.tag)).toEqual([\n      'div',\n      'span',\n    ])\n    expect((elm.children as TestElement[]).map(inner)).toEqual([\n      'hello',\n      'world',\n    ])\n  })\n\n  test('remove elements with updating children without keys', () => {\n    render(\n      h('div', [h('span', ['one']), h('span', ['two']), h('span', ['three'])]),\n      root,\n    )\n    elm = root.children[0] as TestElement\n    expect((elm.children as TestElement[]).map(inner)).toEqual([\n      'one',\n      'two',\n      'three',\n    ])\n\n    render(h('div', [h('span', ['one']), h('span', ['three'])]), root)\n    elm = root.children[0] as TestElement\n    expect((elm.children as TestElement[]).map(inner)).toEqual(['one', 'three'])\n  })\n\n  test('remove a single text node with updating children without keys', () => {\n    render(h('div', ['one']), root)\n    elm = root.children[0] as TestElement\n    expect(serializeInner(elm)).toBe('one')\n\n    render(h('div'), root)\n    expect(serializeInner(elm)).toBe('')\n  })\n\n  test('remove a single text node when children are updated', () => {\n    render(h('div', ['one']), root)\n    elm = root.children[0] as TestElement\n    expect(serializeInner(elm)).toBe('one')\n\n    render(h('div', [h('div', ['two']), h('span', ['three'])]), root)\n    elm = root.children[0] as TestElement\n    expect((elm.children as TestElement[]).map(inner)).toEqual(['two', 'three'])\n  })\n\n  test('remove a text node among other elements', () => {\n    render(h('div', ['one', h('span', ['two'])]), root)\n    elm = root.children[0] as TestElement\n    expect((elm.children as TestElement[]).map(c => serialize(c))).toEqual([\n      'one',\n      '<span>two</span>',\n    ])\n\n    render(h('div', [h('div', ['three'])]), root)\n    elm = root.children[0] as TestElement\n    expect(elm.children.length).toBe(1)\n    expect(serialize(elm.children[0])).toBe('<div>three</div>')\n  })\n\n  test('reorder elements', () => {\n    render(\n      h('div', [h('span', ['one']), h('div', ['two']), h('b', ['three'])]),\n      root,\n    )\n    elm = root.children[0] as TestElement\n    expect((elm.children as TestElement[]).map(inner)).toEqual([\n      'one',\n      'two',\n      'three',\n    ])\n\n    render(\n      h('div', [h('b', ['three']), h('div', ['two']), h('span', ['one'])]),\n      root,\n    )\n    elm = root.children[0] as TestElement\n    expect((elm.children as TestElement[]).map(inner)).toEqual([\n      'three',\n      'two',\n      'one',\n    ])\n  })\n\n  // #6502\n  test('should not de-opt when both head and tail change', () => {\n    render(h('div', [null, h('div'), null]), root)\n    elm = root.children[0] as TestElement\n    const original = elm.children[1]\n\n    render(h('div', [h('p'), h('div'), h('p')]), root)\n    elm = root.children[0] as TestElement\n    const postPatch = elm.children[1]\n\n    expect(postPatch).toBe(original)\n  })\n})\n"
  },
  {
    "path": "packages/runtime-core/__tests__/rendererComponent.spec.ts",
    "content": "import {\n  type Ref,\n  type SetupContext,\n  type VNode,\n  h,\n  inject,\n  nextTick,\n  nodeOps,\n  onMounted,\n  provide,\n  ref,\n  render,\n  serializeInner,\n  watch,\n} from '@vue/runtime-test'\n\ndescribe('renderer: component', () => {\n  test('should update parent(hoc) component host el when child component self update', async () => {\n    const value = ref(true)\n    let parentVnode: VNode\n    let childVnode1: VNode\n    let childVnode2: VNode\n\n    const Parent = {\n      render: () => {\n        // let Parent first rerender\n        return (parentVnode = h(Child))\n      },\n    }\n\n    const Child = {\n      render: () => {\n        return value.value\n          ? (childVnode1 = h('div'))\n          : (childVnode2 = h('span'))\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(Parent), root)\n    expect(serializeInner(root)).toBe(`<div></div>`)\n    expect(parentVnode!.el).toBe(childVnode1!.el)\n\n    value.value = false\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<span></span>`)\n    expect(parentVnode!.el).toBe(childVnode2!.el)\n  })\n\n  it('should create an Component with props', () => {\n    const Comp = {\n      render: () => {\n        return h('div')\n      },\n    }\n    const root = nodeOps.createElement('div')\n    render(h(Comp, { id: 'foo', class: 'bar' }), root)\n    expect(serializeInner(root)).toBe(`<div id=\"foo\" class=\"bar\"></div>`)\n  })\n\n  it('should create an Component with direct text children', () => {\n    const Comp = {\n      render: () => {\n        return h('div', 'test')\n      },\n    }\n    const root = nodeOps.createElement('div')\n    render(h(Comp, { id: 'foo', class: 'bar' }), root)\n    expect(serializeInner(root)).toBe(`<div id=\"foo\" class=\"bar\">test</div>`)\n  })\n\n  it('should update an Component tag which is already mounted', () => {\n    const Comp1 = {\n      render: () => {\n        return h('div', 'foo')\n      },\n    }\n    const root = nodeOps.createElement('div')\n    render(h(Comp1), root)\n    expect(serializeInner(root)).toBe('<div>foo</div>')\n\n    const Comp2 = {\n      render: () => {\n        return h('span', 'foo')\n      },\n    }\n    render(h(Comp2), root)\n    expect(serializeInner(root)).toBe('<span>foo</span>')\n  })\n\n  // #2072\n  it('should not update Component if only changed props are declared emit listeners', () => {\n    const Comp1 = {\n      emits: ['foo'],\n      updated: vi.fn(),\n      render: () => null,\n    }\n    const root = nodeOps.createElement('div')\n    render(\n      h(Comp1, {\n        onFoo: () => {},\n      }),\n      root,\n    )\n    render(\n      h(Comp1, {\n        onFoo: () => {},\n      }),\n      root,\n    )\n    expect(Comp1.updated).not.toHaveBeenCalled()\n  })\n\n  // #2043\n  test('component child synchronously updating parent state should trigger parent re-render', async () => {\n    const App = {\n      setup() {\n        const n = ref(0)\n        provide('foo', n)\n        return () => {\n          return [h('div', n.value), h(Child)]\n        }\n      },\n    }\n\n    const Child = {\n      setup() {\n        const n = inject<Ref<number>>('foo')!\n        n.value++\n\n        return () => {\n          return h('div', n.value)\n        }\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(App), root)\n    expect(serializeInner(root)).toBe(`<div>0</div><div>1</div>`)\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<div>1</div><div>1</div>`)\n  })\n\n  // #2170\n  test('instance.$el should be exposed to watch options', async () => {\n    function returnThis(this: any, _arg: any) {\n      return this\n    }\n    const propWatchSpy = vi.fn(returnThis)\n    const dataWatchSpy = vi.fn(returnThis)\n    let instance: any\n    const Comp = {\n      props: {\n        testProp: String,\n      },\n\n      data() {\n        return {\n          testData: undefined,\n        }\n      },\n\n      watch: {\n        testProp() {\n          // @ts-expect-error\n          propWatchSpy(this.$el)\n        },\n        testData() {\n          // @ts-expect-error\n          dataWatchSpy(this.$el)\n        },\n      },\n\n      created() {\n        instance = this\n      },\n\n      render() {\n        return h('div')\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(Comp), root)\n    await nextTick()\n    expect(propWatchSpy).not.toHaveBeenCalled()\n    expect(dataWatchSpy).not.toHaveBeenCalled()\n\n    render(h(Comp, { testProp: 'prop ' }), root)\n    await nextTick()\n    expect(propWatchSpy).toHaveBeenCalledWith(instance.$el)\n\n    instance.testData = 1\n    await nextTick()\n    expect(dataWatchSpy).toHaveBeenCalledWith(instance.$el)\n  })\n\n  // #2200\n  test('component child updating parent state in pre-flush should trigger parent re-render', async () => {\n    const outer = ref(0)\n    const App = {\n      setup() {\n        const inner = ref(0)\n\n        return () => {\n          return [\n            h('div', inner.value),\n            h(Child, {\n              value: outer.value,\n              onUpdate: (val: number) => (inner.value = val),\n            }),\n          ]\n        }\n      },\n    }\n\n    const Child = {\n      props: ['value'],\n      setup(props: any, { emit }: SetupContext) {\n        watch(\n          () => props.value,\n          (val: number) => emit('update', val),\n        )\n\n        return () => {\n          return h('div', props.value)\n        }\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(App), root)\n    expect(serializeInner(root)).toBe(`<div>0</div><div>0</div>`)\n\n    outer.value++\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<div>1</div><div>1</div>`)\n  })\n\n  test('child only updates once when triggered in multiple ways', async () => {\n    const a = ref(0)\n    const calls: string[] = []\n\n    const Parent = {\n      setup() {\n        return () => {\n          calls.push('render parent')\n          return h(Child, { count: a.value }, () => a.value)\n        }\n      },\n    }\n\n    const Child = {\n      props: ['count'],\n      setup(props: any) {\n        return () => {\n          calls.push('render child')\n          return `${props.count} - ${a.value}`\n        }\n      },\n    }\n\n    render(h(Parent), nodeOps.createElement('div'))\n    expect(calls).toEqual(['render parent', 'render child'])\n\n    // This will trigger child rendering directly, as well as via a prop change\n    a.value++\n    await nextTick()\n    expect(calls).toEqual([\n      'render parent',\n      'render child',\n      'render parent',\n      'render child',\n    ])\n  })\n\n  // #7745\n  test(`an earlier update doesn't lead to excessive subsequent updates`, async () => {\n    const globalCount = ref(0)\n    const parentCount = ref(0)\n    const calls: string[] = []\n\n    const Root = {\n      setup() {\n        return () => {\n          calls.push('render root')\n          return h(Parent, { count: globalCount.value })\n        }\n      },\n    }\n\n    const Parent = {\n      props: ['count'],\n      setup(props: any) {\n        return () => {\n          calls.push('render parent')\n          return [\n            `${globalCount.value} - ${props.count}`,\n            h(Child, { count: parentCount.value }),\n          ]\n        }\n      },\n    }\n\n    const Child = {\n      props: ['count'],\n      setup(props: any) {\n        watch(\n          () => props.count,\n          () => {\n            calls.push('child watcher')\n            globalCount.value = props.count\n          },\n        )\n\n        return () => {\n          calls.push('render child')\n        }\n      },\n    }\n\n    render(h(Root), nodeOps.createElement('div'))\n    expect(calls).toEqual(['render root', 'render parent', 'render child'])\n\n    parentCount.value++\n    await nextTick()\n    expect(calls).toEqual([\n      'render root',\n      'render parent',\n      'render child',\n      'render parent',\n      'child watcher',\n      'render child',\n      'render root',\n      'render parent',\n    ])\n  })\n\n  // #2521\n  test('should pause tracking deps when initializing legacy options', async () => {\n    let childInstance = null as any\n    const Child = {\n      props: ['foo'],\n      data() {\n        return {\n          count: 0,\n        }\n      },\n      watch: {\n        foo: {\n          immediate: true,\n          handler() {\n            ;(this as any).count\n          },\n        },\n      },\n      created() {\n        childInstance = this as any\n        childInstance.count\n      },\n      render() {\n        return h('h1', (this as any).count)\n      },\n    }\n\n    const App = {\n      setup() {\n        return () => h(Child)\n      },\n      updated: vi.fn(),\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(App), root)\n    expect(App.updated).toHaveBeenCalledTimes(0)\n\n    childInstance.count++\n    await nextTick()\n    expect(App.updated).toHaveBeenCalledTimes(0)\n  })\n\n  describe('render with access caches', () => {\n    // #3297\n    test('should not set the access cache in the data() function (production mode)', () => {\n      const Comp = {\n        data() {\n          ;(this as any).foo\n          return { foo: 1 }\n        },\n        render() {\n          return h('h1', (this as any).foo)\n        },\n      }\n      const root = nodeOps.createElement('div')\n\n      __DEV__ = false\n      render(h(Comp), root)\n      __DEV__ = true\n      expect(serializeInner(root)).toBe(`<h1>1</h1>`)\n    })\n  })\n\n  test('the component VNode should be cloned when reusing it', () => {\n    const App = {\n      render() {\n        const c = [h(Comp)]\n        return [c, c, c]\n      },\n    }\n\n    const ids: number[] = []\n    const Comp = {\n      render: () => h('h1'),\n      beforeUnmount() {\n        ids.push((this as any).$.uid)\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(App), root)\n    expect(serializeInner(root)).toBe(`<h1></h1><h1></h1><h1></h1>`)\n\n    render(null, root)\n    expect(serializeInner(root)).toBe(``)\n    expect(ids).toEqual([ids[0], ids[0] + 1, ids[0] + 2])\n  })\n\n  test('child component props update should not lead to double update', async () => {\n    const text = ref(0)\n    const spy = vi.fn()\n\n    const App = {\n      render() {\n        return h(Comp, { text: text.value })\n      },\n    }\n\n    const Comp = {\n      props: ['text'],\n      render(this: any) {\n        spy()\n        return h('h1', this.text)\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(App), root)\n\n    expect(serializeInner(root)).toBe(`<h1>0</h1>`)\n    expect(spy).toHaveBeenCalledTimes(1)\n\n    text.value++\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<h1>1</h1>`)\n    expect(spy).toHaveBeenCalledTimes(2)\n  })\n\n  it('should warn accessing `this` in a <script setup> template', () => {\n    const App = {\n      setup() {\n        return {\n          __isScriptSetup: true,\n        }\n      },\n\n      render(this: any) {\n        return this.$attrs.id\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(App), root)\n\n    expect(\n      `Property '$attrs' was accessed via 'this'. Avoid using 'this' in templates.`,\n    ).toHaveBeenWarned()\n  })\n\n  test('should not update child component if style is not changed', async () => {\n    const text = ref(0)\n    const spy = vi.fn()\n\n    const ClientOnly = {\n      setup(_: any, { slots }: SetupContext) {\n        const mounted = ref(false)\n        onMounted(() => {\n          mounted.value = true\n        })\n        return () => {\n          if (mounted.value) {\n            return slots.default!()\n          }\n        }\n      },\n    }\n\n    const App = {\n      render() {\n        return h(ClientOnly, null, {\n          default: () => [\n            h('span', null, [text.value]),\n            h(Comp, { style: { width: '100%' } }),\n          ],\n        })\n      },\n    }\n\n    const Comp = {\n      render(this: any) {\n        spy()\n        return null\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(App), root)\n    expect(serializeInner(root)).toBe(`<!---->`)\n    await nextTick()\n\n    expect(serializeInner(root)).toBe(`<span>0</span><!---->`)\n    expect(spy).toHaveBeenCalledTimes(1)\n\n    text.value++\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<span>1</span><!---->`)\n    // expect Comp to not be re-rendered\n    expect(spy).toHaveBeenCalledTimes(1)\n  })\n})\n"
  },
  {
    "path": "packages/runtime-core/__tests__/rendererElement.spec.ts",
    "content": "import {\n  type TestElement,\n  h,\n  serializeInner as inner,\n  nodeOps,\n  render,\n} from '@vue/runtime-test'\n\ndescribe('renderer: element', () => {\n  let root: TestElement\n\n  beforeEach(() => {\n    root = nodeOps.createElement('div')\n  })\n\n  it('should create an element', () => {\n    render(h('div'), root)\n    expect(inner(root)).toBe('<div></div>')\n  })\n\n  it('should create an element with props', () => {\n    render(h('div', { id: 'foo', class: 'bar' }), root)\n    expect(inner(root)).toBe('<div id=\"foo\" class=\"bar\"></div>')\n  })\n\n  it('should create an element with direct text children', () => {\n    render(h('div', ['foo', ' ', 'bar']), root)\n    expect(inner(root)).toBe('<div>foo bar</div>')\n  })\n\n  it('should create an element with direct text children and props', () => {\n    render(h('div', { id: 'foo' }, ['bar']), root)\n    expect(inner(root)).toBe('<div id=\"foo\">bar</div>')\n  })\n\n  it('should update an element tag which is already mounted', () => {\n    render(h('div', ['foo']), root)\n    expect(inner(root)).toBe('<div>foo</div>')\n\n    render(h('span', ['foo']), root)\n    expect(inner(root)).toBe('<span>foo</span>')\n  })\n\n  it('should update element props which is already mounted', () => {\n    render(h('div', { id: 'bar' }, ['foo']), root)\n    expect(inner(root)).toBe('<div id=\"bar\">foo</div>')\n\n    render(h('div', { id: 'baz', class: 'bar' }, ['foo']), root)\n    expect(inner(root)).toBe('<div id=\"baz\" class=\"bar\">foo</div>')\n  })\n})\n"
  },
  {
    "path": "packages/runtime-core/__tests__/rendererFragment.spec.ts",
    "content": "import {\n  Fragment,\n  NodeOpTypes,\n  type TestElement,\n  TestNodeTypes,\n  type VNode,\n  createBlock,\n  createCommentVNode,\n  createTextVNode,\n  createVNode,\n  dumpOps,\n  h,\n  nodeOps,\n  openBlock,\n  render,\n  resetOps,\n  serializeInner,\n} from '@vue/runtime-test'\nimport { PatchFlags } from '@vue/shared'\nimport { renderList } from '../src/helpers/renderList'\n\ndescribe('renderer: fragment', () => {\n  it('should allow returning multiple component root nodes', () => {\n    const App = {\n      render() {\n        return [h('div', 'one'), 'two']\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(App), root)\n\n    expect(serializeInner(root)).toBe(`<div>one</div>two`)\n    expect(root.children.length).toBe(4)\n    expect(root.children[0]).toMatchObject({\n      type: TestNodeTypes.TEXT,\n      text: '',\n    })\n    expect(root.children[1]).toMatchObject({\n      type: TestNodeTypes.ELEMENT,\n      tag: 'div',\n    })\n    expect((root.children[1] as TestElement).children[0]).toMatchObject({\n      type: TestNodeTypes.TEXT,\n      text: 'one',\n    })\n    expect(root.children[2]).toMatchObject({\n      type: TestNodeTypes.TEXT,\n      text: 'two',\n    })\n    expect(root.children[3]).toMatchObject({\n      type: TestNodeTypes.TEXT,\n      text: '',\n    })\n  })\n\n  it('explicitly create fragments', () => {\n    const root = nodeOps.createElement('div')\n    render(h('div', [h(Fragment, [h('div', 'one'), 'two'])]), root)\n    const parent = root.children[0] as TestElement\n    expect(serializeInner(parent)).toBe(`<div>one</div>two`)\n  })\n\n  it('patch fragment children (manual, keyed)', () => {\n    const root = nodeOps.createElement('div')\n    render(\n      h(Fragment, [h('div', { key: 1 }, 'one'), h('div', { key: 2 }, 'two')]),\n      root,\n    )\n    expect(serializeInner(root)).toBe(`<div>one</div><div>two</div>`)\n\n    resetOps()\n    render(\n      h(Fragment, [h('div', { key: 2 }, 'two'), h('div', { key: 1 }, 'one')]),\n      root,\n    )\n    expect(serializeInner(root)).toBe(`<div>two</div><div>one</div>`)\n    const ops = dumpOps()\n    // should be moving nodes instead of re-creating or patching them\n    expect(ops).toMatchObject([\n      {\n        type: NodeOpTypes.INSERT,\n      },\n    ])\n  })\n\n  it('patch fragment children (manual, unkeyed)', () => {\n    const root = nodeOps.createElement('div')\n    render(h(Fragment, [h('div', 'one'), h('div', 'two')]), root)\n    expect(serializeInner(root)).toBe(`<div>one</div><div>two</div>`)\n\n    resetOps()\n    render(h(Fragment, [h('div', 'two'), h('div', 'one')]), root)\n    expect(serializeInner(root)).toBe(`<div>two</div><div>one</div>`)\n    const ops = dumpOps()\n    // should be patching nodes instead of moving or re-creating them\n    expect(ops).toMatchObject([\n      {\n        type: NodeOpTypes.SET_ELEMENT_TEXT,\n      },\n      {\n        type: NodeOpTypes.SET_ELEMENT_TEXT,\n      },\n    ])\n  })\n\n  it('patch fragment children (compiler generated, unkeyed)', () => {\n    const root = nodeOps.createElement('div')\n    render(\n      createVNode(\n        Fragment,\n        null,\n        [\n          createVNode('div', null, 'one', PatchFlags.TEXT),\n          createTextVNode('two'),\n        ],\n        PatchFlags.UNKEYED_FRAGMENT,\n      ),\n      root,\n    )\n    expect(serializeInner(root)).toBe(`<div>one</div>two`)\n\n    render(\n      createVNode(\n        Fragment,\n        null,\n        [\n          createVNode('div', null, 'foo', PatchFlags.TEXT),\n          createTextVNode('bar'),\n          createTextVNode('baz'),\n        ],\n        PatchFlags.UNKEYED_FRAGMENT,\n      ),\n      root,\n    )\n    expect(serializeInner(root)).toBe(`<div>foo</div>barbaz`)\n\n    render(\n      createVNode(\n        Fragment,\n        null,\n        [\n          createTextVNode('baz'),\n          createVNode('div', null, 'foo', PatchFlags.TEXT),\n        ],\n        PatchFlags.UNKEYED_FRAGMENT,\n      ),\n      root,\n    )\n    expect(serializeInner(root)).toBe(`baz<div>foo</div>`)\n  })\n\n  it('patch fragment children (compiler generated, keyed)', () => {\n    const root = nodeOps.createElement('div')\n\n    render(\n      createVNode(\n        Fragment,\n        null,\n        [h('div', { key: 1 }, 'one'), h('div', { key: 2 }, 'two')],\n        PatchFlags.KEYED_FRAGMENT,\n      ),\n      root,\n    )\n    expect(serializeInner(root)).toBe(`<div>one</div><div>two</div>`)\n\n    resetOps()\n    render(\n      createVNode(\n        Fragment,\n        null,\n        [h('div', { key: 2 }, 'two'), h('div', { key: 1 }, 'one')],\n        PatchFlags.KEYED_FRAGMENT,\n      ),\n      root,\n    )\n    expect(serializeInner(root)).toBe(`<div>two</div><div>one</div>`)\n    const ops = dumpOps()\n    // should be moving nodes instead of re-creating or patching them\n    expect(ops).toMatchObject([\n      {\n        type: NodeOpTypes.INSERT,\n      },\n    ])\n  })\n\n  it('move fragment', () => {\n    const root = nodeOps.createElement('div')\n    render(\n      h('div', [\n        h('div', { key: 1 }, 'outer'),\n        h(Fragment, { key: 2 }, [\n          h('div', { key: 1 }, 'one'),\n          h('div', { key: 2 }, 'two'),\n        ]),\n      ]),\n      root,\n    )\n    expect(serializeInner(root)).toBe(\n      `<div><div>outer</div><div>one</div><div>two</div></div>`,\n    )\n\n    resetOps()\n    render(\n      h('div', [\n        h(Fragment, { key: 2 }, [\n          h('div', { key: 2 }, 'two'),\n          h('div', { key: 1 }, 'one'),\n        ]),\n        h('div', { key: 1 }, 'outer'),\n      ]),\n      root,\n    )\n    expect(serializeInner(root)).toBe(\n      `<div><div>two</div><div>one</div><div>outer</div></div>`,\n    )\n    const ops = dumpOps()\n    // should be moving nodes instead of re-creating them\n    expect(ops).toMatchObject([\n      // 1. re-order inside the fragment\n      { type: NodeOpTypes.INSERT, targetNode: { type: 'element' } },\n      // 2. move entire fragment, including anchors\n      // not the most efficient move, but this case is super rare\n      // and optimizing for this special case complicates the algo quite a bit\n      { type: NodeOpTypes.INSERT, targetNode: { type: 'text', text: '' } },\n      { type: NodeOpTypes.INSERT, targetNode: { type: 'element' } },\n      { type: NodeOpTypes.INSERT, targetNode: { type: 'element' } },\n      { type: NodeOpTypes.INSERT, targetNode: { type: 'text', text: '' } },\n    ])\n  })\n\n  it('handle nested fragments', () => {\n    const root = nodeOps.createElement('div')\n\n    render(\n      h(Fragment, [\n        h('div', { key: 1 }, 'outer'),\n        h(Fragment, { key: 2 }, [\n          h('div', { key: 1 }, 'one'),\n          h('div', { key: 2 }, 'two'),\n        ]),\n      ]),\n      root,\n    )\n    expect(serializeInner(root)).toBe(\n      `<div>outer</div><div>one</div><div>two</div>`,\n    )\n\n    resetOps()\n    render(\n      h(Fragment, [\n        h(Fragment, { key: 2 }, [\n          h('div', { key: 2 }, 'two'),\n          h('div', { key: 1 }, 'one'),\n        ]),\n        h('div', { key: 1 }, 'outer'),\n      ]),\n      root,\n    )\n    expect(serializeInner(root)).toBe(\n      `<div>two</div><div>one</div><div>outer</div>`,\n    )\n    const ops = dumpOps()\n    // should be moving nodes instead of re-creating them\n    expect(ops).toMatchObject([\n      { type: NodeOpTypes.INSERT, targetNode: { type: 'element' } },\n      { type: NodeOpTypes.INSERT, targetNode: { type: 'text', text: '' } },\n      { type: NodeOpTypes.INSERT, targetNode: { type: 'element' } },\n      { type: NodeOpTypes.INSERT, targetNode: { type: 'element' } },\n      { type: NodeOpTypes.INSERT, targetNode: { type: 'text', text: '' } },\n    ])\n\n    // should properly remove nested fragments\n    render(null, root)\n    expect(serializeInner(root)).toBe(``)\n  })\n\n  // #2080\n  test('`template` keyed fragment w/ comment + hoisted node', () => {\n    const root = nodeOps.createElement('div')\n    const hoisted = h('span')\n\n    const renderFn = (items: string[]) => {\n      return (\n        openBlock(true),\n        createBlock(\n          Fragment,\n          null,\n          renderList(items, item => {\n            return (\n              openBlock(),\n              createBlock(\n                Fragment,\n                { key: item },\n                [\n                  createCommentVNode('comment'),\n                  hoisted,\n                  createVNode('div', null, item, PatchFlags.TEXT),\n                ],\n                PatchFlags.STABLE_FRAGMENT,\n              )\n            )\n          }),\n          PatchFlags.KEYED_FRAGMENT,\n        )\n      )\n    }\n\n    render(renderFn(['one', 'two']), root)\n    expect(serializeInner(root)).toBe(\n      `<!--comment--><span></span><div>one</div><!--comment--><span></span><div>two</div>`,\n    )\n\n    render(renderFn(['two', 'one']), root)\n    expect(serializeInner(root)).toBe(\n      `<!--comment--><span></span><div>two</div><!--comment--><span></span><div>one</div>`,\n    )\n  })\n\n  // #10547\n  test('`template` fragment w/ render function', () => {\n    const renderFn = (vnode: VNode) => {\n      return (\n        openBlock(),\n        createBlock(\n          Fragment,\n          null,\n          [createTextVNode('text'), (openBlock(), createBlock(vnode))],\n          PatchFlags.STABLE_FRAGMENT,\n        )\n      )\n    }\n\n    const root = nodeOps.createElement('div')\n    const foo = h('div', ['foo'])\n    const bar = h('div', [h('div', 'bar')])\n\n    render(renderFn(foo), root)\n    expect(serializeInner(root)).toBe(`text<div>foo</div>`)\n\n    render(renderFn(bar), root)\n    expect(serializeInner(root)).toBe(`text<div><div>bar</div></div>`)\n\n    render(renderFn(foo), root)\n    expect(serializeInner(root)).toBe(`text<div>foo</div>`)\n  })\n\n  // #10547\n  test('`template` fragment w/ render function + keyed vnode', () => {\n    const renderFn = (vnode: VNode) => {\n      return (\n        openBlock(),\n        createBlock(\n          Fragment,\n          null,\n          [createTextVNode('text'), (openBlock(), createBlock(vnode))],\n          PatchFlags.STABLE_FRAGMENT,\n        )\n      )\n    }\n\n    const root = nodeOps.createElement('div')\n    const foo = h('div', { key: 1 }, [h('div', 'foo')])\n    const bar = h('div', { key: 2 }, [h('div', 'bar'), h('div', 'bar')])\n\n    render(renderFn(foo), root)\n    expect(serializeInner(root)).toBe(`text<div><div>foo</div></div>`)\n\n    render(renderFn(bar), root)\n    expect(serializeInner(root)).toBe(\n      `text<div><div>bar</div><div>bar</div></div>`,\n    )\n\n    render(renderFn(foo), root)\n    expect(serializeInner(root)).toBe(`text<div><div>foo</div></div>`)\n  })\n\n  // #6852\n  test('`template` keyed fragment w/ text', () => {\n    const root = nodeOps.createElement('div')\n\n    const renderFn = (items: string[]) => {\n      return (\n        openBlock(true),\n        createBlock(\n          Fragment,\n          null,\n          renderList(items, item => {\n            return (\n              openBlock(),\n              createBlock(\n                Fragment,\n                { key: item },\n                [\n                  createTextVNode('text'),\n                  createVNode('div', null, item, PatchFlags.TEXT),\n                ],\n                PatchFlags.STABLE_FRAGMENT,\n              )\n            )\n          }),\n          PatchFlags.KEYED_FRAGMENT,\n        )\n      )\n    }\n\n    render(renderFn(['one', 'two']), root)\n    expect(serializeInner(root)).toBe(`text<div>one</div>text<div>two</div>`)\n\n    render(renderFn(['two', 'one']), root)\n    expect(serializeInner(root)).toBe(`text<div>two</div>text<div>one</div>`)\n  })\n\n  // #10007\n  test('empty fragment', () => {\n    const root = nodeOps.createElement('div')\n\n    const renderFn = () => {\n      return (openBlock(true), createBlock(Fragment, null))\n    }\n\n    render(renderFn(), root)\n    expect(serializeInner(root)).toBe('')\n  })\n})\n"
  },
  {
    "path": "packages/runtime-core/__tests__/rendererOptimizedMode.spec.ts",
    "content": "import {\n  Fragment,\n  type FunctionalComponent,\n  type SetupContext,\n  Teleport,\n  type TestElement,\n  type VNode,\n  createApp,\n  createBlock,\n  createCommentVNode,\n  createElementBlock,\n  createElementVNode,\n  createTextVNode,\n  createVNode,\n  defineComponent,\n  h,\n  serializeInner as inner,\n  nextTick,\n  nodeOps,\n  onBeforeMount,\n  onBeforeUnmount,\n  onUnmounted,\n  openBlock,\n  ref,\n  render,\n  renderList,\n  renderSlot,\n  serialize,\n  setBlockTracking,\n  withCtx,\n} from '@vue/runtime-test'\nimport { PatchFlags, SlotFlags, toDisplayString } from '@vue/shared'\nimport { SuspenseImpl } from '../src/components/Suspense'\n\ndescribe('renderer: optimized mode', () => {\n  let root: TestElement\n  let block: VNode | null = null\n\n  beforeEach(() => {\n    root = nodeOps.createElement('div')\n    block = null\n  })\n\n  const renderWithBlock = (renderChildren: () => VNode[]) => {\n    render(\n      (openBlock(), (block = createBlock('div', null, renderChildren()))),\n      root,\n    )\n  }\n\n  test('basic use of block', () => {\n    render((openBlock(), (block = createBlock('p', null, 'foo'))), root)\n\n    expect(block.dynamicChildren!.length).toBe(0)\n    expect(inner(root)).toBe('<p>foo</p>')\n  })\n\n  test('block can appear anywhere in the vdom tree', () => {\n    render(\n      h('div', (openBlock(), (block = createBlock('p', null, 'foo')))),\n      root,\n    )\n\n    expect(block.dynamicChildren!.length).toBe(0)\n    expect(inner(root)).toBe('<div><p>foo</p></div>')\n  })\n\n  test('block should collect dynamic vnodes', () => {\n    renderWithBlock(() => [\n      createVNode('p', null, 'foo', PatchFlags.TEXT),\n      createVNode('i'),\n    ])\n\n    expect(block!.dynamicChildren!.length).toBe(1)\n    expect(serialize(block!.dynamicChildren![0].el as TestElement)).toBe(\n      '<p>foo</p>',\n    )\n  })\n\n  test('block can disable tracking', () => {\n    render(\n      // disable tracking\n      (openBlock(true),\n      (block = createBlock('div', null, [\n        createVNode('p', null, 'foo', PatchFlags.TEXT),\n      ]))),\n      root,\n    )\n\n    expect(block.dynamicChildren!.length).toBe(0)\n  })\n\n  test('block as dynamic children', () => {\n    renderWithBlock(() => [\n      (openBlock(), createBlock('div', { key: 0 }, [h('p')])),\n    ])\n\n    expect(block!.dynamicChildren!.length).toBe(1)\n    expect(block!.dynamicChildren![0].dynamicChildren!.length).toBe(0)\n    expect(serialize(block!.dynamicChildren![0].el as TestElement)).toBe(\n      '<div><p></p></div>',\n    )\n\n    renderWithBlock(() => [\n      (openBlock(), createBlock('div', { key: 1 }, [h('i')])),\n    ])\n\n    expect(block!.dynamicChildren!.length).toBe(1)\n    expect(block!.dynamicChildren![0].dynamicChildren!.length).toBe(0)\n    expect(serialize(block!.dynamicChildren![0].el as TestElement)).toBe(\n      '<div><i></i></div>',\n    )\n  })\n\n  test('PatchFlags: PatchFlags.TEXT', async () => {\n    renderWithBlock(() => [createVNode('p', null, 'foo', PatchFlags.TEXT)])\n\n    expect(inner(root)).toBe('<div><p>foo</p></div>')\n    expect(block!.dynamicChildren!.length).toBe(1)\n    expect(serialize(block!.dynamicChildren![0].el as TestElement)).toBe(\n      '<p>foo</p>',\n    )\n\n    renderWithBlock(() => [createVNode('p', null, 'bar', PatchFlags.TEXT)])\n\n    expect(inner(root)).toBe('<div><p>bar</p></div>')\n    expect(block!.dynamicChildren!.length).toBe(1)\n    expect(serialize(block!.dynamicChildren![0].el as TestElement)).toBe(\n      '<p>bar</p>',\n    )\n  })\n\n  test('PatchFlags: PatchFlags.CLASS', async () => {\n    renderWithBlock(() => [\n      createVNode('p', { class: 'foo' }, '', PatchFlags.CLASS),\n    ])\n\n    expect(inner(root)).toBe('<div><p class=\"foo\"></p></div>')\n    expect(block!.dynamicChildren!.length).toBe(1)\n    expect(serialize(block!.dynamicChildren![0].el as TestElement)).toBe(\n      '<p class=\"foo\"></p>',\n    )\n\n    renderWithBlock(() => [\n      createVNode('p', { class: 'bar' }, '', PatchFlags.CLASS),\n    ])\n\n    expect(inner(root)).toBe('<div><p class=\"bar\"></p></div>')\n    expect(block!.dynamicChildren!.length).toBe(1)\n    expect(serialize(block!.dynamicChildren![0].el as TestElement)).toBe(\n      '<p class=\"bar\"></p>',\n    )\n  })\n\n  test('PatchFlags: PatchFlags.STYLE', async () => {\n    renderWithBlock(() => [\n      createVNode('p', { style: 'color: red' }, '', PatchFlags.STYLE),\n    ])\n\n    expect(inner(root)).toBe('<div><p style=\"color: red\"></p></div>')\n    expect(block!.dynamicChildren!.length).toBe(1)\n    expect(serialize(block!.dynamicChildren![0].el as TestElement)).toBe(\n      '<p style=\"color: red\"></p>',\n    )\n\n    renderWithBlock(() => [\n      createVNode('p', { style: 'color: green' }, '', PatchFlags.STYLE),\n    ])\n\n    expect(inner(root)).toBe('<div><p style=\"color: green\"></p></div>')\n    expect(block!.dynamicChildren!.length).toBe(1)\n    expect(serialize(block!.dynamicChildren![0].el as TestElement)).toBe(\n      '<p style=\"color: green\"></p>',\n    )\n  })\n\n  test('PatchFlags: PatchFlags.PROPS', async () => {\n    renderWithBlock(() => [\n      createVNode('p', { id: 'foo' }, '', PatchFlags.PROPS, ['id']),\n    ])\n\n    expect(inner(root)).toBe('<div><p id=\"foo\"></p></div>')\n    expect(block!.dynamicChildren!.length).toBe(1)\n    expect(serialize(block!.dynamicChildren![0].el as TestElement)).toBe(\n      '<p id=\"foo\"></p>',\n    )\n\n    renderWithBlock(() => [\n      createVNode('p', { id: 'bar' }, '', PatchFlags.PROPS, ['id']),\n    ])\n\n    expect(inner(root)).toBe('<div><p id=\"bar\"></p></div>')\n    expect(block!.dynamicChildren!.length).toBe(1)\n    expect(serialize(block!.dynamicChildren![0].el as TestElement)).toBe(\n      '<p id=\"bar\"></p>',\n    )\n  })\n\n  test('PatchFlags: PatchFlags.FULL_PROPS', async () => {\n    let propName = 'foo'\n\n    renderWithBlock(() => [\n      createVNode('p', { [propName]: 'dynamic' }, '', PatchFlags.FULL_PROPS),\n    ])\n\n    expect(inner(root)).toBe('<div><p foo=\"dynamic\"></p></div>')\n    expect(block!.dynamicChildren!.length).toBe(1)\n    expect(serialize(block!.dynamicChildren![0].el as TestElement)).toBe(\n      '<p foo=\"dynamic\"></p>',\n    )\n\n    propName = 'bar'\n    renderWithBlock(() => [\n      createVNode('p', { [propName]: 'dynamic' }, '', PatchFlags.FULL_PROPS),\n    ])\n\n    expect(inner(root)).toBe('<div><p bar=\"dynamic\"></p></div>')\n    expect(block!.dynamicChildren!.length).toBe(1)\n    expect(serialize(block!.dynamicChildren![0].el as TestElement)).toBe(\n      '<p bar=\"dynamic\"></p>',\n    )\n  })\n\n  // the order and length of the list will not change\n  test('PatchFlags: PatchFlags.STABLE_FRAGMENT', async () => {\n    let list = ['foo', 'bar']\n    render(\n      (openBlock(),\n      (block = createBlock(\n        Fragment,\n        null,\n        list.map(item => {\n          return createVNode('p', null, item, PatchFlags.TEXT)\n        }),\n        PatchFlags.STABLE_FRAGMENT,\n      ))),\n      root,\n    )\n\n    expect(inner(root)).toBe('<p>foo</p><p>bar</p>')\n    expect(block.dynamicChildren!.length).toBe(2)\n    expect(serialize(block.dynamicChildren![0].el as TestElement)).toBe(\n      '<p>foo</p>',\n    )\n    expect(serialize(block.dynamicChildren![1].el as TestElement)).toBe(\n      '<p>bar</p>',\n    )\n\n    list = list.map(item => item.repeat(2))\n    render(\n      (openBlock(),\n      createBlock(\n        Fragment,\n        null,\n        list.map(item => {\n          return createVNode('p', null, item, PatchFlags.TEXT)\n        }),\n        PatchFlags.STABLE_FRAGMENT,\n      )),\n      root,\n    )\n\n    expect(inner(root)).toBe('<p>foofoo</p><p>barbar</p>')\n    expect(block.dynamicChildren!.length).toBe(2)\n    expect(serialize(block.dynamicChildren![0].el as TestElement)).toBe(\n      '<p>foofoo</p>',\n    )\n    expect(serialize(block.dynamicChildren![1].el as TestElement)).toBe(\n      '<p>barbar</p>',\n    )\n  })\n\n  // A Fragment with `UNKEYED_FRAGMENT` flag will always patch its children,\n  // so there's no need for tracking dynamicChildren.\n  test('PatchFlags: PatchFlags.UNKEYED_FRAGMENT', async () => {\n    const list = [{ tag: 'p', text: 'foo' }]\n    render(\n      (openBlock(true),\n      (block = createBlock(\n        Fragment,\n        null,\n        list.map(item => {\n          return createVNode(item.tag, null, item.text)\n        }),\n        PatchFlags.UNKEYED_FRAGMENT,\n      ))),\n      root,\n    )\n\n    expect(inner(root)).toBe('<p>foo</p>')\n    expect(block.dynamicChildren!.length).toBe(0)\n\n    list.unshift({ tag: 'i', text: 'bar' })\n    render(\n      (openBlock(true),\n      createBlock(\n        Fragment,\n        null,\n        list.map(item => {\n          return createVNode(item.tag, null, item.text)\n        }),\n        PatchFlags.UNKEYED_FRAGMENT,\n      )),\n      root,\n    )\n\n    expect(inner(root)).toBe('<i>bar</i><p>foo</p>')\n    expect(block.dynamicChildren!.length).toBe(0)\n  })\n\n  // A Fragment with `KEYED_FRAGMENT` will always patch its children,\n  // so there's no need for tracking dynamicChildren.\n  test('PatchFlags: PatchFlags.KEYED_FRAGMENT', async () => {\n    const list = [{ tag: 'p', text: 'foo' }]\n    render(\n      (openBlock(true),\n      (block = createBlock(\n        Fragment,\n        null,\n        list.map(item => {\n          return createVNode(item.tag, { key: item.tag }, item.text)\n        }),\n        PatchFlags.KEYED_FRAGMENT,\n      ))),\n      root,\n    )\n\n    expect(inner(root)).toBe('<p>foo</p>')\n    expect(block.dynamicChildren!.length).toBe(0)\n\n    list.unshift({ tag: 'i', text: 'bar' })\n    render(\n      (openBlock(true),\n      createBlock(\n        Fragment,\n        null,\n        list.map(item => {\n          return createVNode(item.tag, { key: item.tag }, item.text)\n        }),\n        PatchFlags.KEYED_FRAGMENT,\n      )),\n      root,\n    )\n\n    expect(inner(root)).toBe('<i>bar</i><p>foo</p>')\n    expect(block.dynamicChildren!.length).toBe(0)\n  })\n\n  test('PatchFlags: PatchFlags.NEED_PATCH', async () => {\n    const spyMounted = vi.fn()\n    const spyUpdated = vi.fn()\n    const count = ref(0)\n    const Comp = {\n      setup() {\n        return () => {\n          count.value\n          return (\n            openBlock(),\n            (block = createBlock('div', null, [\n              createVNode(\n                'p',\n                { onVnodeMounted: spyMounted, onVnodeBeforeUpdate: spyUpdated },\n                '',\n                PatchFlags.NEED_PATCH,\n              ),\n            ]))\n          )\n        }\n      },\n    }\n\n    render(h(Comp), root)\n\n    expect(inner(root)).toBe('<div><p></p></div>')\n    expect(block!.dynamicChildren!.length).toBe(1)\n    expect(serialize(block!.dynamicChildren![0].el as TestElement)).toBe(\n      '<p></p>',\n    )\n    expect(spyMounted).toHaveBeenCalledTimes(1)\n    expect(spyUpdated).toHaveBeenCalledTimes(0)\n\n    count.value++\n    await nextTick()\n\n    expect(inner(root)).toBe('<div><p></p></div>')\n    expect(block!.dynamicChildren!.length).toBe(1)\n    expect(serialize(block!.dynamicChildren![0].el as TestElement)).toBe(\n      '<p></p>',\n    )\n    expect(spyMounted).toHaveBeenCalledTimes(1)\n    expect(spyUpdated).toHaveBeenCalledTimes(1)\n  })\n\n  test('PatchFlags: PatchFlags.BAIL', async () => {\n    render(\n      (openBlock(),\n      (block = createBlock('div', null, [createVNode('p', null, 'foo')]))),\n      root,\n    )\n\n    expect(inner(root)).toBe('<div><p>foo</p></div>')\n    expect(block!.dynamicChildren!.length).toBe(0)\n\n    render(\n      (openBlock(),\n      (block = createBlock(\n        'div',\n        null,\n        [createVNode('i', null, 'bar')],\n        PatchFlags.BAIL,\n      ))),\n      root,\n    )\n\n    expect(inner(root)).toBe('<div><i>bar</i></div>')\n    expect(block!.dynamicChildren).toBe(null)\n  })\n\n  // #1980\n  test('dynamicChildren should be tracked correctly when normalizing slots to plain children', async () => {\n    let block: VNode\n    const Comp = defineComponent({\n      setup(_props, { slots }) {\n        return () => {\n          const vnode =\n            (openBlock(),\n            (block = createBlock('div', null, {\n              default: withCtx(() => [renderSlot(slots, 'default')]),\n              _: SlotFlags.FORWARDED,\n            })))\n\n          return vnode\n        }\n      },\n    })\n\n    const foo = ref(0)\n    const App = {\n      setup() {\n        return () => {\n          return createBlock(Comp, null, {\n            default: withCtx(() => [\n              createVNode('p', null, foo.value, PatchFlags.TEXT),\n            ]),\n            // Indicates that this is a stable slot to avoid bail out\n            _: SlotFlags.STABLE,\n          })\n        }\n      },\n    }\n\n    render(h(App), root)\n    expect(inner(root)).toBe('<div><p>0</p></div>')\n    expect(block!.dynamicChildren!.length).toBe(1)\n    expect(block!.dynamicChildren![0].type).toBe(Fragment)\n    expect(block!.dynamicChildren![0].dynamicChildren!.length).toBe(1)\n    expect(\n      serialize(\n        block!.dynamicChildren![0].dynamicChildren![0].el as TestElement,\n      ),\n    ).toBe('<p>0</p>')\n\n    foo.value++\n    await nextTick()\n\n    expect(inner(root)).toBe('<div><p>1</p></div>')\n  })\n\n  // #2169\n  // block\n  // - dynamic child (1)\n  //   - component (2)\n  // When unmounting (1), we know we are in optimized mode so no need to further\n  // traverse unmount its children\n  test('should not perform unnecessary unmount traversals', () => {\n    const spy = vi.fn()\n    const Child = {\n      setup() {\n        onBeforeUnmount(spy)\n        return () => 'child'\n      },\n    }\n    const Parent = () => (\n      openBlock(),\n      createBlock('div', null, [\n        createVNode('div', { style: {} }, [createVNode(Child)], 4 /* STYLE */),\n      ])\n    )\n    render(h(Parent), root)\n    render(null, root)\n    expect(spy).toHaveBeenCalledTimes(1)\n  })\n\n  test('should call onUnmounted hook for dynamic components receiving an existing vnode w/ component children', async () => {\n    const spy = vi.fn()\n    const show = ref(1)\n    const Child = {\n      setup() {\n        onUnmounted(spy)\n        return () => 'child'\n      },\n    }\n    const foo = h('div', null, h(Child))\n    const app = createApp({\n      render() {\n        return show.value\n          ? (openBlock(),\n            createBlock('div', null, [(openBlock(), createBlock(foo))]))\n          : createCommentVNode('v-if', true)\n      },\n    })\n\n    app.mount(root)\n    show.value = 0\n    await nextTick()\n\n    expect(spy).toHaveBeenCalledTimes(1)\n  })\n\n  // #2444\n  // `KEYED_FRAGMENT` and `UNKEYED_FRAGMENT` always need to diff its children\n  test('non-stable Fragment always need to diff its children', () => {\n    const spyA = vi.fn()\n    const spyB = vi.fn()\n    const ChildA = {\n      setup() {\n        onBeforeUnmount(spyA)\n        return () => 'child'\n      },\n    }\n    const ChildB = {\n      setup() {\n        onBeforeUnmount(spyB)\n        return () => 'child'\n      },\n    }\n    const Parent = () => (\n      openBlock(),\n      createBlock('div', null, [\n        (openBlock(true),\n        createBlock(\n          Fragment,\n          null,\n          [createVNode(ChildA, { key: 0 })],\n          128 /* KEYED_FRAGMENT */,\n        )),\n        (openBlock(true),\n        createBlock(\n          Fragment,\n          null,\n          [createVNode(ChildB)],\n          256 /* UNKEYED_FRAGMENT */,\n        )),\n      ])\n    )\n    render(h(Parent), root)\n    render(null, root)\n    expect(spyA).toHaveBeenCalledTimes(1)\n    expect(spyB).toHaveBeenCalledTimes(1)\n  })\n\n  // #2893\n  test('manually rendering the optimized slots should allow subsequent updates to exit the optimized mode correctly', async () => {\n    const state = ref(0)\n\n    const CompA = {\n      name: 'A',\n      setup(props: any, { slots }: SetupContext) {\n        return () => {\n          return (\n            openBlock(),\n            createBlock('div', null, [renderSlot(slots, 'default')])\n          )\n        }\n      },\n    }\n\n    const Wrapper = {\n      name: 'Wrapper',\n      setup(props: any, { slots }: SetupContext) {\n        // use the manually written render function to rendering the optimized slots,\n        // which should make subsequent updates exit the optimized mode correctly\n        return () => {\n          return slots.default!()[state.value]\n        }\n      },\n    }\n\n    const app = createApp({\n      name: 'App',\n      setup() {\n        return () => {\n          return (\n            openBlock(),\n            createBlock(Wrapper, null, {\n              default: withCtx(() => [\n                createVNode(CompA, null, {\n                  default: withCtx(() => [createTextVNode('Hello')]),\n                  _: 1 /* STABLE */,\n                }),\n                createVNode(CompA, null, {\n                  default: withCtx(() => [createTextVNode('World')]),\n                  _: 1 /* STABLE */,\n                }),\n              ]),\n              _: 1 /* STABLE */,\n            })\n          )\n        }\n      },\n    })\n\n    app.mount(root)\n    expect(inner(root)).toBe('<div>Hello</div>')\n\n    state.value = 1\n    await nextTick()\n    expect(inner(root)).toBe('<div>World</div>')\n  })\n\n  //#3623\n  test('nested teleport unmount need exit the optimization mode', async () => {\n    const target = nodeOps.createElement('div')\n    const root = nodeOps.createElement('div')\n\n    render(\n      (openBlock(),\n      createBlock('div', null, [\n        (openBlock(),\n        createBlock(\n          Teleport as any,\n          {\n            to: target,\n          },\n          [\n            createVNode('div', null, [\n              (openBlock(),\n              createBlock(\n                Teleport as any,\n                {\n                  to: target,\n                },\n                [createVNode('div', null, 'foo')],\n              )),\n            ]),\n          ],\n        )),\n      ])),\n      root,\n    )\n    await nextTick()\n    expect(inner(target)).toMatchInlineSnapshot(\n      `\"<div><!--teleport start--><!--teleport end--></div><div>foo</div>\"`,\n    )\n    expect(inner(root)).toMatchInlineSnapshot(\n      `\"<div><!--teleport start--><!--teleport end--></div>\"`,\n    )\n\n    render(null, root)\n    expect(inner(target)).toBe('')\n  })\n\n  // #3548\n  test('should not track dynamic children when the user calls a compiled slot inside template expression', () => {\n    const Comp = {\n      setup(props: any, { slots }: SetupContext) {\n        return () => {\n          return (\n            openBlock(),\n            (block = createBlock('section', null, [\n              renderSlot(slots, 'default'),\n            ]))\n          )\n        }\n      },\n    }\n\n    let dynamicVNode: VNode\n    const Wrapper = {\n      setup(props: any, { slots }: SetupContext) {\n        return () => {\n          return (\n            openBlock(),\n            createBlock(Comp, null, {\n              default: withCtx(() => {\n                return [\n                  (dynamicVNode = createVNode(\n                    'div',\n                    {\n                      class: {\n                        foo: !!slots.default!(),\n                      },\n                    },\n                    null,\n                    PatchFlags.CLASS,\n                  )),\n                ]\n              }),\n              _: 1,\n            })\n          )\n        }\n      },\n    }\n    const app = createApp({\n      render() {\n        return (\n          openBlock(),\n          createBlock(Wrapper, null, {\n            default: withCtx(() => {\n              return [createVNode({}) /* component */]\n            }),\n            _: 1,\n          })\n        )\n      },\n    })\n\n    app.mount(root)\n    expect(inner(root)).toBe('<section><div class=\"foo\"></div></section>')\n    /**\n     * Block Tree:\n     *  - block(div)\n     *   - block(Fragment): renderSlots()\n     *    - dynamicVNode\n     */\n    expect(block!.dynamicChildren!.length).toBe(1)\n    expect(block!.dynamicChildren![0].dynamicChildren!.length).toBe(1)\n    expect(block!.dynamicChildren![0].dynamicChildren![0]).toEqual(\n      dynamicVNode!,\n    )\n  })\n\n  // 3569\n  test('should force bailout when the user manually calls the slot function', async () => {\n    const index = ref(0)\n    const Foo = {\n      setup(props: any, { slots }: SetupContext) {\n        return () => {\n          return slots.default!()[index.value]\n        }\n      },\n    }\n\n    const app = createApp({\n      setup() {\n        return () => {\n          return (\n            openBlock(),\n            createBlock(Foo, null, {\n              default: withCtx(() => [\n                true\n                  ? (openBlock(), createBlock('p', { key: 0 }, '1'))\n                  : createCommentVNode('v-if', true),\n                true\n                  ? (openBlock(), createBlock('p', { key: 0 }, '2'))\n                  : createCommentVNode('v-if', true),\n              ]),\n              _: 1 /* STABLE */,\n            })\n          )\n        }\n      },\n    })\n\n    app.mount(root)\n    expect(inner(root)).toBe('<p>1</p>')\n\n    index.value = 1\n    await nextTick()\n    expect(inner(root)).toBe('<p>2</p>')\n\n    index.value = 0\n    await nextTick()\n    expect(inner(root)).toBe('<p>1</p>')\n  })\n\n  // #3779\n  test('treat slots manually written by the user as dynamic', async () => {\n    const Middle = {\n      setup(props: any, { slots }: any) {\n        return slots.default!\n      },\n    }\n\n    const Comp = {\n      setup(props: any, { slots }: any) {\n        return () => {\n          return (\n            openBlock(),\n            createBlock('div', null, [\n              createVNode(Middle, null, {\n                default: withCtx(\n                  () => [\n                    createVNode('div', null, [renderSlot(slots, 'default')]),\n                  ],\n                  undefined,\n                ),\n                _: 3 /* FORWARDED */,\n              }),\n            ])\n          )\n        }\n      },\n    }\n\n    const loading = ref(false)\n    const app = createApp({\n      setup() {\n        return () => {\n          // important: write the slot content here\n          const content = h('span', loading.value ? 'loading' : 'loaded')\n          return h(Comp, null, {\n            default: () => content,\n          })\n        }\n      },\n    })\n\n    app.mount(root)\n    expect(inner(root)).toBe('<div><div><span>loaded</span></div></div>')\n\n    loading.value = true\n    await nextTick()\n    expect(inner(root)).toBe('<div><div><span>loading</span></div></div>')\n  })\n\n  // #3828\n  test('patch Suspense in optimized mode w/ nested dynamic nodes', async () => {\n    const show = ref(false)\n\n    const app = createApp({\n      render() {\n        return (\n          openBlock(),\n          createBlock(\n            Fragment,\n            null,\n            [\n              (openBlock(),\n              createBlock(SuspenseImpl, null, {\n                default: withCtx(() => [\n                  createVNode('div', null, [\n                    createVNode('div', null, show.value, PatchFlags.TEXT),\n                  ]),\n                ]),\n                _: SlotFlags.STABLE,\n              })),\n            ],\n            PatchFlags.STABLE_FRAGMENT,\n          )\n        )\n      },\n    })\n\n    app.mount(root)\n    expect(inner(root)).toBe('<div><div>false</div></div>')\n\n    show.value = true\n    await nextTick()\n    expect(inner(root)).toBe('<div><div>true</div></div>')\n  })\n\n  // #13305\n  test('patch Suspense nested in list nodes in optimized mode', async () => {\n    const deps: Promise<any>[] = []\n\n    const Item = {\n      props: {\n        someId: { type: Number, required: true },\n      },\n      async setup(props: any) {\n        const p = new Promise(resolve => setTimeout(resolve, 1))\n        deps.push(p)\n\n        await p\n        return () => (\n          openBlock(),\n          createElementBlock('li', null, [\n            createElementVNode(\n              'p',\n              null,\n              String(props.someId),\n              PatchFlags.TEXT,\n            ),\n          ])\n        )\n      },\n    }\n\n    const list = ref([1, 2, 3])\n    const App = {\n      setup() {\n        return () => (\n          openBlock(),\n          createElementBlock(\n            Fragment,\n            null,\n            [\n              createElementVNode(\n                'p',\n                null,\n                JSON.stringify(list.value),\n                PatchFlags.TEXT,\n              ),\n              createElementVNode('ol', null, [\n                (openBlock(),\n                createBlock(SuspenseImpl, null, {\n                  fallback: withCtx(() => [\n                    createElementVNode('li', null, 'Loading…'),\n                  ]),\n                  default: withCtx(() => [\n                    (openBlock(true),\n                    createElementBlock(\n                      Fragment,\n                      null,\n                      renderList(list.value, id => {\n                        return (\n                          openBlock(),\n                          createBlock(\n                            Item,\n                            {\n                              key: id,\n                              'some-id': id,\n                            },\n                            null,\n                            PatchFlags.PROPS,\n                            ['some-id'],\n                          )\n                        )\n                      }),\n                      PatchFlags.KEYED_FRAGMENT,\n                    )),\n                  ]),\n                  _: 1 /* STABLE */,\n                })),\n              ]),\n            ],\n            PatchFlags.STABLE_FRAGMENT,\n          )\n        )\n      },\n    }\n\n    const app = createApp(App)\n    app.mount(root)\n    expect(inner(root)).toBe(`<p>[1,2,3]</p>` + `<ol><li>Loading…</li></ol>`)\n\n    await Promise.all(deps)\n    await nextTick()\n    expect(inner(root)).toBe(\n      `<p>[1,2,3]</p>` +\n        `<ol>` +\n        `<li><p>1</p></li>` +\n        `<li><p>2</p></li>` +\n        `<li><p>3</p></li>` +\n        `</ol>`,\n    )\n\n    list.value = [3, 1, 2]\n    await nextTick()\n    expect(inner(root)).toBe(\n      `<p>[3,1,2]</p>` +\n        `<ol>` +\n        `<li><p>3</p></li>` +\n        `<li><p>1</p></li>` +\n        `<li><p>2</p></li>` +\n        `</ol>`,\n    )\n  })\n\n  // #4183\n  test('should not take unmount children fast path /w Suspense', async () => {\n    const show = ref(true)\n    const spyUnmounted = vi.fn()\n\n    const Parent = {\n      setup(props: any, { slots }: SetupContext) {\n        return () => (\n          openBlock(),\n          createBlock(SuspenseImpl, null, {\n            default: withCtx(() => [renderSlot(slots, 'default')]),\n            _: SlotFlags.FORWARDED,\n          })\n        )\n      },\n    }\n\n    const Child = {\n      setup() {\n        onUnmounted(spyUnmounted)\n        return () => createVNode('div', null, show.value, PatchFlags.TEXT)\n      },\n    }\n\n    const app = createApp({\n      render() {\n        return show.value\n          ? (openBlock(),\n            createBlock(\n              Parent,\n              { key: 0 },\n              {\n                default: withCtx(() => [createVNode(Child)]),\n                _: SlotFlags.STABLE,\n              },\n            ))\n          : createCommentVNode('v-if', true)\n      },\n    })\n\n    app.mount(root)\n    expect(inner(root)).toBe('<div>true</div>')\n\n    show.value = false\n    await nextTick()\n    expect(inner(root)).toBe('<!--v-if-->')\n    expect(spyUnmounted).toHaveBeenCalledTimes(1)\n  })\n\n  // #3881\n  // root cause: fragment inside a compiled slot passed to component which\n  // programmatically invokes the slot. The entire slot should de-opt but\n  // the fragment was incorrectly put in optimized mode which causes it to skip\n  // updates for its inner components.\n  test('fragments inside programmatically invoked compiled slot should de-opt properly', async () => {\n    const Parent: FunctionalComponent = (_, { slots }) => slots.default!()\n    const Dummy = () => 'dummy'\n\n    const toggle = ref(true)\n    const force = ref(0)\n\n    const app = createApp({\n      render() {\n        if (!toggle.value) {\n          return null\n        }\n        return h(\n          Parent,\n          { n: force.value },\n          {\n            default: withCtx(\n              () => [\n                createVNode('ul', null, [\n                  (openBlock(),\n                  createBlock(\n                    Fragment,\n                    null,\n                    renderList(1, item => {\n                      return createVNode('li', null, [createVNode(Dummy)])\n                    }),\n                    64 /* STABLE_FRAGMENT */,\n                  )),\n                ]),\n              ],\n              undefined,\n              true,\n            ),\n            _: 1 /* STABLE */,\n          },\n        )\n      },\n    })\n\n    app.mount(root)\n\n    // force a patch\n    force.value++\n    await nextTick()\n    expect(inner(root)).toBe(`<ul><li>dummy</li></ul>`)\n\n    // unmount\n    toggle.value = false\n    await nextTick()\n    // should successfully unmount without error\n    expect(inner(root)).toBe(`<!---->`)\n  })\n\n  // #10870\n  test('should bail manually rendered compiler slots for both mount and update', async () => {\n    // only reproducible in prod\n    __DEV__ = false\n    function Outer(_: any, { slots }: any) {\n      return slots.default()\n    }\n    const Mid = {\n      render(ctx: any) {\n        return (\n          openBlock(),\n          createElementBlock('div', null, [renderSlot(ctx.$slots, 'default')])\n        )\n      },\n    }\n    const state1 = ref(true)\n    const state2 = ref(true)\n    const App = {\n      render() {\n        return (\n          openBlock(),\n          createBlock(Outer, null, {\n            default: withCtx(() => [\n              createVNode(\n                Mid,\n                { foo: state2.value },\n                {\n                  default: withCtx(() => [\n                    createElementVNode('div', null, [\n                      createElementVNode('div', null, [\n                        state2.value\n                          ? (openBlock(),\n                            createElementBlock(\n                              'div',\n                              {\n                                key: 0,\n                                id: 'if',\n                                foo: state1.value,\n                              },\n                              null,\n                              8 /* PROPS */,\n                              ['foo'],\n                            ))\n                          : createCommentVNode('v-if', true),\n                      ]),\n                    ]),\n                  ]),\n                  _: 1 /* STABLE */,\n                },\n                8 /* PROPS */,\n                ['foo'],\n              ),\n            ]),\n            _: 1 /* STABLE */,\n          })\n        )\n      },\n    }\n\n    const app = createApp(App)\n    app.config.errorHandler = vi.fn()\n\n    try {\n      app.mount(root)\n\n      state1.value = false\n      await nextTick()\n\n      state2.value = false\n      await nextTick()\n    } finally {\n      __DEV__ = true\n      expect(app.config.errorHandler).not.toHaveBeenCalled()\n    }\n  })\n\n  // #11336\n  test('should bail manually rendered compiler slots for both mount and update (2)', async () => {\n    // only reproducible in prod\n    __DEV__ = false\n    const n = ref(0)\n    function Outer(_: any, { slots }: any) {\n      n.value // track\n      return slots.default()\n    }\n    const Mid = {\n      render(ctx: any) {\n        return (\n          openBlock(),\n          createElementBlock('div', null, [renderSlot(ctx.$slots, 'default')])\n        )\n      },\n    }\n    const show = ref(false)\n    const App = {\n      render() {\n        return (\n          openBlock(),\n          createBlock(Outer, null, {\n            default: withCtx(() => [\n              createVNode(Mid, null, {\n                default: withCtx(() => [\n                  createElementVNode('div', null, [\n                    show.value\n                      ? (openBlock(),\n                        createElementBlock('div', { key: 0 }, '1'))\n                      : createCommentVNode('v-if', true),\n                    createElementVNode('div', null, '2'),\n                    createElementVNode('div', null, '3'),\n                  ]),\n                  createElementVNode('div', null, '4'),\n                ]),\n                _: 1 /* STABLE */,\n              }),\n            ]),\n            _: 1 /* STABLE */,\n          })\n        )\n      },\n    }\n\n    const app = createApp(App)\n    app.config.errorHandler = vi.fn()\n\n    try {\n      app.mount(root)\n\n      // force Outer update, which will assign new slots to Mid\n      // we want to make sure the compiled slot flag doesn't accidentally\n      // get assigned again\n      n.value++\n      await nextTick()\n\n      show.value = true\n      await nextTick()\n    } finally {\n      __DEV__ = true\n      expect(app.config.errorHandler).not.toHaveBeenCalled()\n    }\n  })\n\n  test('diff slot and slot fallback node', async () => {\n    const Comp = {\n      props: ['show'],\n      setup(props: any, { slots }: SetupContext) {\n        return () => {\n          return (\n            openBlock(),\n            createElementBlock('div', null, [\n              renderSlot(slots, 'default', { hide: !props.show }, () => [\n                (openBlock(),\n                (block = createElementBlock(\n                  Fragment,\n                  { key: 0 },\n                  [createTextVNode('foo')],\n                  PatchFlags.STABLE_FRAGMENT,\n                ))),\n              ]),\n            ])\n          )\n        }\n      },\n    }\n\n    const show = ref(true)\n    const app = createApp({\n      render() {\n        return (\n          openBlock(),\n          createBlock(\n            Comp,\n            { show: show.value },\n            {\n              default: withCtx(({ hide }: { hide: boolean }) => [\n                !hide\n                  ? (openBlock(),\n                    createElementBlock(\n                      Fragment,\n                      { key: 0 },\n                      [\n                        createCommentVNode('comment'),\n                        createElementVNode(\n                          'div',\n                          null,\n                          'bar',\n                          PatchFlags.CACHED,\n                        ),\n                      ],\n                      PatchFlags.STABLE_FRAGMENT,\n                    ))\n                  : createCommentVNode('v-if', true),\n              ]),\n              _: SlotFlags.STABLE,\n            },\n            PatchFlags.PROPS,\n            ['show'],\n          )\n        )\n      },\n    })\n\n    app.mount(root)\n    expect(inner(root)).toBe('<div><!--comment--><div>bar</div></div>')\n    expect(block).toBe(null)\n\n    show.value = false\n    await nextTick()\n    expect(inner(root)).toBe('<div>foo</div>')\n\n    show.value = true\n    await nextTick()\n    expect(inner(root)).toBe('<div><!--comment--><div>bar</div></div>')\n  })\n\n  test('should not take unmount children fast path if children contain cached nodes', async () => {\n    const show = ref(true)\n    const spyUnmounted = vi.fn()\n\n    const Child = {\n      setup() {\n        onUnmounted(spyUnmounted)\n        return () => createVNode('div', null, 'Child')\n      },\n    }\n\n    const app = createApp({\n      render(_: any, cache: any) {\n        return show.value\n          ? (openBlock(),\n            createBlock('div', null, [\n              createVNode('div', null, [\n                cache[0] ||\n                  (setBlockTracking(-1, true),\n                  ((cache[0] = createVNode('div', null, [\n                    createVNode(Child),\n                  ])).cacheIndex = 0),\n                  setBlockTracking(1),\n                  cache[0]),\n              ]),\n            ]))\n          : createCommentVNode('v-if', true)\n      },\n    })\n\n    app.mount(root)\n    expect(inner(root)).toBe(\n      '<div><div><div><div>Child</div></div></div></div>',\n    )\n\n    show.value = false\n    await nextTick()\n    expect(inner(root)).toBe('<!--v-if-->')\n    expect(spyUnmounted).toHaveBeenCalledTimes(1)\n\n    show.value = true\n    await nextTick()\n    expect(inner(root)).toBe(\n      '<div><div><div><div>Child</div></div></div></div>',\n    )\n\n    // should unmount again, this verifies previous cache was properly cleared\n    show.value = false\n    await nextTick()\n    expect(inner(root)).toBe('<!--v-if-->')\n    expect(spyUnmounted).toHaveBeenCalledTimes(2)\n  })\n\n  // #12371\n  test('unmount children when the user calls a compiled slot', async () => {\n    const beforeMountSpy = vi.fn()\n    const beforeUnmountSpy = vi.fn()\n\n    const Child = {\n      setup() {\n        onBeforeMount(beforeMountSpy)\n        onBeforeUnmount(beforeUnmountSpy)\n        return () => 'child'\n      },\n    }\n\n    const Wrapper = {\n      setup(_: any, { slots }: SetupContext) {\n        return () => (\n          openBlock(),\n          createElementBlock('section', null, [\n            (openBlock(),\n            createElementBlock('div', { key: 1 }, [\n              createTextVNode(slots.header!() ? 'foo' : 'bar', 1 /* TEXT */),\n              renderSlot(slots, 'content'),\n            ])),\n          ])\n        )\n      },\n    }\n\n    const show = ref(false)\n    const app = createApp({\n      render() {\n        return show.value\n          ? (openBlock(),\n            createBlock(Wrapper, null, {\n              header: withCtx(() => [createVNode({})]),\n              content: withCtx(() => [createVNode(Child)]),\n              _: 1,\n            }))\n          : createCommentVNode('v-if', true)\n      },\n    })\n\n    app.mount(root)\n    expect(inner(root)).toMatchInlineSnapshot(`\"<!--v-if-->\"`)\n    expect(beforeMountSpy).toHaveBeenCalledTimes(0)\n    expect(beforeUnmountSpy).toHaveBeenCalledTimes(0)\n\n    show.value = true\n    await nextTick()\n    expect(inner(root)).toMatchInlineSnapshot(\n      `\"<section><div>foochild</div></section>\"`,\n    )\n    expect(beforeMountSpy).toHaveBeenCalledTimes(1)\n\n    show.value = false\n    await nextTick()\n    expect(inner(root)).toBe('<!--v-if-->')\n    expect(beforeUnmountSpy).toHaveBeenCalledTimes(1)\n  })\n\n  // #12411\n  test('handle patch stable fragment with non-reactive v-for source', async () => {\n    const count = ref(0)\n    const foo: any = []\n    function updateFoo() {\n      for (let n = 0; n < 3; n++) {\n        foo[n] = n + 1 + '_foo'\n      }\n    }\n    const Comp = {\n      setup() {\n        return () => {\n          // <div>{{ count }}</div>\n          // <div v-for='item in foo'>{{ item }}</div>\n          return (\n            openBlock(),\n            createElementBlock(\n              Fragment,\n              null,\n              [\n                createElementVNode(\n                  'div',\n                  null,\n                  toDisplayString(count.value),\n                  PatchFlags.TEXT,\n                ),\n                (openBlock(),\n                createElementBlock(\n                  Fragment,\n                  null,\n                  renderList(foo, item => {\n                    return createElementVNode(\n                      'div',\n                      null,\n                      toDisplayString(item),\n                      PatchFlags.TEXT,\n                    )\n                  }),\n                  PatchFlags.STABLE_FRAGMENT,\n                )),\n              ],\n              PatchFlags.STABLE_FRAGMENT,\n            )\n          )\n        }\n      },\n    }\n\n    render(h(Comp), root)\n    expect(inner(root)).toBe('<div>0</div>')\n    updateFoo()\n    count.value++\n    await nextTick()\n    expect(inner(root)).toBe(\n      '<div>1</div><div>1_foo</div><div>2_foo</div><div>3_foo</div>',\n    )\n  })\n})\n"
  },
  {
    "path": "packages/runtime-core/__tests__/rendererTemplateRef.spec.ts",
    "content": "import {\n  KeepAlive,\n  defineAsyncComponent,\n  defineComponent,\n  h,\n  nextTick,\n  nodeOps,\n  reactive,\n  ref,\n  render,\n  serializeInner,\n  shallowRef,\n  watch,\n} from '@vue/runtime-test'\n\ndescribe('api: template refs', () => {\n  it('string ref mount', () => {\n    const root = nodeOps.createElement('div')\n    const el = ref(null)\n\n    const Comp = {\n      setup() {\n        return {\n          refKey: el,\n        }\n      },\n      render() {\n        return h('div', { ref: 'refKey' })\n      },\n    }\n    render(h(Comp), root)\n    expect(el.value).toBe(root.children[0])\n  })\n\n  it('string ref update', async () => {\n    const root = nodeOps.createElement('div')\n    const fooEl = ref(null)\n    const barEl = ref(null)\n    const refKey = ref('foo')\n\n    const Comp = {\n      setup() {\n        return {\n          foo: fooEl,\n          bar: barEl,\n        }\n      },\n      render() {\n        return h('div', { ref: refKey.value })\n      },\n    }\n    render(h(Comp), root)\n    expect(fooEl.value).toBe(root.children[0])\n    expect(barEl.value).toBe(null)\n\n    refKey.value = 'bar'\n    await nextTick()\n    expect(fooEl.value).toBe(null)\n    expect(barEl.value).toBe(root.children[0])\n  })\n\n  it('string ref unmount', async () => {\n    const root = nodeOps.createElement('div')\n    const el = ref(null)\n    const toggle = ref(true)\n\n    const Comp = {\n      setup() {\n        return {\n          refKey: el,\n        }\n      },\n      render() {\n        return toggle.value ? h('div', { ref: 'refKey' }) : null\n      },\n    }\n    render(h(Comp), root)\n    expect(el.value).toBe(root.children[0])\n\n    toggle.value = false\n    await nextTick()\n    expect(el.value).toBe(null)\n  })\n\n  it('function ref mount', () => {\n    const root = nodeOps.createElement('div')\n    const fn = vi.fn()\n\n    const Comp = defineComponent(() => () => h('div', { ref: fn }))\n    render(h(Comp), root)\n    expect(fn.mock.calls[0][0]).toBe(root.children[0])\n  })\n\n  it('function ref update', async () => {\n    const root = nodeOps.createElement('div')\n    const fn1 = vi.fn()\n    const fn2 = vi.fn()\n    const fn = ref(fn1)\n\n    const Comp = defineComponent(() => () => h('div', { ref: fn.value }))\n\n    render(h(Comp), root)\n    expect(fn1.mock.calls).toHaveLength(1)\n    expect(fn1.mock.calls[0][0]).toBe(root.children[0])\n    expect(fn2.mock.calls).toHaveLength(0)\n\n    fn.value = fn2\n    await nextTick()\n    expect(fn1.mock.calls).toHaveLength(1)\n    expect(fn2.mock.calls).toHaveLength(1)\n    expect(fn2.mock.calls[0][0]).toBe(root.children[0])\n  })\n\n  it('function ref unmount', async () => {\n    const root = nodeOps.createElement('div')\n    const fn = vi.fn()\n    const toggle = ref(true)\n\n    const Comp = defineComponent(\n      () => () => (toggle.value ? h('div', { ref: fn }) : null),\n    )\n    render(h(Comp), root)\n    expect(fn.mock.calls[0][0]).toBe(root.children[0])\n    toggle.value = false\n    await nextTick()\n    expect(fn.mock.calls[1][0]).toBe(null)\n  })\n\n  it('render function ref mount', () => {\n    const root = nodeOps.createElement('div')\n    const el = ref(null)\n\n    const Comp = {\n      setup() {\n        return () => h('div', { ref: el })\n      },\n    }\n    render(h(Comp), root)\n    expect(el.value).toBe(root.children[0])\n  })\n\n  it('render function ref update', async () => {\n    const root = nodeOps.createElement('div')\n    const refs = {\n      foo: ref(null),\n      bar: ref(null),\n    }\n    const refKey = ref<keyof typeof refs>('foo')\n\n    const Comp = {\n      setup() {\n        return () => h('div', { ref: refs[refKey.value] })\n      },\n    }\n    render(h(Comp), root)\n    expect(refs.foo.value).toBe(root.children[0])\n    expect(refs.bar.value).toBe(null)\n\n    refKey.value = 'bar'\n    await nextTick()\n    expect(refs.foo.value).toBe(null)\n    expect(refs.bar.value).toBe(root.children[0])\n  })\n\n  it('render function ref unmount', async () => {\n    const root = nodeOps.createElement('div')\n    const el = ref(null)\n    const toggle = ref(true)\n\n    const Comp = {\n      setup() {\n        return () => (toggle.value ? h('div', { ref: el }) : null)\n      },\n    }\n    render(h(Comp), root)\n    expect(el.value).toBe(root.children[0])\n\n    toggle.value = false\n    await nextTick()\n    expect(el.value).toBe(null)\n  })\n\n  // #12639\n  it('update and unmount child in the same tick', async () => {\n    const root = nodeOps.createElement('div')\n    const el = ref(null)\n    const toggle = ref(true)\n    const show = ref(true)\n\n    const Comp = defineComponent({\n      emits: ['change'],\n      props: ['show'],\n      setup(props, { emit }) {\n        watch(\n          () => props.show,\n          () => {\n            emit('change')\n          },\n        )\n        return () => h('div', 'hi')\n      },\n    })\n\n    const App = {\n      setup() {\n        return {\n          refKey: el,\n        }\n      },\n      render() {\n        return toggle.value\n          ? h(Comp, {\n              ref: 'refKey',\n              show: show.value,\n              onChange: () => (toggle.value = false),\n            })\n          : null\n      },\n    }\n    render(h(App), root)\n    expect(el.value).not.toBe(null)\n\n    show.value = false\n    await nextTick()\n    expect(el.value).toBe(null)\n  })\n\n  it('set and change ref in the same tick', async () => {\n    const root = nodeOps.createElement('div')\n    const show = ref(false)\n    const refName = ref('a')\n\n    const Child = defineComponent({\n      setup() {\n        refName.value = 'b'\n        return () => {}\n      },\n    })\n\n    const Comp = {\n      render() {\n        return h(Child, {\n          ref: refName.value,\n        })\n      },\n      updated(this: any) {\n        expect(this.$refs.a).toBe(null)\n        expect(this.$refs.b).not.toBe(null)\n      },\n    }\n\n    const App = {\n      render() {\n        return show.value ? h(Comp) : null\n      },\n    }\n\n    render(h(App), root)\n    expect(refName.value).toBe('a')\n\n    show.value = true\n    await nextTick()\n    expect(refName.value).toBe('b')\n  })\n\n  it('unset old ref when new ref is absent', async () => {\n    const root1 = nodeOps.createElement('div')\n    const root2 = nodeOps.createElement('div')\n    const el1 = ref(null)\n    const el2 = ref(null)\n    const toggle = ref(true)\n\n    const Comp1 = {\n      setup() {\n        return () => (toggle.value ? h('div', { ref: el1 }) : h('div'))\n      },\n    }\n\n    const Comp2 = {\n      setup() {\n        return () => h('div', { ref: toggle.value ? el2 : undefined })\n      },\n    }\n\n    render(h(Comp1), root1)\n    render(h(Comp2), root2)\n\n    expect(el1.value).toBe(root1.children[0])\n    expect(el2.value).toBe(root2.children[0])\n\n    toggle.value = false\n    await nextTick()\n    expect(el1.value).toBe(null)\n    expect(el2.value).toBe(null)\n  })\n\n  test('string ref inside slots', async () => {\n    const root = nodeOps.createElement('div')\n    const spy = vi.fn()\n    const Child = {\n      render(this: any) {\n        return this.$slots.default()\n      },\n    }\n\n    const Comp = {\n      render() {\n        return h(Child, () => {\n          return h('div', { ref: 'foo' })\n        })\n      },\n      mounted(this: any) {\n        spy(this.$refs.foo.tag)\n      },\n    }\n    render(h(Comp), root)\n\n    expect(spy).toHaveBeenCalledWith('div')\n  })\n\n  it('should work with direct reactive property', () => {\n    const root = nodeOps.createElement('div')\n    const state = reactive({\n      refKey: null,\n    })\n\n    const Comp = {\n      setup() {\n        return state\n      },\n      render() {\n        return h('div', { ref: 'refKey' })\n      },\n    }\n    render(h(Comp), root)\n    expect(state.refKey).toBe(root.children[0])\n    expect('Template ref \"refKey\" used on a non-ref value').toHaveBeenWarned()\n  })\n\n  test('multiple root refs', () => {\n    const root = nodeOps.createElement('div')\n    const refKey1 = ref(null)\n    const refKey2 = ref(null)\n    const refKey3 = ref(null)\n\n    const Comp = {\n      setup() {\n        return {\n          refKey1,\n          refKey2,\n          refKey3,\n        }\n      },\n      render() {\n        return [\n          h('div', { ref: 'refKey1' }),\n          h('div', { ref: 'refKey2' }),\n          h('div', { ref: 'refKey3' }),\n        ]\n      },\n    }\n    render(h(Comp), root)\n    expect(refKey1.value).toBe(root.children[1])\n    expect(refKey2.value).toBe(root.children[2])\n    expect(refKey3.value).toBe(root.children[3])\n  })\n\n  // #1505\n  test('reactive template ref in the same template', async () => {\n    const Comp = {\n      setup() {\n        const el = ref()\n        return { el }\n      },\n      render(this: any) {\n        return h('div', { id: 'foo', ref: 'el' }, this.el && this.el.props.id)\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(Comp), root)\n    // ref not ready on first render, but should queue an update immediately\n    expect(serializeInner(root)).toBe(`<div id=\"foo\"></div>`)\n    await nextTick()\n    // ref should be updated\n    expect(serializeInner(root)).toBe(`<div id=\"foo\">foo</div>`)\n  })\n\n  // #1834\n  test('exchange refs', async () => {\n    const refToggle = ref(false)\n    const spy = vi.fn()\n\n    const Comp = {\n      render(this: any) {\n        return [\n          h('p', { ref: refToggle.value ? 'foo' : 'bar' }),\n          h('i', { ref: refToggle.value ? 'bar' : 'foo' }),\n        ]\n      },\n      mounted(this: any) {\n        spy(this.$refs.foo.tag, this.$refs.bar.tag)\n      },\n      updated(this: any) {\n        spy(this.$refs.foo.tag, this.$refs.bar.tag)\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(Comp), root)\n\n    expect(spy.mock.calls[0][0]).toBe('i')\n    expect(spy.mock.calls[0][1]).toBe('p')\n    refToggle.value = true\n    await nextTick()\n    expect(spy.mock.calls[1][0]).toBe('p')\n    expect(spy.mock.calls[1][1]).toBe('i')\n  })\n\n  // #1789\n  test('toggle the same ref to different elements', async () => {\n    const refToggle = ref(false)\n    const spy = vi.fn()\n\n    const Comp = {\n      render(this: any) {\n        return refToggle.value ? h('p', { ref: 'foo' }) : h('i', { ref: 'foo' })\n      },\n      mounted(this: any) {\n        spy(this.$refs.foo.tag)\n      },\n      updated(this: any) {\n        spy(this.$refs.foo.tag)\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(Comp), root)\n\n    expect(spy.mock.calls[0][0]).toBe('i')\n    refToggle.value = true\n    await nextTick()\n    expect(spy.mock.calls[1][0]).toBe('p')\n  })\n\n  // #2078\n  test('handling multiple merged refs', async () => {\n    const Foo = {\n      render: () => h('div', 'foo'),\n    }\n    const Bar = {\n      render: () => h('div', 'bar'),\n    }\n\n    const viewRef = shallowRef<any>(Foo)\n    const elRef1 = ref()\n    const elRef2 = ref()\n\n    const App = {\n      render() {\n        if (!viewRef.value) {\n          return null\n        }\n        const view = h(viewRef.value, { ref: elRef1 })\n        return h(view, { ref: elRef2 })\n      },\n    }\n    const root = nodeOps.createElement('div')\n    render(h(App), root)\n\n    expect(serializeInner(elRef1.value.$el)).toBe('foo')\n    expect(elRef1.value).toBe(elRef2.value)\n\n    viewRef.value = Bar\n    await nextTick()\n    expect(serializeInner(elRef1.value.$el)).toBe('bar')\n    expect(elRef1.value).toBe(elRef2.value)\n\n    viewRef.value = null\n    await nextTick()\n    expect(elRef1.value).toBeNull()\n    expect(elRef1.value).toBe(elRef2.value)\n  })\n\n  // compiled output of <script setup> inline mode\n  test('raw ref with ref_key', () => {\n    let refs: any\n\n    const el = ref()\n\n    const App = {\n      mounted() {\n        refs = (this as any).$refs\n      },\n      render() {\n        return h(\n          'div',\n          {\n            ref: el,\n            ref_key: 'el',\n          },\n          'hello',\n        )\n      },\n    }\n    const root = nodeOps.createElement('div')\n    render(h(App), root)\n\n    expect(serializeInner(el.value)).toBe('hello')\n    expect(serializeInner(refs.el)).toBe('hello')\n  })\n\n  // compiled output of v-for + template ref\n  test('ref in v-for', async () => {\n    const show = ref(true)\n    const list = reactive([1, 2, 3])\n    const listRefs = ref([])\n    const mapRefs = () => listRefs.value.map(n => serializeInner(n))\n\n    const App = {\n      render() {\n        return show.value\n          ? h(\n              'ul',\n              list.map(i =>\n                h(\n                  'li',\n                  {\n                    ref: listRefs,\n                    ref_for: true,\n                  },\n                  i,\n                ),\n              ),\n            )\n          : null\n      },\n    }\n    const root = nodeOps.createElement('div')\n    render(h(App), root)\n\n    expect(mapRefs()).toMatchObject(['1', '2', '3'])\n\n    list.push(4)\n    await nextTick()\n    expect(mapRefs()).toMatchObject(['1', '2', '3', '4'])\n\n    list.shift()\n    await nextTick()\n    expect(mapRefs()).toMatchObject(['2', '3', '4'])\n\n    show.value = !show.value\n    await nextTick()\n\n    expect(mapRefs()).toMatchObject([])\n\n    show.value = !show.value\n    await nextTick()\n    expect(mapRefs()).toMatchObject(['2', '3', '4'])\n  })\n\n  test('named ref in v-for', async () => {\n    const show = ref(true)\n    const list = reactive([1, 2, 3])\n    const listRefs = ref([])\n    const mapRefs = () => listRefs.value.map(n => serializeInner(n))\n\n    const App = {\n      setup() {\n        return { listRefs }\n      },\n      render() {\n        return show.value\n          ? h(\n              'ul',\n              list.map(i =>\n                h(\n                  'li',\n                  {\n                    ref: 'listRefs',\n                    ref_for: true,\n                  },\n                  i,\n                ),\n              ),\n            )\n          : null\n      },\n    }\n    const root = nodeOps.createElement('div')\n    render(h(App), root)\n\n    expect(mapRefs()).toMatchObject(['1', '2', '3'])\n\n    list.push(4)\n    await nextTick()\n    expect(mapRefs()).toMatchObject(['1', '2', '3', '4'])\n\n    list.shift()\n    await nextTick()\n    expect(mapRefs()).toMatchObject(['2', '3', '4'])\n\n    show.value = !show.value\n    await nextTick()\n\n    expect(mapRefs()).toMatchObject([])\n\n    show.value = !show.value\n    await nextTick()\n    expect(mapRefs()).toMatchObject(['2', '3', '4'])\n  })\n\n  // #6697 v-for ref behaves differently under production and development\n  test('named ref in v-for , should be responsive when rendering', async () => {\n    const list = ref([1, 2, 3])\n    const listRefs = ref([])\n    const App = {\n      setup() {\n        return { listRefs }\n      },\n      render() {\n        return h('div', null, [\n          h('div', null, String(listRefs.value)),\n          h(\n            'ul',\n            list.value.map(i =>\n              h(\n                'li',\n                {\n                  ref: 'listRefs',\n                  ref_for: true,\n                },\n                i,\n              ),\n            ),\n          ),\n        ])\n      },\n    }\n    const root = nodeOps.createElement('div')\n    render(h(App), root)\n\n    await nextTick()\n    expect(String(listRefs.value)).toBe(\n      '[object Object],[object Object],[object Object]',\n    )\n    expect(serializeInner(root)).toBe(\n      '<div><div>[object Object],[object Object],[object Object]</div><ul><li>1</li><li>2</li><li>3</li></ul></div>',\n    )\n\n    list.value.splice(0, 1)\n    await nextTick()\n    expect(String(listRefs.value)).toBe('[object Object],[object Object]')\n    expect(serializeInner(root)).toBe(\n      '<div><div>[object Object],[object Object]</div><ul><li>2</li><li>3</li></ul></div>',\n    )\n  })\n\n  test('with async component which nested in KeepAlive', async () => {\n    const AsyncComp = defineAsyncComponent(\n      () =>\n        new Promise(resolve =>\n          setTimeout(() =>\n            resolve(\n              defineComponent({\n                setup(_, { expose }) {\n                  expose({\n                    name: 'AsyncComp',\n                  })\n                  return () => h('div')\n                },\n              }) as any,\n            ),\n          ),\n        ),\n    )\n\n    const Comp = defineComponent({\n      setup(_, { expose }) {\n        expose({\n          name: 'Comp',\n        })\n        return () => h('div')\n      },\n    })\n\n    const toggle = ref(false)\n    const instanceRef = ref<any>(null)\n\n    const App = {\n      render: () => {\n        return h(KeepAlive, () =>\n          toggle.value\n            ? h(AsyncComp, { ref: instanceRef })\n            : h(Comp, { ref: instanceRef }),\n        )\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(App), root)\n    expect(instanceRef.value.name).toBe('Comp')\n\n    // switch to async component\n    toggle.value = true\n    await nextTick()\n    expect(instanceRef.value).toBe(null)\n\n    await new Promise(r => setTimeout(r))\n    expect(instanceRef.value.name).toBe('AsyncComp')\n\n    // switch back to normal component\n    toggle.value = false\n    await nextTick()\n    expect(instanceRef.value.name).toBe('Comp')\n\n    // switch to async component again\n    toggle.value = true\n    await nextTick()\n    expect(instanceRef.value.name).toBe('AsyncComp')\n  })\n})\n"
  },
  {
    "path": "packages/runtime-core/__tests__/scheduler.spec.ts",
    "content": "import {\n  type SchedulerJob,\n  SchedulerJobFlags,\n  flushPostFlushCbs,\n  flushPreFlushCbs,\n  nextTick,\n  queueJob,\n  queuePostFlushCb,\n} from '../src/scheduler'\n\ndescribe('scheduler', () => {\n  it('nextTick', async () => {\n    const calls: string[] = []\n    const dummyThen = Promise.resolve().then()\n    const job1 = () => {\n      calls.push('job1')\n    }\n    const job2 = () => {\n      calls.push('job2')\n    }\n    nextTick(job1)\n    job2()\n\n    expect(calls.length).toBe(1)\n    await dummyThen\n    // job1 will be pushed in nextTick\n    expect(calls.length).toBe(2)\n    expect(calls).toMatchObject(['job2', 'job1'])\n  })\n\n  describe('queueJob', () => {\n    it('basic usage', async () => {\n      const calls: string[] = []\n      const job1 = () => {\n        calls.push('job1')\n      }\n      const job2 = () => {\n        calls.push('job2')\n      }\n      queueJob(job1)\n      queueJob(job2)\n      expect(calls).toEqual([])\n      await nextTick()\n      expect(calls).toEqual(['job1', 'job2'])\n    })\n\n    it(\"should insert jobs in ascending order of job's id when flushing\", async () => {\n      const calls: string[] = []\n      const job1 = () => {\n        calls.push('job1')\n\n        queueJob(job2)\n        queueJob(job3)\n      }\n\n      const job2 = () => {\n        calls.push('job2')\n        queueJob(job4)\n        queueJob(job5)\n      }\n      job2.id = 10\n\n      const job3 = () => {\n        calls.push('job3')\n      }\n      job3.id = 1\n\n      const job4 = () => {\n        calls.push('job4')\n      }\n\n      const job5 = () => {\n        calls.push('job5')\n      }\n\n      queueJob(job1)\n\n      expect(calls).toEqual([])\n      await nextTick()\n      expect(calls).toEqual(['job1', 'job3', 'job2', 'job4', 'job5'])\n    })\n\n    it('should dedupe queued jobs', async () => {\n      const calls: string[] = []\n      const job1 = () => {\n        calls.push('job1')\n      }\n      const job2 = () => {\n        calls.push('job2')\n      }\n      queueJob(job1)\n      queueJob(job2)\n      queueJob(job1)\n      queueJob(job2)\n      expect(calls).toEqual([])\n      await nextTick()\n      expect(calls).toEqual(['job1', 'job2'])\n    })\n\n    it('queueJob while flushing', async () => {\n      const calls: string[] = []\n      const job1 = () => {\n        calls.push('job1')\n        // job2 will be executed after job1 at the same tick\n        queueJob(job2)\n      }\n      const job2 = () => {\n        calls.push('job2')\n      }\n      queueJob(job1)\n\n      await nextTick()\n      expect(calls).toEqual(['job1', 'job2'])\n    })\n  })\n\n  describe('pre flush jobs', () => {\n    it('queueJob inside preFlushCb', async () => {\n      const calls: string[] = []\n      const job1 = () => {\n        calls.push('job1')\n      }\n      const cb1: SchedulerJob = () => {\n        // queueJob in postFlushCb\n        calls.push('cb1')\n        queueJob(job1)\n      }\n      cb1.flags! |= SchedulerJobFlags.PRE\n\n      queueJob(cb1)\n      await nextTick()\n      expect(calls).toEqual(['cb1', 'job1'])\n    })\n\n    it('queueJob & preFlushCb inside preFlushCb', async () => {\n      const calls: string[] = []\n      const job1 = () => {\n        calls.push('job1')\n      }\n      job1.id = 1\n\n      const cb1: SchedulerJob = () => {\n        calls.push('cb1')\n        queueJob(job1)\n        // cb2 should execute before the job\n        queueJob(cb2)\n        queueJob(cb3)\n      }\n      cb1.flags! |= SchedulerJobFlags.PRE\n\n      const cb2: SchedulerJob = () => {\n        calls.push('cb2')\n      }\n      cb2.flags! |= SchedulerJobFlags.PRE\n      cb2.id = 1\n\n      const cb3: SchedulerJob = () => {\n        calls.push('cb3')\n      }\n      cb3.flags! |= SchedulerJobFlags.PRE\n      cb3.id = 1\n\n      queueJob(cb1)\n      await nextTick()\n      expect(calls).toEqual(['cb1', 'cb2', 'cb3', 'job1'])\n    })\n\n    it('should insert jobs after pre jobs with the same id', async () => {\n      const calls: string[] = []\n      const job1: SchedulerJob = () => {\n        calls.push('job1')\n      }\n      job1.id = 1\n      job1.flags! |= SchedulerJobFlags.PRE\n      const job2: SchedulerJob = () => {\n        calls.push('job2')\n        queueJob(job5)\n        queueJob(job6)\n      }\n      job2.id = 2\n      job2.flags! |= SchedulerJobFlags.PRE\n      const job3: SchedulerJob = () => {\n        calls.push('job3')\n      }\n      job3.id = 2\n      job3.flags! |= SchedulerJobFlags.PRE\n      const job4: SchedulerJob = () => {\n        calls.push('job4')\n      }\n      job4.id = 3\n      job4.flags! |= SchedulerJobFlags.PRE\n      const job5: SchedulerJob = () => {\n        calls.push('job5')\n      }\n      job5.id = 2\n      const job6: SchedulerJob = () => {\n        calls.push('job6')\n      }\n      job6.id = 2\n      job6.flags! |= SchedulerJobFlags.PRE\n\n      // We need several jobs to test this properly, otherwise\n      // findInsertionIndex can yield the correct index by chance\n      queueJob(job4)\n      queueJob(job2)\n      queueJob(job3)\n      queueJob(job1)\n\n      await nextTick()\n      expect(calls).toEqual(['job1', 'job2', 'job3', 'job6', 'job5', 'job4'])\n    })\n\n    it('preFlushCb inside queueJob', async () => {\n      const calls: string[] = []\n      const job1 = () => {\n        // the only case where a pre-flush cb can be queued inside a job is\n        // when updating the props of a child component. This is handled\n        // directly inside `updateComponentPreRender` to avoid non atomic\n        // cb triggers (#1763)\n        queueJob(cb1)\n        queueJob(cb2)\n        flushPreFlushCbs()\n        calls.push('job1')\n      }\n      const cb1: SchedulerJob = () => {\n        calls.push('cb1')\n        // a cb triggers its parent job, which should be skipped\n        queueJob(job1)\n      }\n      cb1.flags! |= SchedulerJobFlags.PRE\n      const cb2: SchedulerJob = () => {\n        calls.push('cb2')\n      }\n      cb2.flags! |= SchedulerJobFlags.PRE\n\n      queueJob(job1)\n      await nextTick()\n      expect(calls).toEqual(['cb1', 'cb2', 'job1'])\n    })\n\n    it('should insert pre jobs without ids first during flushing', async () => {\n      const calls: string[] = []\n      const job1: SchedulerJob = () => {\n        calls.push('job1')\n        queueJob(job3)\n        queueJob(job4)\n      }\n      // job1 has no id\n      job1.flags! |= SchedulerJobFlags.PRE\n      const job2: SchedulerJob = () => {\n        calls.push('job2')\n      }\n      job2.id = 1\n      job2.flags! |= SchedulerJobFlags.PRE\n      const job3: SchedulerJob = () => {\n        calls.push('job3')\n      }\n      // job3 has no id\n      job3.flags! |= SchedulerJobFlags.PRE\n      const job4: SchedulerJob = () => {\n        calls.push('job4')\n      }\n      // job4 has no id\n      job4.flags! |= SchedulerJobFlags.PRE\n\n      queueJob(job1)\n      queueJob(job2)\n      await nextTick()\n      expect(calls).toEqual(['job1', 'job3', 'job4', 'job2'])\n    })\n\n    // #3806\n    it('queue preFlushCb inside postFlushCb', async () => {\n      const spy = vi.fn()\n      const cb: SchedulerJob = () => spy()\n      cb.flags! |= SchedulerJobFlags.PRE\n      queuePostFlushCb(() => {\n        queueJob(cb)\n      })\n      await nextTick()\n      expect(spy).toHaveBeenCalled()\n    })\n  })\n\n  describe('queuePostFlushCb', () => {\n    it('basic usage', async () => {\n      const calls: string[] = []\n      const cb1 = () => {\n        calls.push('cb1')\n      }\n      const cb2 = () => {\n        calls.push('cb2')\n      }\n      const cb3 = () => {\n        calls.push('cb3')\n      }\n\n      queuePostFlushCb([cb1, cb2])\n      queuePostFlushCb(cb3)\n\n      expect(calls).toEqual([])\n      await nextTick()\n      expect(calls).toEqual(['cb1', 'cb2', 'cb3'])\n    })\n\n    it('should dedupe queued postFlushCb', async () => {\n      const calls: string[] = []\n      const cb1 = () => {\n        calls.push('cb1')\n      }\n      const cb2 = () => {\n        calls.push('cb2')\n      }\n      const cb3 = () => {\n        calls.push('cb3')\n      }\n\n      queuePostFlushCb([cb1, cb2])\n      queuePostFlushCb(cb3)\n\n      queuePostFlushCb([cb1, cb3])\n      queuePostFlushCb(cb2)\n\n      expect(calls).toEqual([])\n      await nextTick()\n      expect(calls).toEqual(['cb1', 'cb2', 'cb3'])\n    })\n\n    it('queuePostFlushCb while flushing', async () => {\n      const calls: string[] = []\n      const cb1 = () => {\n        calls.push('cb1')\n        // cb2 will be executed after cb1 at the same tick\n        queuePostFlushCb(cb2)\n      }\n      const cb2 = () => {\n        calls.push('cb2')\n      }\n      queuePostFlushCb(cb1)\n\n      await nextTick()\n      expect(calls).toEqual(['cb1', 'cb2'])\n    })\n  })\n\n  describe('queueJob w/ queuePostFlushCb', () => {\n    it('queueJob inside postFlushCb', async () => {\n      const calls: string[] = []\n      const job1 = () => {\n        calls.push('job1')\n      }\n      const cb1 = () => {\n        // queueJob in postFlushCb\n        calls.push('cb1')\n        queueJob(job1)\n      }\n\n      queuePostFlushCb(cb1)\n      await nextTick()\n      expect(calls).toEqual(['cb1', 'job1'])\n    })\n\n    it('queueJob & postFlushCb inside postFlushCb', async () => {\n      const calls: string[] = []\n      const job1 = () => {\n        calls.push('job1')\n      }\n      const cb1 = () => {\n        calls.push('cb1')\n        queuePostFlushCb(cb2)\n        // job1 will executed before cb2\n        // Job has higher priority than postFlushCb\n        queueJob(job1)\n      }\n      const cb2 = () => {\n        calls.push('cb2')\n      }\n\n      queuePostFlushCb(cb1)\n      await nextTick()\n      expect(calls).toEqual(['cb1', 'job1', 'cb2'])\n    })\n\n    it('postFlushCb inside queueJob', async () => {\n      const calls: string[] = []\n      const job1 = () => {\n        calls.push('job1')\n        // postFlushCb in queueJob\n        queuePostFlushCb(cb1)\n      }\n      const cb1 = () => {\n        calls.push('cb1')\n      }\n\n      queueJob(job1)\n      await nextTick()\n      expect(calls).toEqual(['job1', 'cb1'])\n    })\n\n    it('queueJob & postFlushCb inside queueJob', async () => {\n      const calls: string[] = []\n      const job1 = () => {\n        calls.push('job1')\n        // cb1 will executed after job2\n        // Job has higher priority than postFlushCb\n        queuePostFlushCb(cb1)\n        queueJob(job2)\n      }\n      const job2 = () => {\n        calls.push('job2')\n      }\n      const cb1 = () => {\n        calls.push('cb1')\n      }\n\n      queueJob(job1)\n      await nextTick()\n      expect(calls).toEqual(['job1', 'job2', 'cb1'])\n    })\n\n    it('nested queueJob w/ postFlushCb', async () => {\n      const calls: string[] = []\n      const job1 = () => {\n        calls.push('job1')\n\n        queuePostFlushCb(cb1)\n        queueJob(job2)\n      }\n      const job2 = () => {\n        calls.push('job2')\n        queuePostFlushCb(cb2)\n      }\n      const cb1 = () => {\n        calls.push('cb1')\n      }\n      const cb2 = () => {\n        calls.push('cb2')\n      }\n\n      queueJob(job1)\n      await nextTick()\n      expect(calls).toEqual(['job1', 'job2', 'cb1', 'cb2'])\n    })\n\n    test('jobs added during post flush are ordered correctly', async () => {\n      const calls: string[] = []\n\n      const job1: SchedulerJob = () => {\n        calls.push('job1')\n      }\n      job1.id = 1\n\n      const job2: SchedulerJob = () => {\n        calls.push('job2')\n      }\n      job2.id = 2\n\n      queuePostFlushCb(() => {\n        queueJob(job2)\n        queueJob(job1)\n      })\n\n      await nextTick()\n\n      expect(calls).toEqual(['job1', 'job2'])\n    })\n  })\n\n  test('sort job based on id', async () => {\n    const calls: string[] = []\n    const job1 = () => calls.push('job1')\n    // job1 has no id\n    const job2 = () => calls.push('job2')\n    job2.id = 2\n    const job3 = () => calls.push('job3')\n    job3.id = 1\n    const job4: SchedulerJob = () => calls.push('job4')\n    job4.id = 2\n    job4.flags! |= SchedulerJobFlags.PRE\n    const job5: SchedulerJob = () => calls.push('job5')\n    // job5 has no id\n    job5.flags! |= SchedulerJobFlags.PRE\n\n    queueJob(job1)\n    queueJob(job2)\n    queueJob(job3)\n    queueJob(job4)\n    queueJob(job5)\n    await nextTick()\n    expect(calls).toEqual(['job5', 'job3', 'job4', 'job2', 'job1'])\n  })\n\n  test('sort SchedulerCbs based on id', async () => {\n    const calls: string[] = []\n    const cb1 = () => calls.push('cb1')\n    // cb1 has no id\n    const cb2 = () => calls.push('cb2')\n    cb2.id = 2\n    const cb3 = () => calls.push('cb3')\n    cb3.id = 1\n\n    queuePostFlushCb(cb1)\n    queuePostFlushCb(cb2)\n    queuePostFlushCb(cb3)\n    await nextTick()\n    expect(calls).toEqual(['cb3', 'cb2', 'cb1'])\n  })\n\n  // #1595\n  test('avoid duplicate postFlushCb invocation', async () => {\n    const calls: string[] = []\n    const cb1 = () => {\n      calls.push('cb1')\n      queuePostFlushCb(cb2)\n    }\n    const cb2 = () => {\n      calls.push('cb2')\n    }\n    queuePostFlushCb(cb1)\n    queuePostFlushCb(cb2)\n    await nextTick()\n    expect(calls).toEqual(['cb1', 'cb2'])\n  })\n\n  test('nextTick should capture scheduler flush errors', async () => {\n    const err = new Error('test')\n    queueJob(() => {\n      throw err\n    })\n    try {\n      await nextTick()\n    } catch (e: any) {\n      expect(e).toBe(err)\n    }\n    expect(\n      `Unhandled error during execution of scheduler flush`,\n    ).toHaveBeenWarned()\n\n    // this one should no longer error\n    await nextTick()\n  })\n\n  test('jobs can be re-queued after an error', async () => {\n    const err = new Error('test')\n    let shouldThrow = true\n\n    const job1: SchedulerJob = vi.fn(() => {\n      if (shouldThrow) {\n        shouldThrow = false\n        throw err\n      }\n    })\n    job1.id = 1\n\n    const job2: SchedulerJob = vi.fn()\n    job2.id = 2\n\n    queueJob(job1)\n    queueJob(job2)\n\n    try {\n      await nextTick()\n    } catch (e: any) {\n      expect(e).toBe(err)\n    }\n    expect(\n      `Unhandled error during execution of scheduler flush`,\n    ).toHaveBeenWarned()\n\n    expect(job1).toHaveBeenCalledTimes(1)\n    expect(job2).toHaveBeenCalledTimes(0)\n\n    queueJob(job1)\n    queueJob(job2)\n\n    await nextTick()\n\n    expect(job1).toHaveBeenCalledTimes(2)\n    expect(job2).toHaveBeenCalledTimes(1)\n  })\n\n  test('should prevent self-triggering jobs by default', async () => {\n    let count = 0\n    const job = () => {\n      if (count < 3) {\n        count++\n        queueJob(job)\n      }\n    }\n    queueJob(job)\n    await nextTick()\n    // only runs once - a job cannot queue itself\n    expect(count).toBe(1)\n  })\n\n  test('should allow explicitly marked jobs to trigger itself', async () => {\n    // normal job\n    let count = 0\n    const job: SchedulerJob = () => {\n      if (count < 3) {\n        count++\n        queueJob(job)\n      }\n    }\n    job.flags! |= SchedulerJobFlags.ALLOW_RECURSE\n    queueJob(job)\n    await nextTick()\n    expect(count).toBe(3)\n\n    // post cb\n    const cb: SchedulerJob = () => {\n      if (count < 5) {\n        count++\n        queuePostFlushCb(cb)\n      }\n    }\n    cb.flags! |= SchedulerJobFlags.ALLOW_RECURSE\n    queuePostFlushCb(cb)\n    await nextTick()\n    expect(count).toBe(5)\n  })\n\n  test('recursive jobs can only be queued once non-recursively', async () => {\n    const job: SchedulerJob = vi.fn()\n    job.id = 1\n    job.flags = SchedulerJobFlags.ALLOW_RECURSE\n\n    queueJob(job)\n    queueJob(job)\n\n    await nextTick()\n\n    expect(job).toHaveBeenCalledTimes(1)\n  })\n\n  test('recursive jobs can only be queued once recursively', async () => {\n    let recurse = true\n\n    const job: SchedulerJob = vi.fn(() => {\n      if (recurse) {\n        queueJob(job)\n        queueJob(job)\n        recurse = false\n      }\n    })\n    job.id = 1\n    job.flags = SchedulerJobFlags.ALLOW_RECURSE\n\n    queueJob(job)\n\n    await nextTick()\n\n    expect(job).toHaveBeenCalledTimes(2)\n  })\n\n  test(`recursive jobs can't be re-queued by other jobs`, async () => {\n    let recurse = true\n\n    const job1: SchedulerJob = () => {\n      if (recurse) {\n        // job2 is already queued, so this shouldn't do anything\n        queueJob(job2)\n        recurse = false\n      }\n    }\n    job1.id = 1\n\n    const job2: SchedulerJob = vi.fn(() => {\n      if (recurse) {\n        queueJob(job1)\n        queueJob(job2)\n      }\n    })\n    job2.id = 2\n    job2.flags = SchedulerJobFlags.ALLOW_RECURSE\n\n    queueJob(job2)\n\n    await nextTick()\n\n    expect(job2).toHaveBeenCalledTimes(2)\n  })\n\n  test('jobs are de-duplicated correctly when calling flushPreFlushCbs', async () => {\n    let recurse = true\n\n    const job1: SchedulerJob = vi.fn(() => {\n      queueJob(job3)\n      queueJob(job3)\n      flushPreFlushCbs()\n    })\n    job1.id = 1\n    job1.flags = SchedulerJobFlags.PRE\n\n    const job2: SchedulerJob = vi.fn(() => {\n      if (recurse) {\n        // job2 does not allow recurse, so this shouldn't do anything\n        queueJob(job2)\n\n        // job3 is already queued, so this shouldn't do anything\n        queueJob(job3)\n        recurse = false\n      }\n    })\n    job2.id = 2\n    job2.flags = SchedulerJobFlags.PRE\n\n    const job3: SchedulerJob = vi.fn(() => {\n      if (recurse) {\n        queueJob(job2)\n        queueJob(job3)\n\n        // The jobs are already queued, so these should have no effect\n        queueJob(job2)\n        queueJob(job3)\n      }\n    })\n    job3.id = 3\n    job3.flags = SchedulerJobFlags.ALLOW_RECURSE | SchedulerJobFlags.PRE\n\n    queueJob(job1)\n\n    await nextTick()\n\n    expect(job1).toHaveBeenCalledTimes(1)\n    expect(job2).toHaveBeenCalledTimes(1)\n    expect(job3).toHaveBeenCalledTimes(2)\n  })\n\n  // #1947 flushPostFlushCbs should handle nested calls\n  // e.g. app.mount inside app.mount\n  test('flushPostFlushCbs', async () => {\n    let count = 0\n\n    const queueAndFlush = (hook: Function) => {\n      queuePostFlushCb(hook)\n      flushPostFlushCbs()\n    }\n\n    queueAndFlush(() => {\n      queueAndFlush(() => {\n        count++\n      })\n    })\n\n    await nextTick()\n    expect(count).toBe(1)\n  })\n\n  // #910\n  test('should not run stopped reactive effects', async () => {\n    const spy = vi.fn()\n\n    // simulate parent component that toggles child\n    const job1 = () => {\n      // @ts-expect-error\n      job2.flags! |= SchedulerJobFlags.DISPOSED\n    }\n    // simulate child that's triggered by the same reactive change that\n    // triggers its toggle\n    const job2 = () => spy()\n    expect(spy).toHaveBeenCalledTimes(0)\n\n    queueJob(job1)\n    queueJob(job2)\n    await nextTick()\n\n    // should not be called\n    expect(spy).toHaveBeenCalledTimes(0)\n  })\n\n  it('flushPreFlushCbs inside a pre job', async () => {\n    const spy = vi.fn()\n    const job: SchedulerJob = () => {\n      spy()\n      flushPreFlushCbs()\n    }\n    job.flags! |= SchedulerJobFlags.PRE\n    queueJob(job)\n    await nextTick()\n    expect(spy).toHaveBeenCalledTimes(1)\n  })\n\n  test('flushPreFlushCbs inside a post job', async () => {\n    const calls: string[] = []\n    const callsAfterFlush: string[] = []\n\n    const job1: SchedulerJob = () => {\n      calls.push('job1')\n    }\n    job1.id = 1\n    job1.flags! |= SchedulerJobFlags.PRE\n\n    const job2: SchedulerJob = () => {\n      calls.push('job2')\n    }\n    job2.id = 2\n    job2.flags! |= SchedulerJobFlags.PRE\n\n    queuePostFlushCb(() => {\n      queueJob(job2)\n      queueJob(job1)\n\n      // e.g. nested app.mount() call\n      flushPreFlushCbs()\n      callsAfterFlush.push(...calls)\n    })\n\n    await nextTick()\n\n    expect(callsAfterFlush).toEqual(['job1', 'job2'])\n    expect(calls).toEqual(['job1', 'job2'])\n  })\n\n  it('nextTick should return promise', async () => {\n    const fn = vi.fn(() => {\n      return 1\n    })\n\n    const p = nextTick(fn)\n\n    expect(p).toBeInstanceOf(Promise)\n    expect(await p).toBe(1)\n    expect(fn).toHaveBeenCalledTimes(1)\n  })\n\n  // #10003\n  test('nested flushPostFlushCbs', async () => {\n    const calls: string[] = []\n    const cb1 = () => calls.push('cb1')\n    // cb1 has no id\n    const cb2 = () => calls.push('cb2')\n    cb2.id = -1\n    const queueAndFlush = (hook: Function) => {\n      queuePostFlushCb(hook)\n      flushPostFlushCbs()\n    }\n\n    queueAndFlush(() => {\n      queuePostFlushCb([cb1, cb2])\n      flushPostFlushCbs()\n    })\n\n    await nextTick()\n    expect(calls).toEqual(['cb2', 'cb1'])\n  })\n})\n"
  },
  {
    "path": "packages/runtime-core/__tests__/scopeId.spec.ts",
    "content": "import {\n  Fragment,\n  Suspense,\n  createBlock,\n  createCommentVNode,\n  createVNode,\n  defineComponent,\n  h,\n  nextTick,\n  nodeOps,\n  openBlock,\n  popScopeId,\n  pushScopeId,\n  ref,\n  render,\n  renderSlot,\n  serializeInner,\n  withScopeId,\n} from '@vue/runtime-test'\nimport { withCtx } from '../src/componentRenderContext'\nimport { PatchFlags } from '@vue/shared'\n\ndescribe('scopeId runtime support', () => {\n  test('should attach scopeId', () => {\n    const App = {\n      __scopeId: 'parent',\n      render: () => h('div', [h('div')]),\n    }\n    const root = nodeOps.createElement('div')\n    render(h(App), root)\n    expect(serializeInner(root)).toBe(`<div parent><div parent></div></div>`)\n  })\n\n  test('should attach scopeId to components in parent component', () => {\n    const Child = {\n      __scopeId: 'child',\n      render: () => h('div'),\n    }\n    const App = {\n      __scopeId: 'parent',\n      render: () => h('div', [h(Child)]),\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(App), root)\n    expect(serializeInner(root)).toBe(\n      `<div parent><div child parent></div></div>`,\n    )\n  })\n\n  // #5148\n  test('should attach scopeId to suspense content', async () => {\n    const deps: Promise<any>[] = []\n    const Child = {\n      async setup() {\n        const p = new Promise(r => setTimeout(r, 1))\n        deps.push(p.then(() => Promise.resolve()))\n\n        await p\n        return () => h('div', 'async')\n      },\n    }\n\n    const Wrapper = {\n      setup(_: any, { slots }: any) {\n        return () => slots.default({ Component: h(Child) })\n      },\n    }\n\n    const App = {\n      __scopeId: 'parent',\n      setup() {\n        return () =>\n          h(Wrapper, null, {\n            default: withCtx(({ Component }: any) =>\n              h(Suspense, null, {\n                default: h(Component),\n                fallback: h('div', 'fallback'),\n              }),\n            ),\n          })\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(App), root)\n    expect(serializeInner(root)).toBe(`<div parent>fallback</div>`)\n\n    await Promise.all(deps)\n    await nextTick()\n    expect(serializeInner(root)).toBe(`<div parent>async</div>`)\n  })\n\n  // :slotted basic\n  test('should work on slots', () => {\n    const Child = {\n      __scopeId: 'child',\n      render(this: any) {\n        return h('div', renderSlot(this.$slots, 'default'))\n      },\n    }\n    const Child2 = {\n      __scopeId: 'child2',\n      render: () => h('span'),\n    }\n    const App = {\n      __scopeId: 'parent',\n      render: () => {\n        return h(\n          Child,\n          withCtx(() => {\n            return [h('div'), h(Child2)]\n          }),\n        )\n      },\n    }\n    const root = nodeOps.createElement('div')\n    render(h(App), root)\n    // slot content should have:\n    // - scopeId from parent\n    // - slotted scopeId (with `-s` postfix) from child (the tree owner)\n    expect(serializeInner(root)).toBe(\n      `<div child parent>` +\n        `<div parent child-s></div>` +\n        // component inside slot should have:\n        // - scopeId from template context\n        // - slotted scopeId from slot owner\n        // - its own scopeId\n        `<span child2 parent child-s></span>` +\n        `</div>`,\n    )\n  })\n\n  // #2892\n  test(':slotted on forwarded slots', async () => {\n    const Wrapper = {\n      __scopeId: 'wrapper',\n      render(this: any) {\n        // <div class=\"wrapper\"><slot/></div>\n        return h('div', { class: 'wrapper' }, [\n          renderSlot(\n            this.$slots,\n            'default',\n            {},\n            undefined,\n            true /* noSlotted */,\n          ),\n        ])\n      },\n    }\n\n    const Slotted = {\n      __scopeId: 'slotted',\n      render(this: any) {\n        // <Wrapper><slot/></Wrapper>\n        return h(Wrapper, null, {\n          default: withCtx(() => [renderSlot(this.$slots, 'default')]),\n        })\n      },\n    }\n\n    // simulate hoisted node\n    pushScopeId('root')\n    const hoisted = h('div', 'hoisted')\n    popScopeId()\n\n    const Root = {\n      __scopeId: 'root',\n      render(this: any) {\n        // <Slotted><div>hoisted</div><div>{{ dynamic }}</div></Slotted>\n        return h(Slotted, null, {\n          default: withCtx(() => {\n            return [hoisted, h('div', 'dynamic')]\n          }),\n        })\n      },\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(Root), root)\n    expect(serializeInner(root)).toBe(\n      `<div wrapper slotted root class=\"wrapper\">` +\n        `<div root slotted-s>hoisted</div>` +\n        `<div root slotted-s>dynamic</div>` +\n        `</div>`,\n    )\n\n    const Root2 = {\n      __scopeId: 'root',\n      render(this: any) {\n        // <Slotted>\n        //  <Wrapper>\n        //    <div>hoisted</div><div>{{ dynamic }}</div>\n        //  </Wrapper>\n        // </Slotted>\n        return h(Slotted, null, {\n          default: withCtx(() => [\n            h(Wrapper, null, {\n              default: withCtx(() => [hoisted, h('div', 'dynamic')]),\n            }),\n          ]),\n        })\n      },\n    }\n    const root2 = nodeOps.createElement('div')\n    render(h(Root2), root2)\n    expect(serializeInner(root2)).toBe(\n      `<div wrapper slotted root class=\"wrapper\">` +\n        `<div wrapper root slotted-s class=\"wrapper\">` +\n        `<div root>hoisted</div>` +\n        `<div root>dynamic</div>` +\n        `</div>` +\n        `</div>`,\n    )\n  })\n\n  // #1988\n  test('should inherit scopeId through nested HOCs with inheritAttrs: false', () => {\n    const App = {\n      __scopeId: 'parent',\n      render: () => {\n        return h(Child)\n      },\n    }\n\n    function Child() {\n      return h(Child2, { class: 'foo' })\n    }\n\n    function Child2() {\n      return h('div')\n    }\n    Child2.inheritAttrs = false\n\n    const root = nodeOps.createElement('div')\n    render(h(App), root)\n\n    expect(serializeInner(root)).toBe(`<div parent></div>`)\n  })\n\n  test('should inherit scopeId through nested DEV_ROOT_FRAGMENT with inheritAttrs: false', async () => {\n    const Parent = {\n      __scopeId: 'parent',\n      render() {\n        return h(Child, { class: 'foo' })\n      },\n    }\n\n    const ok = ref(true)\n    const Child = defineComponent({\n      inheritAttrs: false,\n      render() {\n        return (\n          openBlock(),\n          createBlock(\n            Fragment,\n            null,\n            [\n              createCommentVNode('comment1'),\n              ok.value\n                ? (openBlock(), createBlock('div', { key: 0 }, 'div1'))\n                : (openBlock(),\n                  createBlock(\n                    Fragment,\n                    { key: 1 },\n                    [\n                      createCommentVNode('comment2'),\n                      createVNode('div', null, 'div2'),\n                    ],\n                    PatchFlags.STABLE_FRAGMENT | PatchFlags.DEV_ROOT_FRAGMENT,\n                  )),\n            ],\n            PatchFlags.STABLE_FRAGMENT | PatchFlags.DEV_ROOT_FRAGMENT,\n          )\n        )\n      },\n    })\n\n    const root = nodeOps.createElement('div')\n    render(h(Parent), root)\n    expect(serializeInner(root)).toBe(`<!--comment1--><div parent>div1</div>`)\n\n    ok.value = false\n    await nextTick()\n    expect(serializeInner(root)).toBe(\n      `<!--comment1--><!--comment2--><div parent>div2</div>`,\n    )\n  })\n})\n\ndescribe('backwards compat with <=3.0.7', () => {\n  const withParentId = withScopeId('parent')\n  const withChildId = withScopeId('child')\n\n  test('should attach scopeId', () => {\n    const App = {\n      __scopeId: 'parent',\n      render: withParentId(() => {\n        return h('div', [h('div')])\n      }),\n    }\n    const root = nodeOps.createElement('div')\n    render(h(App), root)\n    expect(serializeInner(root)).toBe(`<div parent><div parent></div></div>`)\n  })\n\n  test('should attach scopeId to components in parent component', () => {\n    const Child = {\n      __scopeId: 'child',\n      render: withChildId(() => {\n        return h('div')\n      }),\n    }\n    const App = {\n      __scopeId: 'parent',\n      render: withParentId(() => {\n        return h('div', [h(Child)])\n      }),\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(App), root)\n    expect(serializeInner(root)).toBe(\n      `<div parent><div child parent></div></div>`,\n    )\n  })\n\n  test('should work on slots', () => {\n    const Child = {\n      __scopeId: 'child',\n      render: withChildId(function (this: any) {\n        return h('div', renderSlot(this.$slots, 'default'))\n      }),\n    }\n    const withChild2Id = withScopeId('child2')\n    const Child2 = {\n      __scopeId: 'child2',\n      render: withChild2Id(() => h('span')),\n    }\n    const App = {\n      __scopeId: 'parent',\n      render: withParentId(() => {\n        return h(\n          Child,\n          withParentId(() => {\n            return [h('div'), h(Child2)]\n          }),\n        )\n      }),\n    }\n    const root = nodeOps.createElement('div')\n    render(h(App), root)\n    // slot content should have:\n    // - scopeId from parent\n    // - slotted scopeId (with `-s` postfix) from child (the tree owner)\n    expect(serializeInner(root)).toBe(\n      `<div child parent>` +\n        `<div parent child-s></div>` +\n        // component inside slot should have:\n        // - scopeId from template context\n        // - slotted scopeId from slot owner\n        // - its own scopeId\n        `<span child2 parent child-s></span>` +\n        `</div>`,\n    )\n  })\n\n  // #1988\n  test('should inherit scopeId through nested HOCs with inheritAttrs: false', () => {\n    const withParentId = withScopeId('parent')\n    const App = {\n      __scopeId: 'parent',\n      render: withParentId(() => {\n        return h(Child)\n      }),\n    }\n\n    function Child() {\n      return h(Child2, { class: 'foo' })\n    }\n\n    function Child2() {\n      return h('div')\n    }\n    Child2.inheritAttrs = false\n\n    const root = nodeOps.createElement('div')\n    render(h(App), root)\n\n    expect(serializeInner(root)).toBe(`<div parent></div>`)\n  })\n\n  test('hoisted nodes', async () => {\n    pushScopeId('foobar')\n    const hoisted = h('div', 'hello')\n    popScopeId()\n\n    const App = {\n      __scopeId: 'foobar',\n      render: () => h('div', [hoisted]),\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(App), root)\n\n    expect(serializeInner(root)).toBe(\n      `<div foobar><div foobar>hello</div></div>`,\n    )\n  })\n})\n"
  },
  {
    "path": "packages/runtime-core/__tests__/vnode.spec.ts",
    "content": "import {\n  Comment,\n  Fragment,\n  Text,\n  type VNode,\n  cloneVNode,\n  createBlock,\n  createVNode,\n  isBlockTreeEnabled,\n  mergeProps,\n  normalizeVNode,\n  openBlock,\n  transformVNodeArgs,\n} from '../src/vnode'\nimport type { Data } from '../src/component'\nimport { PatchFlags, ShapeFlags } from '@vue/shared'\nimport { h, isReactive, reactive, ref, setBlockTracking, withCtx } from '../src'\nimport { createApp, nodeOps, serializeInner } from '@vue/runtime-test'\nimport { setCurrentRenderingInstance } from '../src/componentRenderContext'\n\ndescribe('vnode', () => {\n  test('create with just tag', () => {\n    const vnode = createVNode('p')\n    expect(vnode.type).toBe('p')\n    expect(vnode.props).toBe(null)\n  })\n\n  test('create with tag and props', () => {\n    const vnode = createVNode('p', {})\n    expect(vnode.type).toBe('p')\n    expect(vnode.props).toMatchObject({})\n  })\n\n  test('create with tag, props and children', () => {\n    const vnode = createVNode('p', {}, ['foo'])\n    expect(vnode.type).toBe('p')\n    expect(vnode.props).toMatchObject({})\n    expect(vnode.children).toMatchObject(['foo'])\n  })\n\n  test('create with 0 as props', () => {\n    const vnode = createVNode('p', null)\n    expect(vnode.type).toBe('p')\n    expect(vnode.props).toBe(null)\n  })\n\n  test('show warn when create with invalid type', () => {\n    const vnode = createVNode('')\n    expect('Invalid vnode type when creating vnode').toHaveBeenWarned()\n    expect(vnode.type).toBe(Comment)\n  })\n\n  test('create from an existing vnode', () => {\n    const vnode1 = createVNode('p', { id: 'foo' })\n    const vnode2 = createVNode(vnode1, { class: 'bar' }, 'baz')\n    expect(vnode2).toMatchObject({\n      type: 'p',\n      props: {\n        id: 'foo',\n        class: 'bar',\n      },\n      children: 'baz',\n      shapeFlag: ShapeFlags.ELEMENT | ShapeFlags.TEXT_CHILDREN,\n    })\n  })\n\n  test('create from an existing text vnode', () => {\n    const vnode1 = createVNode('div', null, 'text', PatchFlags.TEXT)\n    const vnode2 = createVNode(vnode1)\n    expect(vnode2).toMatchObject({\n      type: 'div',\n      patchFlag: PatchFlags.BAIL,\n      children: 'text',\n      shapeFlag: ShapeFlags.ELEMENT | ShapeFlags.TEXT_CHILDREN,\n    })\n  })\n\n  test('vnode keys', () => {\n    for (const key of ['', 'a', 0, 1, NaN]) {\n      expect(createVNode('div', { key }).key).toBe(key)\n    }\n    expect(createVNode('div').key).toBe(null)\n    expect(createVNode('div', { key: undefined }).key).toBe(null)\n    expect(`VNode created with invalid key (NaN)`).toHaveBeenWarned()\n  })\n\n  test('create with class component', () => {\n    class Component {\n      $props: any\n      static __vccOpts = { template: '<div />' }\n    }\n    const vnode = createVNode(Component)\n    expect(vnode.type).toEqual(Component.__vccOpts)\n  })\n\n  describe('class normalization', () => {\n    test('string', () => {\n      const vnode = createVNode('p', { class: 'foo baz' })\n      expect(vnode.props).toMatchObject({ class: 'foo baz' })\n    })\n\n    test('array<string>', () => {\n      const vnode = createVNode('p', { class: ['foo', 'baz'] })\n      expect(vnode.props).toMatchObject({ class: 'foo baz' })\n    })\n\n    test('array<object>', () => {\n      const vnode = createVNode('p', {\n        class: [{ foo: 'foo' }, { baz: 'baz' }],\n      })\n      expect(vnode.props).toMatchObject({ class: 'foo baz' })\n    })\n\n    test('object', () => {\n      const vnode = createVNode('p', { class: { foo: 'foo', baz: 'baz' } })\n      expect(vnode.props).toMatchObject({ class: 'foo baz' })\n    })\n  })\n\n  describe('style normalization', () => {\n    test('array', () => {\n      const vnode = createVNode('p', {\n        style: [{ foo: 'foo' }, { baz: 'baz' }],\n      })\n      expect(vnode.props).toMatchObject({ style: { foo: 'foo', baz: 'baz' } })\n    })\n\n    test('object', () => {\n      const vnode = createVNode('p', { style: { foo: 'foo', baz: 'baz' } })\n      expect(vnode.props).toMatchObject({ style: { foo: 'foo', baz: 'baz' } })\n    })\n  })\n\n  describe('children normalization', () => {\n    const nop = vi.fn\n\n    test('null', () => {\n      const vnode = createVNode('p', null, null)\n      expect(vnode.children).toBe(null)\n      expect(vnode.shapeFlag).toBe(ShapeFlags.ELEMENT)\n    })\n\n    test('array', () => {\n      const vnode = createVNode('p', null, ['foo'])\n      expect(vnode.children).toMatchObject(['foo'])\n      expect(vnode.shapeFlag).toBe(\n        ShapeFlags.ELEMENT | ShapeFlags.ARRAY_CHILDREN,\n      )\n    })\n\n    test('object', () => {\n      const vnode = createVNode({}, null, { foo: 'foo' })\n      expect(vnode.children).toMatchObject({ foo: 'foo' })\n      expect(vnode.shapeFlag).toBe(\n        ShapeFlags.STATEFUL_COMPONENT | ShapeFlags.SLOTS_CHILDREN,\n      )\n    })\n\n    test('function', () => {\n      const vnode = createVNode('p', null, nop)\n      expect(vnode.children).toMatchObject({ default: nop })\n      expect(vnode.shapeFlag).toBe(\n        ShapeFlags.ELEMENT | ShapeFlags.SLOTS_CHILDREN,\n      )\n    })\n\n    test('string', () => {\n      const vnode = createVNode('p', null, 'foo')\n      expect(vnode.children).toBe('foo')\n      expect(vnode.shapeFlag).toBe(\n        ShapeFlags.ELEMENT | ShapeFlags.TEXT_CHILDREN,\n      )\n    })\n\n    test('element with slots', () => {\n      const children = [createVNode('span', null, 'hello')]\n      const vnode = createVNode('div', null, {\n        default: () => children,\n      })\n\n      expect(vnode.children).toBe(children)\n      expect(vnode.shapeFlag).toBe(\n        ShapeFlags.ELEMENT | ShapeFlags.ARRAY_CHILDREN,\n      )\n    })\n  })\n\n  test('normalizeVNode', () => {\n    // null / undefined -> Comment\n    expect(normalizeVNode(null)).toMatchObject({ type: Comment })\n    expect(normalizeVNode(undefined)).toMatchObject({ type: Comment })\n\n    // boolean -> Comment\n    // this is for usage like `someBoolean && h('div')` and behavior consistency\n    // with 2.x (#574)\n    expect(normalizeVNode(true)).toMatchObject({ type: Comment })\n    expect(normalizeVNode(false)).toMatchObject({ type: Comment })\n\n    // array -> Fragment\n    expect(normalizeVNode(['foo'])).toMatchObject({ type: Fragment })\n\n    // VNode -> VNode\n    const vnode = createVNode('div')\n    expect(normalizeVNode(vnode)).toBe(vnode)\n\n    // mounted VNode -> cloned VNode\n    const mounted = createVNode('div')\n    mounted.el = {}\n    const normalized = normalizeVNode(mounted)\n    expect(normalized).not.toBe(mounted)\n    expect(normalized).toEqual(mounted)\n\n    // primitive types\n    expect(normalizeVNode('foo')).toMatchObject({ type: Text, children: `foo` })\n    expect(normalizeVNode(1)).toMatchObject({ type: Text, children: `1` })\n  })\n\n  test('type shapeFlag inference', () => {\n    expect(createVNode('div').shapeFlag).toBe(ShapeFlags.ELEMENT)\n    expect(createVNode({}).shapeFlag).toBe(ShapeFlags.STATEFUL_COMPONENT)\n    expect(createVNode(() => {}).shapeFlag).toBe(\n      ShapeFlags.FUNCTIONAL_COMPONENT,\n    )\n    expect(createVNode(Text).shapeFlag).toBe(0)\n  })\n\n  test('cloneVNode', () => {\n    const node1 = createVNode('div', { foo: 1 }, null)\n    expect(cloneVNode(node1)).toEqual(node1)\n\n    const node2 = createVNode({}, null, [node1])\n    const cloned2 = cloneVNode(node2)\n    expect(cloned2).toEqual(node2)\n    expect(cloneVNode(node2)).toEqual(cloned2)\n  })\n\n  test('cloneVNode key normalization', () => {\n    // #1041 should use resolved key/ref\n    expect(cloneVNode(createVNode('div', { key: 1 })).key).toBe(1)\n    expect(cloneVNode(createVNode('div', { key: 1 }), { key: 2 }).key).toBe(2)\n    expect(cloneVNode(createVNode('div'), { key: 2 }).key).toBe(2)\n  })\n\n  // ref normalizes to [currentRenderingInstance, ref]\n  test('cloneVNode ref normalization', () => {\n    const mockInstance1 = { type: {} } as any\n    const mockInstance2 = { type: {} } as any\n\n    setCurrentRenderingInstance(mockInstance1)\n    const original = createVNode('div', { ref: 'foo' })\n    expect(original.ref).toMatchObject({\n      i: mockInstance1,\n      r: 'foo',\n      f: false,\n    })\n\n    // clone and preserve original ref\n    const cloned1 = cloneVNode(original)\n    expect(cloned1.ref).toMatchObject({ i: mockInstance1, r: 'foo', f: false })\n\n    // cloning with new ref, but with same context instance\n    const cloned2 = cloneVNode(original, { ref: 'bar' })\n    expect(cloned2.ref).toMatchObject({ i: mockInstance1, r: 'bar', f: false })\n\n    // cloning and adding ref to original that has no ref\n    const original2 = createVNode('div')\n    const cloned3 = cloneVNode(original2, { ref: 'bar' })\n    expect(cloned3.ref).toMatchObject({ i: mockInstance1, r: 'bar', f: false })\n\n    // cloning with different context instance\n    setCurrentRenderingInstance(mockInstance2)\n\n    // clone and preserve original ref\n    const cloned4 = cloneVNode(original)\n    // #1311 should preserve original context instance!\n    expect(cloned4.ref).toMatchObject({ i: mockInstance1, r: 'foo', f: false })\n\n    // cloning with new ref, but with same context instance\n    const cloned5 = cloneVNode(original, { ref: 'bar' })\n    // new ref should use current context instance and overwrite original\n    expect(cloned5.ref).toMatchObject({ i: mockInstance2, r: 'bar', f: false })\n\n    // cloning and adding ref to original that has no ref\n    const cloned6 = cloneVNode(original2, { ref: 'bar' })\n    expect(cloned6.ref).toMatchObject({ i: mockInstance2, r: 'bar', f: false })\n\n    const original3 = createVNode('div', { ref: 'foo', ref_for: true })\n    expect(original3.ref).toMatchObject({\n      i: mockInstance2,\n      r: 'foo',\n      f: true,\n    })\n    const cloned7 = cloneVNode(original3, { ref: 'bar', ref_for: true })\n    expect(cloned7.ref).toMatchObject({ i: mockInstance2, r: 'bar', f: true })\n\n    const r = ref()\n    const original4 = createVNode('div', { ref: r, ref_key: 'foo' })\n    expect(original4.ref).toMatchObject({\n      i: mockInstance2,\n      r,\n      k: 'foo',\n    })\n    const cloned8 = cloneVNode(original4)\n    expect(cloned8.ref).toMatchObject({ i: mockInstance2, r, k: 'foo' })\n\n    // @ts-expect-error #8230\n    const original5 = createVNode('div', { ref: 111, ref_key: 'foo' })\n    expect(original5.ref).toMatchObject({\n      i: mockInstance2,\n      r: '111',\n      k: 'foo',\n    })\n    const cloned9 = cloneVNode(original5)\n    expect(cloned9.ref).toMatchObject({ i: mockInstance2, r: '111', k: 'foo' })\n\n    setCurrentRenderingInstance(null)\n  })\n\n  test('cloneVNode ref merging', () => {\n    const mockInstance1 = { type: {} } as any\n    const mockInstance2 = { type: {} } as any\n\n    setCurrentRenderingInstance(mockInstance1)\n    const original = createVNode('div', { ref: 'foo' })\n    expect(original.ref).toMatchObject({ i: mockInstance1, r: 'foo', f: false })\n\n    // clone and preserve original ref\n    setCurrentRenderingInstance(mockInstance2)\n    const cloned1 = cloneVNode(original, { ref: 'bar' }, true)\n    expect(cloned1.ref).toMatchObject([\n      { i: mockInstance1, r: 'foo', f: false },\n      { i: mockInstance2, r: 'bar', f: false },\n    ])\n\n    setCurrentRenderingInstance(null)\n  })\n\n  test('cloneVNode class normalization', () => {\n    const vnode = createVNode('div')\n    const expectedProps = {\n      class: 'a b',\n    }\n    expect(cloneVNode(vnode, { class: 'a b' }).props).toMatchObject(\n      expectedProps,\n    )\n    expect(cloneVNode(vnode, { class: ['a', 'b'] }).props).toMatchObject(\n      expectedProps,\n    )\n    expect(\n      cloneVNode(vnode, { class: { a: true, b: true } }).props,\n    ).toMatchObject(expectedProps)\n    expect(\n      cloneVNode(vnode, { class: [{ a: true, b: true }] }).props,\n    ).toMatchObject(expectedProps)\n  })\n\n  test('cloneVNode style normalization', () => {\n    const vnode = createVNode('div')\n    const expectedProps = {\n      style: {\n        color: 'blue',\n        width: '300px',\n      },\n    }\n    expect(\n      cloneVNode(vnode, { style: 'color: blue; width: 300px;' }).props,\n    ).toMatchObject(expectedProps)\n    expect(\n      cloneVNode(vnode, {\n        style: {\n          color: 'blue',\n          width: '300px',\n        },\n      }).props,\n    ).toMatchObject(expectedProps)\n    expect(\n      cloneVNode(vnode, {\n        style: [\n          {\n            color: 'blue',\n            width: '300px',\n          },\n        ],\n      }).props,\n    ).toMatchObject(expectedProps)\n  })\n\n  describe('mergeProps', () => {\n    test('class', () => {\n      let props1: Data = { class: { c: true } }\n      let props2: Data = { class: ['cc'] }\n      let props3: Data = { class: [{ ccc: true }] }\n      let props4: Data = { class: { cccc: true } }\n      expect(mergeProps(props1, props2, props3, props4)).toMatchObject({\n        class: 'c cc ccc cccc',\n      })\n    })\n\n    test('style', () => {\n      let props1: Data = {\n        style: [\n          {\n            color: 'red',\n            fontSize: 10,\n          },\n        ],\n      }\n      let props2: Data = {\n        style: [\n          {\n            color: 'blue',\n            width: '200px',\n          },\n          {\n            width: '300px',\n            height: '300px',\n            fontSize: 30,\n          },\n        ],\n      }\n      expect(mergeProps(props1, props2)).toMatchObject({\n        style: {\n          color: 'blue',\n          width: '300px',\n          height: '300px',\n          fontSize: 30,\n        },\n      })\n    })\n\n    test('style w/ strings', () => {\n      let props1: Data = {\n        style: 'width:100px;right:10;top:10',\n      }\n      let props2: Data = {\n        style: [\n          {\n            color: 'blue',\n            width: '200px',\n          },\n          {\n            width: '300px',\n            height: '300px',\n            fontSize: 30,\n          },\n        ],\n      }\n      expect(mergeProps(props1, props2)).toMatchObject({\n        style: {\n          color: 'blue',\n          width: '300px',\n          height: '300px',\n          fontSize: 30,\n          right: '10',\n          top: '10',\n        },\n      })\n    })\n\n    test('handlers', () => {\n      let clickHandler1 = function () {}\n      let clickHandler2 = function () {}\n      let focusHandler2 = function () {}\n\n      let props1: Data = { onClick: clickHandler1 }\n      let props2: Data = { onClick: clickHandler2, onFocus: focusHandler2 }\n      expect(mergeProps(props1, props2)).toMatchObject({\n        onClick: [clickHandler1, clickHandler2],\n        onFocus: focusHandler2,\n      })\n      let props3: Data = { onClick: undefined }\n      expect(mergeProps(props1, props3)).toMatchObject({\n        onClick: clickHandler1,\n      })\n    })\n\n    test('default', () => {\n      let props1: Data = { foo: 'c' }\n      let props2: Data = { foo: {}, bar: ['cc'] }\n      let props3: Data = { baz: { ccc: true } }\n      expect(mergeProps(props1, props2, props3)).toMatchObject({\n        foo: {},\n        bar: ['cc'],\n        baz: { ccc: true },\n      })\n    })\n  })\n\n  describe('dynamic children', () => {\n    test('with patchFlags', () => {\n      const hoist = createVNode('div')\n      let vnode1\n      const vnode =\n        (openBlock(),\n        createBlock('div', null, [\n          hoist,\n          (vnode1 = createVNode('div', null, 'text', PatchFlags.TEXT)),\n        ]))\n      expect(vnode.dynamicChildren).toStrictEqual([vnode1])\n    })\n\n    test('should not track vnodes with only NEED_HYDRATION flag', () => {\n      const hoist = createVNode('div')\n      const vnode =\n        (openBlock(),\n        createBlock('div', null, [\n          hoist,\n          createVNode('div', null, 'text', PatchFlags.NEED_HYDRATION),\n        ]))\n      expect(vnode.dynamicChildren).toStrictEqual([])\n    })\n\n    test('many times call openBlock', () => {\n      const hoist = createVNode('div')\n      let vnode1, vnode2, vnode3\n      const vnode =\n        (openBlock(),\n        createBlock('div', null, [\n          hoist,\n          (vnode1 = createVNode('div', null, 'text', PatchFlags.TEXT)),\n          (vnode2 =\n            (openBlock(),\n            createBlock('div', null, [\n              hoist,\n              (vnode3 = createVNode('div', null, 'text', PatchFlags.TEXT)),\n            ]))),\n        ]))\n      expect(vnode.dynamicChildren).toStrictEqual([vnode1, vnode2])\n      expect(vnode2.dynamicChildren).toStrictEqual([vnode3])\n    })\n\n    test('with stateful component', () => {\n      const hoist = createVNode('div')\n      let vnode1\n      const vnode =\n        (openBlock(),\n        createBlock('div', null, [\n          hoist,\n          (vnode1 = createVNode({}, null, 'text')),\n        ]))\n      expect(vnode.dynamicChildren).toStrictEqual([vnode1])\n    })\n\n    test('with functional component', () => {\n      const hoist = createVNode('div')\n      let vnode1\n      const vnode =\n        (openBlock(),\n        createBlock('div', null, [\n          hoist,\n          (vnode1 = createVNode(() => {}, null, 'text')),\n        ]))\n      expect(vnode.dynamicChildren).toStrictEqual([vnode1])\n    })\n\n    // #1039\n    // <component :is=\"foo\">{{ bar }}</component>\n    // - content is compiled as slot\n    // - dynamic component resolves to plain element, but as a block\n    // - block creation disables its own tracking, accidentally causing the\n    //   slot content (called during the block node creation) to be missed\n    test('element block should track normalized slot children', () => {\n      const hoist = createVNode('div')\n      let vnode1: any\n      const vnode =\n        (openBlock(),\n        createBlock('div', null, {\n          default: () => {\n            return [\n              hoist,\n              (vnode1 = createVNode('div', null, 'text', PatchFlags.TEXT)),\n            ]\n          },\n        }))\n      expect(vnode.dynamicChildren).toStrictEqual([vnode1])\n    })\n\n    test('openBlock w/ disableTracking: true', () => {\n      const hoist = createVNode('div')\n      let vnode1\n      const vnode =\n        (openBlock(),\n        createBlock('div', null, [\n          // a v-for fragment block generated by the compiler\n          // disables tracking because it always diffs its\n          // children.\n          (vnode1 =\n            (openBlock(true),\n            createBlock(Fragment, null, [\n              hoist,\n              /*vnode2*/ createVNode(() => {}, null, 'text'),\n            ]))),\n        ]))\n      expect(vnode.dynamicChildren).toStrictEqual([vnode1])\n      expect(vnode1.dynamicChildren).toStrictEqual([])\n    })\n\n    test('openBlock without disableTracking: true', () => {\n      const hoist = createVNode('div')\n      let vnode1, vnode2\n      const vnode =\n        (openBlock(),\n        createBlock('div', null, [\n          (vnode1 =\n            (openBlock(),\n            createBlock(Fragment, null, [\n              hoist,\n              (vnode2 = createVNode(() => {}, null, 'text')),\n            ]))),\n        ]))\n      expect(vnode.dynamicChildren).toStrictEqual([vnode1])\n      expect(vnode1.dynamicChildren).toStrictEqual([vnode2])\n    })\n\n    test('should not track openBlock() when tracking is disabled', () => {\n      let vnode1\n      const vnode =\n        (openBlock(),\n        createBlock('div', null, [\n          setBlockTracking(-1, true),\n          (vnode1 = (openBlock(), createBlock('div'))),\n          setBlockTracking(1),\n          vnode1,\n        ]))\n      const expected: VNode['dynamicChildren'] = []\n      expected.hasOnce = true\n      expect(vnode.dynamicChildren).toStrictEqual(expected)\n    })\n    // #5657\n    test('error of slot function execution should not affect block tracking', () => {\n      expect(isBlockTreeEnabled).toStrictEqual(1)\n      const slotFn = withCtx(\n        () => {\n          throw new Error('slot execution error')\n        },\n        { type: {}, appContext: {} } as any,\n      )\n      const Parent = {\n        setup(_: any, { slots }: any) {\n          return () => {\n            try {\n              slots.default()\n            } catch (e) {}\n          }\n        },\n      }\n      const vnode =\n        (openBlock(), createBlock(Parent, null, { default: slotFn }))\n      createApp(vnode).mount(nodeOps.createElement('div'))\n      expect(isBlockTreeEnabled).toStrictEqual(1)\n    })\n  })\n\n  describe('transformVNodeArgs', () => {\n    afterEach(() => {\n      // reset\n      transformVNodeArgs()\n    })\n\n    test('no-op pass through', () => {\n      transformVNodeArgs(args => args)\n      const vnode = createVNode('div', { id: 'foo' }, 'hello')\n      expect(vnode).toMatchObject({\n        type: 'div',\n        props: { id: 'foo' },\n        children: 'hello',\n        shapeFlag: ShapeFlags.ELEMENT | ShapeFlags.TEXT_CHILDREN,\n      })\n    })\n\n    test('direct override', () => {\n      transformVNodeArgs(() => ['div', { id: 'foo' }, 'hello'])\n      const vnode = createVNode('p')\n      expect(vnode).toMatchObject({\n        type: 'div',\n        props: { id: 'foo' },\n        children: 'hello',\n        shapeFlag: ShapeFlags.ELEMENT | ShapeFlags.TEXT_CHILDREN,\n      })\n    })\n\n    test('receive component instance as 2nd arg', () => {\n      transformVNodeArgs((args, instance) => {\n        if (instance) {\n          return ['h1', null, instance.type.name]\n        } else {\n          return args\n        }\n      })\n      const App = {\n        // this will be the name of the component in the h1\n        name: 'Root Component',\n        render() {\n          return h('p') // this will be overwritten by the transform\n        },\n      }\n      const root = nodeOps.createElement('div')\n      createApp(App).mount(root)\n      expect(serializeInner(root)).toBe('<h1>Root Component</h1>')\n    })\n\n    test('should not be observable', () => {\n      const a = createVNode('div')\n      const b = reactive(a)\n      expect(b).toBe(a)\n      expect(isReactive(b)).toBe(false)\n    })\n  })\n})\n"
  },
  {
    "path": "packages/runtime-core/__tests__/vnodeHooks.spec.ts",
    "content": "import {\n  type TestElement,\n  TestNodeTypes,\n  type VNode,\n  type VNodeProps,\n  h,\n  nodeOps,\n  render,\n} from '@vue/runtime-test'\n\ndescribe('renderer: vnode hooks', () => {\n  function assertHooks(hooks: VNodeProps, vnode1: VNode, vnode2: VNode) {\n    const root = nodeOps.createElement('div')\n    render(vnode1, root)\n    expect(hooks.onVnodeBeforeMount).toHaveBeenCalledWith(vnode1, null)\n    expect(hooks.onVnodeMounted).toHaveBeenCalledWith(vnode1, null)\n    expect(hooks.onVnodeBeforeUpdate).not.toHaveBeenCalled()\n    expect(hooks.onVnodeUpdated).not.toHaveBeenCalled()\n    expect(hooks.onVnodeBeforeUnmount).not.toHaveBeenCalled()\n    expect(hooks.onVnodeUnmounted).not.toHaveBeenCalled()\n\n    // update\n    render(vnode2, root)\n    expect(hooks.onVnodeBeforeMount).toHaveBeenCalledTimes(1)\n    expect(hooks.onVnodeMounted).toHaveBeenCalledTimes(1)\n    expect(hooks.onVnodeBeforeUpdate).toHaveBeenCalledWith(vnode2, vnode1)\n    expect(hooks.onVnodeUpdated).toHaveBeenCalledWith(vnode2, vnode1)\n    expect(hooks.onVnodeBeforeUnmount).not.toHaveBeenCalled()\n    expect(hooks.onVnodeUnmounted).not.toHaveBeenCalled()\n\n    // unmount\n    render(null, root)\n    expect(hooks.onVnodeBeforeMount).toHaveBeenCalledTimes(1)\n    expect(hooks.onVnodeMounted).toHaveBeenCalledTimes(1)\n    expect(hooks.onVnodeBeforeUpdate).toHaveBeenCalledTimes(1)\n    expect(hooks.onVnodeUpdated).toHaveBeenCalledTimes(1)\n    expect(hooks.onVnodeBeforeUnmount).toHaveBeenCalledWith(vnode2, null)\n    expect(hooks.onVnodeUnmounted).toHaveBeenCalledWith(vnode2, null)\n  }\n\n  test('should work on element', () => {\n    const hooks: VNodeProps = {\n      onVnodeBeforeMount: vi.fn<(vnode: VNode) => void>(),\n      onVnodeMounted: vi.fn<(vnode: VNode) => void>(),\n      onVnodeBeforeUpdate: vi.fn(vnode => {\n        expect((vnode.el as TestElement).children[0]).toMatchObject({\n          type: TestNodeTypes.TEXT,\n          text: 'foo',\n        })\n      }),\n      onVnodeUpdated: vi.fn(vnode => {\n        expect((vnode.el as TestElement).children[0]).toMatchObject({\n          type: TestNodeTypes.TEXT,\n          text: 'bar',\n        })\n      }),\n      onVnodeBeforeUnmount: vi.fn<(vnode: VNode) => void>(),\n      onVnodeUnmounted: vi.fn<(vnode: VNode) => void>(),\n    }\n\n    assertHooks(hooks, h('div', hooks, 'foo'), h('div', hooks, 'bar'))\n  })\n\n  test('should work on component', () => {\n    const Comp = (props: { msg: string }) => props.msg\n\n    const hooks: VNodeProps = {\n      onVnodeBeforeMount: vi.fn<(vnode: VNode) => void>(),\n      onVnodeMounted: vi.fn<(vnode: VNode) => void>(),\n      onVnodeBeforeUpdate: vi.fn(vnode => {\n        expect(vnode.el as TestElement).toMatchObject({\n          type: TestNodeTypes.TEXT,\n          text: 'foo',\n        })\n      }),\n      onVnodeUpdated: vi.fn(vnode => {\n        expect(vnode.el as TestElement).toMatchObject({\n          type: TestNodeTypes.TEXT,\n          text: 'bar',\n        })\n      }),\n      onVnodeBeforeUnmount: vi.fn<(vnode: VNode) => void>(),\n      onVnodeUnmounted: vi.fn<(vnode: VNode) => void>(),\n    }\n\n    assertHooks(\n      hooks,\n      h(Comp, {\n        ...hooks,\n        msg: 'foo',\n      }),\n      h(Comp, {\n        ...hooks,\n        msg: 'bar',\n      }),\n    )\n  })\n})\n"
  },
  {
    "path": "packages/runtime-core/index.js",
    "content": "'use strict'\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./dist/runtime-core.cjs.prod.js')\n} else {\n  module.exports = require('./dist/runtime-core.cjs.js')\n}\n"
  },
  {
    "path": "packages/runtime-core/package.json",
    "content": "{\n  \"name\": \"@vue/runtime-core\",\n  \"version\": \"3.5.30\",\n  \"description\": \"@vue/runtime-core\",\n  \"main\": \"index.js\",\n  \"module\": \"dist/runtime-core.esm-bundler.js\",\n  \"types\": \"dist/runtime-core.d.ts\",\n  \"files\": [\n    \"index.js\",\n    \"dist\"\n  ],\n  \"exports\": {\n    \".\": {\n      \"types\": \"./dist/runtime-core.d.ts\",\n      \"node\": {\n        \"production\": \"./dist/runtime-core.cjs.prod.js\",\n        \"development\": \"./dist/runtime-core.cjs.js\",\n        \"default\": \"./index.js\"\n      },\n      \"module\": \"./dist/runtime-core.esm-bundler.js\",\n      \"import\": \"./dist/runtime-core.esm-bundler.js\",\n      \"require\": \"./index.js\"\n    },\n    \"./*\": \"./*\"\n  },\n  \"buildOptions\": {\n    \"name\": \"VueRuntimeCore\",\n    \"formats\": [\n      \"esm-bundler\",\n      \"cjs\"\n    ]\n  },\n  \"sideEffects\": false,\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/vuejs/core.git\",\n    \"directory\": \"packages/runtime-core\"\n  },\n  \"keywords\": [\n    \"vue\"\n  ],\n  \"author\": \"Evan You\",\n  \"license\": \"MIT\",\n  \"bugs\": {\n    \"url\": \"https://github.com/vuejs/core/issues\"\n  },\n  \"homepage\": \"https://github.com/vuejs/core/tree/main/packages/runtime-core#readme\",\n  \"dependencies\": {\n    \"@vue/shared\": \"workspace:*\",\n    \"@vue/reactivity\": \"workspace:*\"\n  }\n}\n"
  },
  {
    "path": "packages/runtime-core/src/apiAsyncComponent.ts",
    "content": "import {\n  type Component,\n  type ComponentInternalInstance,\n  type ComponentOptions,\n  type ConcreteComponent,\n  currentInstance,\n  getComponentName,\n  isInSSRComponentSetup,\n} from './component'\nimport { isFunction, isObject } from '@vue/shared'\nimport type { ComponentPublicInstance } from './componentPublicInstance'\nimport { type VNode, createVNode } from './vnode'\nimport { defineComponent } from './apiDefineComponent'\nimport { warn } from './warning'\nimport { ref } from '@vue/reactivity'\nimport { ErrorCodes, handleError } from './errorHandling'\nimport { isKeepAlive } from './components/KeepAlive'\nimport { markAsyncBoundary } from './helpers/useId'\nimport { type HydrationStrategy, forEachElement } from './hydrationStrategies'\n\nexport type AsyncComponentResolveResult<T = Component> = T | { default: T } // es modules\n\nexport type AsyncComponentLoader<T = any> = () => Promise<\n  AsyncComponentResolveResult<T>\n>\n\nexport interface AsyncComponentOptions<T = any> {\n  loader: AsyncComponentLoader<T>\n  loadingComponent?: Component\n  errorComponent?: Component\n  delay?: number\n  timeout?: number\n  suspensible?: boolean\n  hydrate?: HydrationStrategy\n  onError?: (\n    error: Error,\n    retry: () => void,\n    fail: () => void,\n    attempts: number,\n  ) => any\n}\n\nexport const isAsyncWrapper = (i: ComponentInternalInstance | VNode): boolean =>\n  !!(i.type as ComponentOptions).__asyncLoader\n\n/*@__NO_SIDE_EFFECTS__*/\nexport function defineAsyncComponent<\n  T extends Component = { new (): ComponentPublicInstance },\n>(source: AsyncComponentLoader<T> | AsyncComponentOptions<T>): T {\n  if (isFunction(source)) {\n    source = { loader: source }\n  }\n\n  const {\n    loader,\n    loadingComponent,\n    errorComponent,\n    delay = 200,\n    hydrate: hydrateStrategy,\n    timeout, // undefined = never times out\n    suspensible = true,\n    onError: userOnError,\n  } = source\n\n  let pendingRequest: Promise<ConcreteComponent> | null = null\n  let resolvedComp: ConcreteComponent | undefined\n\n  let retries = 0\n  const retry = () => {\n    retries++\n    pendingRequest = null\n    return load()\n  }\n\n  const load = (): Promise<ConcreteComponent> => {\n    let thisRequest: Promise<ConcreteComponent>\n    return (\n      pendingRequest ||\n      (thisRequest = pendingRequest =\n        loader()\n          .catch(err => {\n            err = err instanceof Error ? err : new Error(String(err))\n            if (userOnError) {\n              return new Promise((resolve, reject) => {\n                const userRetry = () => resolve(retry())\n                const userFail = () => reject(err)\n                userOnError(err, userRetry, userFail, retries + 1)\n              })\n            } else {\n              throw err\n            }\n          })\n          .then((comp: any) => {\n            if (thisRequest !== pendingRequest && pendingRequest) {\n              return pendingRequest\n            }\n            if (__DEV__ && !comp) {\n              warn(\n                `Async component loader resolved to undefined. ` +\n                  `If you are using retry(), make sure to return its return value.`,\n              )\n            }\n            // interop module default\n            if (\n              comp &&\n              (comp.__esModule || comp[Symbol.toStringTag] === 'Module')\n            ) {\n              comp = comp.default\n            }\n            if (__DEV__ && comp && !isObject(comp) && !isFunction(comp)) {\n              throw new Error(`Invalid async component load result: ${comp}`)\n            }\n            resolvedComp = comp\n            return comp\n          }))\n    )\n  }\n\n  return defineComponent({\n    name: 'AsyncComponentWrapper',\n\n    __asyncLoader: load,\n\n    __asyncHydrate(el, instance, hydrate) {\n      let patched = false\n      ;(instance.bu || (instance.bu = [])).push(() => (patched = true))\n      const performHydrate = () => {\n        // skip hydration if the component has been patched\n        if (patched) {\n          if (__DEV__) {\n            warn(\n              `Skipping lazy hydration for component '${getComponentName(resolvedComp!) || resolvedComp!.__file}': ` +\n                `it was updated before lazy hydration performed.`,\n            )\n          }\n          return\n        }\n        hydrate()\n      }\n      const doHydrate = hydrateStrategy\n        ? () => {\n            const teardown = hydrateStrategy(performHydrate, cb =>\n              forEachElement(el, cb),\n            )\n            if (teardown) {\n              ;(instance.bum || (instance.bum = [])).push(teardown)\n            }\n          }\n        : performHydrate\n      if (resolvedComp) {\n        doHydrate()\n      } else {\n        load().then(() => !instance.isUnmounted && doHydrate())\n      }\n    },\n\n    get __asyncResolved() {\n      return resolvedComp\n    },\n\n    setup() {\n      const instance = currentInstance!\n      markAsyncBoundary(instance)\n\n      // already resolved\n      if (resolvedComp) {\n        return () => createInnerComp(resolvedComp!, instance)\n      }\n\n      const onError = (err: Error) => {\n        pendingRequest = null\n        handleError(\n          err,\n          instance,\n          ErrorCodes.ASYNC_COMPONENT_LOADER,\n          !errorComponent /* do not throw in dev if user provided error component */,\n        )\n      }\n\n      // suspense-controlled or SSR.\n      if (\n        (__FEATURE_SUSPENSE__ && suspensible && instance.suspense) ||\n        (__SSR__ && isInSSRComponentSetup)\n      ) {\n        return load()\n          .then(comp => {\n            return () => createInnerComp(comp, instance)\n          })\n          .catch(err => {\n            onError(err)\n            return () =>\n              errorComponent\n                ? createVNode(errorComponent as ConcreteComponent, {\n                    error: err,\n                  })\n                : null\n          })\n      }\n\n      const loaded = ref(false)\n      const error = ref()\n      const delayed = ref(!!delay)\n\n      if (delay) {\n        setTimeout(() => {\n          delayed.value = false\n        }, delay)\n      }\n\n      if (timeout != null) {\n        setTimeout(() => {\n          if (!loaded.value && !error.value) {\n            const err = new Error(\n              `Async component timed out after ${timeout}ms.`,\n            )\n            onError(err)\n            error.value = err\n          }\n        }, timeout)\n      }\n\n      load()\n        .then(() => {\n          loaded.value = true\n          if (instance.parent && isKeepAlive(instance.parent.vnode)) {\n            // parent is keep-alive, force update so the loaded component's\n            // name is taken into account\n            instance.parent.update()\n          }\n        })\n        .catch(err => {\n          onError(err)\n          error.value = err\n        })\n\n      return () => {\n        if (loaded.value && resolvedComp) {\n          return createInnerComp(resolvedComp, instance)\n        } else if (error.value && errorComponent) {\n          return createVNode(errorComponent, {\n            error: error.value,\n          })\n        } else if (loadingComponent && !delayed.value) {\n          return createInnerComp(\n            loadingComponent as ConcreteComponent,\n            instance,\n          )\n        }\n      }\n    },\n  }) as T\n}\n\nfunction createInnerComp(\n  comp: ConcreteComponent,\n  parent: ComponentInternalInstance,\n) {\n  const { ref, props, children, ce } = parent.vnode\n  const vnode = createVNode(comp, props, children)\n  // ensure inner component inherits the async wrapper's ref owner\n  vnode.ref = ref\n  // pass the custom element callback on to the inner comp\n  // and remove it from the async wrapper\n  vnode.ce = ce\n  delete parent.vnode.ce\n\n  return vnode\n}\n"
  },
  {
    "path": "packages/runtime-core/src/apiComputed.ts",
    "content": "import { type ComputedRefImpl, computed as _computed } from '@vue/reactivity'\nimport { getCurrentInstance, isInSSRComponentSetup } from './component'\n\nexport const computed: typeof _computed = (\n  getterOrOptions: any,\n  debugOptions?: any,\n) => {\n  // @ts-expect-error\n  const c = _computed(getterOrOptions, debugOptions, isInSSRComponentSetup)\n  if (__DEV__) {\n    const i = getCurrentInstance()\n    if (i && i.appContext.config.warnRecursiveComputed) {\n      ;(c as unknown as ComputedRefImpl<any>)._warnRecursive = true\n    }\n  }\n  return c as any\n}\n"
  },
  {
    "path": "packages/runtime-core/src/apiCreateApp.ts",
    "content": "import {\n  type Component,\n  type ComponentInternalInstance,\n  type ConcreteComponent,\n  type Data,\n  getComponentPublicInstance,\n  validateComponentName,\n} from './component'\nimport type {\n  ComponentOptions,\n  MergedComponentOptions,\n  RuntimeCompilerOptions,\n} from './componentOptions'\nimport type {\n  ComponentCustomProperties,\n  ComponentPublicInstance,\n} from './componentPublicInstance'\nimport { type Directive, validateDirectiveName } from './directives'\nimport type { ElementNamespace, RootRenderFunction } from './renderer'\nimport type { InjectionKey } from './apiInject'\nimport { warn } from './warning'\nimport { type VNode, cloneVNode, createVNode } from './vnode'\nimport type { RootHydrateFunction } from './hydration'\nimport { devtoolsInitApp, devtoolsUnmountApp } from './devtools'\nimport { NO, extend, hasOwn, isFunction, isObject } from '@vue/shared'\nimport { version } from '.'\nimport { installAppCompatProperties } from './compat/global'\nimport type { NormalizedPropsOptions } from './componentProps'\nimport type { ObjectEmitsOptions } from './componentEmits'\nimport { ErrorCodes, callWithAsyncErrorHandling } from './errorHandling'\nimport type { DefineComponent } from './apiDefineComponent'\n\nexport interface App<HostElement = any> {\n  version: string\n  config: AppConfig\n\n  use<Options extends unknown[]>(\n    plugin: Plugin<Options>,\n    ...options: NoInfer<Options>\n  ): this\n  use<Options>(plugin: Plugin<Options>, options: NoInfer<Options>): this\n\n  mixin(mixin: ComponentOptions): this\n  component(name: string): Component | undefined\n  component<T extends Component | DefineComponent>(\n    name: string,\n    component: T,\n  ): this\n  directive<\n    HostElement = any,\n    Value = any,\n    Modifiers extends string = string,\n    Arg = any,\n  >(\n    name: string,\n  ): Directive<HostElement, Value, Modifiers, Arg> | undefined\n  directive<\n    HostElement = any,\n    Value = any,\n    Modifiers extends string = string,\n    Arg = any,\n  >(\n    name: string,\n    directive: Directive<HostElement, Value, Modifiers, Arg>,\n  ): this\n  mount(\n    rootContainer: HostElement | string,\n    /**\n     * @internal\n     */\n    isHydrate?: boolean,\n    /**\n     * @internal\n     */\n    namespace?: boolean | ElementNamespace,\n    /**\n     * @internal\n     */\n    vnode?: VNode,\n  ): ComponentPublicInstance\n  unmount(): void\n  onUnmount(cb: () => void): void\n  provide<T, K = InjectionKey<T> | string | number>(\n    key: K,\n    value: K extends InjectionKey<infer V> ? V : T,\n  ): this\n\n  /**\n   * Runs a function with the app as active instance. This allows using of `inject()` within the function to get access\n   * to variables provided via `app.provide()`.\n   *\n   * @param fn - function to run with the app as active instance\n   */\n  runWithContext<T>(fn: () => T): T\n\n  // internal, but we need to expose these for the server-renderer and devtools\n  _uid: number\n  _component: ConcreteComponent\n  _props: Data | null\n  _container: HostElement | null\n  _context: AppContext\n  _instance: ComponentInternalInstance | null\n\n  /**\n   * @internal custom element vnode\n   */\n  _ceVNode?: VNode\n\n  /**\n   * v2 compat only\n   */\n  filter?(name: string): Function | undefined\n  filter?(name: string, filter: Function): this\n\n  /**\n   * @internal v3 compat only\n   */\n  _createRoot?(options: ComponentOptions): ComponentPublicInstance\n}\n\nexport type OptionMergeFunction = (to: unknown, from: unknown) => any\n\nexport interface AppConfig {\n  // @private\n  readonly isNativeTag: (tag: string) => boolean\n\n  performance: boolean\n  optionMergeStrategies: Record<string, OptionMergeFunction>\n  globalProperties: ComponentCustomProperties & Record<string, any>\n  errorHandler?: (\n    err: unknown,\n    instance: ComponentPublicInstance | null,\n    info: string,\n  ) => void\n  warnHandler?: (\n    msg: string,\n    instance: ComponentPublicInstance | null,\n    trace: string,\n  ) => void\n\n  /**\n   * Options to pass to `@vue/compiler-dom`.\n   * Only supported in runtime compiler build.\n   */\n  compilerOptions: RuntimeCompilerOptions\n\n  /**\n   * @deprecated use config.compilerOptions.isCustomElement\n   */\n  isCustomElement?: (tag: string) => boolean\n\n  /**\n   * TODO document for 3.5\n   * Enable warnings for computed getters that recursively trigger itself.\n   */\n  warnRecursiveComputed?: boolean\n\n  /**\n   * Whether to throw unhandled errors in production.\n   * Default is `false` to avoid crashing on any error (and only logs it)\n   * But in some cases, e.g. SSR, throwing might be more desirable.\n   */\n  throwUnhandledErrorInProduction?: boolean\n\n  /**\n   * Prefix for all useId() calls within this app\n   */\n  idPrefix?: string\n}\n\nexport interface AppContext {\n  app: App // for devtools\n  config: AppConfig\n  mixins: ComponentOptions[]\n  components: Record<string, Component>\n  directives: Record<string, Directive>\n  provides: Record<string | symbol, any>\n\n  /**\n   * Cache for merged/normalized component options\n   * Each app instance has its own cache because app-level global mixins and\n   * optionMergeStrategies can affect merge behavior.\n   * @internal\n   */\n  optionsCache: WeakMap<ComponentOptions, MergedComponentOptions>\n  /**\n   * Cache for normalized props options\n   * @internal\n   */\n  propsCache: WeakMap<ConcreteComponent, NormalizedPropsOptions>\n  /**\n   * Cache for normalized emits options\n   * @internal\n   */\n  emitsCache: WeakMap<ConcreteComponent, ObjectEmitsOptions | null>\n  /**\n   * HMR only\n   * @internal\n   */\n  reload?: () => void\n  /**\n   * v2 compat only\n   * @internal\n   */\n  filters?: Record<string, Function>\n}\n\ntype PluginInstallFunction<Options = any[]> = Options extends unknown[]\n  ? (app: App, ...options: Options) => any\n  : (app: App, options: Options) => any\n\nexport type ObjectPlugin<Options = any[]> = {\n  install: PluginInstallFunction<Options>\n}\nexport type FunctionPlugin<Options = any[]> = PluginInstallFunction<Options> &\n  Partial<ObjectPlugin<Options>>\n\nexport type Plugin<\n  Options = any[],\n  // TODO: in next major Options extends unknown[] and remove P\n  P extends unknown[] = Options extends unknown[] ? Options : [Options],\n> = FunctionPlugin<P> | ObjectPlugin<P>\n\nexport function createAppContext(): AppContext {\n  return {\n    app: null as any,\n    config: {\n      isNativeTag: NO,\n      performance: false,\n      globalProperties: {},\n      optionMergeStrategies: {},\n      errorHandler: undefined,\n      warnHandler: undefined,\n      compilerOptions: {},\n    },\n    mixins: [],\n    components: {},\n    directives: {},\n    provides: Object.create(null),\n    optionsCache: new WeakMap(),\n    propsCache: new WeakMap(),\n    emitsCache: new WeakMap(),\n  }\n}\n\nexport type CreateAppFunction<HostElement> = (\n  rootComponent: Component,\n  rootProps?: Data | null,\n) => App<HostElement>\n\nlet uid = 0\n\nexport function createAppAPI<HostElement>(\n  render: RootRenderFunction<HostElement>,\n  hydrate?: RootHydrateFunction,\n): CreateAppFunction<HostElement> {\n  return function createApp(rootComponent, rootProps = null) {\n    if (!isFunction(rootComponent)) {\n      rootComponent = extend({}, rootComponent)\n    }\n\n    if (rootProps != null && !isObject(rootProps)) {\n      __DEV__ && warn(`root props passed to app.mount() must be an object.`)\n      rootProps = null\n    }\n\n    const context = createAppContext()\n    const installedPlugins = new WeakSet()\n    const pluginCleanupFns: Array<() => any> = []\n\n    let isMounted = false\n\n    const app: App = (context.app = {\n      _uid: uid++,\n      _component: rootComponent as ConcreteComponent,\n      _props: rootProps,\n      _container: null,\n      _context: context,\n      _instance: null,\n\n      version,\n\n      get config() {\n        return context.config\n      },\n\n      set config(v) {\n        if (__DEV__) {\n          warn(\n            `app.config cannot be replaced. Modify individual options instead.`,\n          )\n        }\n      },\n\n      use(plugin: Plugin, ...options: any[]) {\n        if (installedPlugins.has(plugin)) {\n          __DEV__ && warn(`Plugin has already been applied to target app.`)\n        } else if (plugin && isFunction(plugin.install)) {\n          installedPlugins.add(plugin)\n          plugin.install(app, ...options)\n        } else if (isFunction(plugin)) {\n          installedPlugins.add(plugin)\n          plugin(app, ...options)\n        } else if (__DEV__) {\n          warn(\n            `A plugin must either be a function or an object with an \"install\" ` +\n              `function.`,\n          )\n        }\n        return app\n      },\n\n      mixin(mixin: ComponentOptions) {\n        if (__FEATURE_OPTIONS_API__) {\n          if (!context.mixins.includes(mixin)) {\n            context.mixins.push(mixin)\n          } else if (__DEV__) {\n            warn(\n              'Mixin has already been applied to target app' +\n                (mixin.name ? `: ${mixin.name}` : ''),\n            )\n          }\n        } else if (__DEV__) {\n          warn('Mixins are only available in builds supporting Options API')\n        }\n        return app\n      },\n\n      component(name: string, component?: Component): any {\n        if (__DEV__) {\n          validateComponentName(name, context.config)\n        }\n        if (!component) {\n          return context.components[name]\n        }\n        if (__DEV__ && context.components[name]) {\n          warn(`Component \"${name}\" has already been registered in target app.`)\n        }\n        context.components[name] = component\n        return app\n      },\n\n      directive(name: string, directive?: Directive) {\n        if (__DEV__) {\n          validateDirectiveName(name)\n        }\n\n        if (!directive) {\n          return context.directives[name] as any\n        }\n        if (__DEV__ && context.directives[name]) {\n          warn(`Directive \"${name}\" has already been registered in target app.`)\n        }\n        context.directives[name] = directive\n        return app\n      },\n\n      mount(\n        rootContainer: HostElement,\n        isHydrate?: boolean,\n        namespace?: boolean | ElementNamespace,\n      ): any {\n        if (!isMounted) {\n          // #5571\n          if (__DEV__ && (rootContainer as any).__vue_app__) {\n            warn(\n              `There is already an app instance mounted on the host container.\\n` +\n                ` If you want to mount another app on the same host container,` +\n                ` you need to unmount the previous app by calling \\`app.unmount()\\` first.`,\n            )\n          }\n          const vnode = app._ceVNode || createVNode(rootComponent, rootProps)\n          // store app context on the root VNode.\n          // this will be set on the root instance on initial mount.\n          vnode.appContext = context\n\n          if (namespace === true) {\n            namespace = 'svg'\n          } else if (namespace === false) {\n            namespace = undefined\n          }\n\n          // HMR root reload\n          if (__DEV__) {\n            context.reload = () => {\n              const cloned = cloneVNode(vnode)\n              // avoid hydration for hmr updating\n              cloned.el = null\n              // casting to ElementNamespace because TS doesn't guarantee type narrowing\n              // over function boundaries\n              render(cloned, rootContainer, namespace as ElementNamespace)\n            }\n          }\n\n          if (isHydrate && hydrate) {\n            hydrate(vnode as VNode<Node, Element>, rootContainer as any)\n          } else {\n            render(vnode, rootContainer, namespace)\n          }\n          isMounted = true\n          app._container = rootContainer\n          // for devtools and telemetry\n          ;(rootContainer as any).__vue_app__ = app\n\n          if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {\n            app._instance = vnode.component\n            devtoolsInitApp(app, version)\n          }\n\n          return getComponentPublicInstance(vnode.component!)\n        } else if (__DEV__) {\n          warn(\n            `App has already been mounted.\\n` +\n              `If you want to remount the same app, move your app creation logic ` +\n              `into a factory function and create fresh app instances for each ` +\n              `mount - e.g. \\`const createMyApp = () => createApp(App)\\``,\n          )\n        }\n      },\n\n      onUnmount(cleanupFn: () => void) {\n        if (__DEV__ && typeof cleanupFn !== 'function') {\n          warn(\n            `Expected function as first argument to app.onUnmount(), ` +\n              `but got ${typeof cleanupFn}`,\n          )\n        }\n        pluginCleanupFns.push(cleanupFn)\n      },\n\n      unmount() {\n        if (isMounted) {\n          callWithAsyncErrorHandling(\n            pluginCleanupFns,\n            app._instance,\n            ErrorCodes.APP_UNMOUNT_CLEANUP,\n          )\n          render(null, app._container)\n          if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {\n            app._instance = null\n            devtoolsUnmountApp(app)\n          }\n          delete app._container.__vue_app__\n        } else if (__DEV__) {\n          warn(`Cannot unmount an app that is not mounted.`)\n        }\n      },\n\n      provide(key, value) {\n        if (__DEV__ && (key as string | symbol) in context.provides) {\n          if (hasOwn(context.provides, key as string | symbol)) {\n            warn(\n              `App already provides property with key \"${String(key)}\". ` +\n                `It will be overwritten with the new value.`,\n            )\n          } else {\n            // #13212, context.provides can inherit the provides object from parent on custom elements\n            warn(\n              `App already provides property with key \"${String(key)}\" inherited from its parent element. ` +\n                `It will be overwritten with the new value.`,\n            )\n          }\n        }\n\n        context.provides[key as string | symbol] = value\n\n        return app\n      },\n\n      runWithContext(fn) {\n        const lastApp = currentApp\n        currentApp = app\n        try {\n          return fn()\n        } finally {\n          currentApp = lastApp\n        }\n      },\n    })\n\n    if (__COMPAT__) {\n      installAppCompatProperties(app, context, render)\n    }\n\n    return app\n  }\n}\n\n/**\n * @internal Used to identify the current app when using `inject()` within\n * `app.runWithContext()`.\n */\nexport let currentApp: App<unknown> | null = null\n"
  },
  {
    "path": "packages/runtime-core/src/apiDefineComponent.ts",
    "content": "import type {\n  ComponentInjectOptions,\n  ComponentOptions,\n  ComponentOptionsBase,\n  ComponentOptionsMixin,\n  ComponentProvideOptions,\n  ComputedOptions,\n  MethodOptions,\n  RenderFunction,\n} from './componentOptions'\nimport type {\n  AllowedComponentProps,\n  Component,\n  ComponentCustomProps,\n  GlobalComponents,\n  GlobalDirectives,\n  SetupContext,\n} from './component'\nimport type {\n  ComponentObjectPropsOptions,\n  ComponentPropsOptions,\n  ExtractDefaultPropTypes,\n  ExtractPropTypes,\n} from './componentProps'\nimport type {\n  EmitsOptions,\n  EmitsToProps,\n  TypeEmitsToOptions,\n} from './componentEmits'\nimport { type IsKeyValues, extend, isFunction } from '@vue/shared'\nimport type { VNodeProps } from './vnode'\nimport type {\n  ComponentPublicInstanceConstructor,\n  CreateComponentPublicInstanceWithMixins,\n} from './componentPublicInstance'\nimport type { SlotsType } from './componentSlots'\nimport type { Directive } from './directives'\nimport type { ComponentTypeEmits } from './apiSetupHelpers'\n\nexport type PublicProps = VNodeProps &\n  AllowedComponentProps &\n  ComponentCustomProps\n\ntype ResolveProps<PropsOrPropOptions, E extends EmitsOptions> = Readonly<\n  PropsOrPropOptions extends ComponentPropsOptions\n    ? ExtractPropTypes<PropsOrPropOptions>\n    : PropsOrPropOptions\n> &\n  ({} extends E ? {} : EmitsToProps<E>)\n\nexport type DefineComponent<\n  PropsOrPropOptions = {},\n  RawBindings = {},\n  D = {},\n  C extends ComputedOptions = ComputedOptions,\n  M extends MethodOptions = MethodOptions,\n  Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,\n  Extends extends ComponentOptionsMixin = ComponentOptionsMixin,\n  E extends EmitsOptions = {},\n  EE extends string = string,\n  PP = PublicProps,\n  Props = ResolveProps<PropsOrPropOptions, E>,\n  Defaults = ExtractDefaultPropTypes<PropsOrPropOptions>,\n  S extends SlotsType = {},\n  LC extends Record<string, Component> = {},\n  Directives extends Record<string, Directive> = {},\n  Exposed extends string = string,\n  Provide extends ComponentProvideOptions = ComponentProvideOptions,\n  MakeDefaultsOptional extends boolean = true,\n  TypeRefs extends Record<string, unknown> = {},\n  TypeEl extends Element = any,\n> = ComponentPublicInstanceConstructor<\n  CreateComponentPublicInstanceWithMixins<\n    Props,\n    RawBindings,\n    D,\n    C,\n    M,\n    Mixin,\n    Extends,\n    E,\n    PP,\n    Defaults,\n    MakeDefaultsOptional,\n    {},\n    S,\n    LC & GlobalComponents,\n    Directives & GlobalDirectives,\n    Exposed,\n    TypeRefs,\n    TypeEl\n  >\n> &\n  ComponentOptionsBase<\n    Props,\n    RawBindings,\n    D,\n    C,\n    M,\n    Mixin,\n    Extends,\n    E,\n    EE,\n    Defaults,\n    {},\n    string,\n    S,\n    LC & GlobalComponents,\n    Directives & GlobalDirectives,\n    Exposed,\n    Provide\n  > &\n  PP\n\nexport type DefineSetupFnComponent<\n  P extends Record<string, any>,\n  E extends EmitsOptions = {},\n  S extends SlotsType = SlotsType,\n  Props = P & EmitsToProps<E>,\n  PP = PublicProps,\n> = new (\n  props: Props & PP,\n) => CreateComponentPublicInstanceWithMixins<\n  Props,\n  {},\n  {},\n  {},\n  {},\n  ComponentOptionsMixin,\n  ComponentOptionsMixin,\n  E,\n  PP,\n  {},\n  false,\n  {},\n  S\n>\n\ntype ToResolvedProps<Props, Emits extends EmitsOptions> = Readonly<Props> &\n  Readonly<EmitsToProps<Emits>>\n\n// defineComponent is a utility that is primarily used for type inference\n// when declaring components. Type inference is provided in the component\n// options (provided as the argument). The returned value has artificial types\n// for TSX / manual render function / IDE support.\n\n// overload 1: direct setup function\n// (uses user defined props interface)\nexport function defineComponent<\n  Props extends Record<string, any>,\n  E extends EmitsOptions = {},\n  EE extends string = string,\n  S extends SlotsType = {},\n>(\n  setup: (\n    props: Props,\n    ctx: SetupContext<E, S>,\n  ) => RenderFunction | Promise<RenderFunction>,\n  options?: Pick<ComponentOptions, 'name' | 'inheritAttrs'> & {\n    props?: (keyof NoInfer<Props>)[]\n    emits?: E | EE[]\n    slots?: S\n  },\n): DefineSetupFnComponent<Props, E, S>\nexport function defineComponent<\n  Props extends Record<string, any>,\n  E extends EmitsOptions = {},\n  EE extends string = string,\n  S extends SlotsType = {},\n>(\n  setup: (\n    props: Props,\n    ctx: SetupContext<E, S>,\n  ) => RenderFunction | Promise<RenderFunction>,\n  options?: Pick<ComponentOptions, 'name' | 'inheritAttrs'> & {\n    props?: ComponentObjectPropsOptions<Props>\n    emits?: E | EE[]\n    slots?: S\n  },\n): DefineSetupFnComponent<Props, E, S>\n\n// overload 2: defineComponent with options object, infer props from options\nexport function defineComponent<\n  // props\n  TypeProps,\n  RuntimePropsOptions extends ComponentObjectPropsOptions =\n    ComponentObjectPropsOptions,\n  RuntimePropsKeys extends string = string,\n  // emits\n  TypeEmits extends ComponentTypeEmits = {},\n  RuntimeEmitsOptions extends EmitsOptions = {},\n  RuntimeEmitsKeys extends string = string,\n  // other options\n  Data = {},\n  SetupBindings = {},\n  Computed extends ComputedOptions = {},\n  Methods extends MethodOptions = {},\n  Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,\n  Extends extends ComponentOptionsMixin = ComponentOptionsMixin,\n  InjectOptions extends ComponentInjectOptions = {},\n  InjectKeys extends string = string,\n  Slots extends SlotsType = {},\n  LocalComponents extends Record<string, Component> = {},\n  Directives extends Record<string, Directive> = {},\n  Exposed extends string = string,\n  Provide extends ComponentProvideOptions = ComponentProvideOptions,\n  // resolved types\n  ResolvedEmits extends EmitsOptions = {} extends RuntimeEmitsOptions\n    ? TypeEmitsToOptions<TypeEmits>\n    : RuntimeEmitsOptions,\n  InferredProps = IsKeyValues<TypeProps> extends true\n    ? TypeProps\n    : string extends RuntimePropsKeys\n      ? ComponentObjectPropsOptions extends RuntimePropsOptions\n        ? {}\n        : ExtractPropTypes<RuntimePropsOptions>\n      : { [key in RuntimePropsKeys]?: any },\n  TypeRefs extends Record<string, unknown> = {},\n  TypeEl extends Element = any,\n>(\n  options: {\n    props?: (RuntimePropsOptions & ThisType<void>) | RuntimePropsKeys[]\n    /**\n     * @private for language-tools use only\n     */\n    __typeProps?: TypeProps\n    /**\n     * @private for language-tools use only\n     */\n    __typeEmits?: TypeEmits\n    /**\n     * @private for language-tools use only\n     */\n    __typeRefs?: TypeRefs\n    /**\n     * @private for language-tools use only\n     */\n    __typeEl?: TypeEl\n  } & ComponentOptionsBase<\n    ToResolvedProps<InferredProps, ResolvedEmits>,\n    SetupBindings,\n    Data,\n    Computed,\n    Methods,\n    Mixin,\n    Extends,\n    RuntimeEmitsOptions,\n    RuntimeEmitsKeys,\n    {}, // Defaults\n    InjectOptions,\n    InjectKeys,\n    Slots,\n    LocalComponents,\n    Directives,\n    Exposed,\n    Provide\n  > &\n    ThisType<\n      CreateComponentPublicInstanceWithMixins<\n        ToResolvedProps<InferredProps, ResolvedEmits>,\n        SetupBindings,\n        Data,\n        Computed,\n        Methods,\n        Mixin,\n        Extends,\n        ResolvedEmits,\n        {},\n        {},\n        false,\n        InjectOptions,\n        Slots,\n        LocalComponents,\n        Directives,\n        string\n      >\n    >,\n): DefineComponent<\n  InferredProps,\n  SetupBindings,\n  Data,\n  Computed,\n  Methods,\n  Mixin,\n  Extends,\n  ResolvedEmits,\n  RuntimeEmitsKeys,\n  PublicProps,\n  ToResolvedProps<InferredProps, ResolvedEmits>,\n  ExtractDefaultPropTypes<RuntimePropsOptions>,\n  Slots,\n  LocalComponents,\n  Directives,\n  Exposed,\n  Provide,\n  // MakeDefaultsOptional - if TypeProps is provided, set to false to use\n  // user props types verbatim\n  unknown extends TypeProps ? true : false,\n  TypeRefs,\n  TypeEl\n>\n\n// implementation, close to no-op\n/*@__NO_SIDE_EFFECTS__*/\nexport function defineComponent(\n  options: unknown,\n  extraOptions?: ComponentOptions,\n) {\n  return isFunction(options)\n    ? // #8236: extend call and options.name access are considered side-effects\n      // by Rollup, so we have to wrap it in a pure-annotated IIFE.\n      /*@__PURE__*/ (() =>\n        extend({ name: options.name }, extraOptions, { setup: options }))()\n    : options\n}\n"
  },
  {
    "path": "packages/runtime-core/src/apiInject.ts",
    "content": "import { isFunction } from '@vue/shared'\nimport { currentInstance, getCurrentInstance } from './component'\nimport { currentApp } from './apiCreateApp'\nimport { warn } from './warning'\n\ninterface InjectionConstraint<T> {}\n\nexport type InjectionKey<T> = symbol & InjectionConstraint<T>\n\nexport function provide<T, K = InjectionKey<T> | string | number>(\n  key: K,\n  value: K extends InjectionKey<infer V> ? V : T,\n): void {\n  if (__DEV__) {\n    if (!currentInstance || currentInstance.isMounted) {\n      warn(`provide() can only be used inside setup().`)\n    }\n  }\n  if (currentInstance) {\n    let provides = currentInstance.provides\n    // by default an instance inherits its parent's provides object\n    // but when it needs to provide values of its own, it creates its\n    // own provides object using parent provides object as prototype.\n    // this way in `inject` we can simply look up injections from direct\n    // parent and let the prototype chain do the work.\n    const parentProvides =\n      currentInstance.parent && currentInstance.parent.provides\n    if (parentProvides === provides) {\n      provides = currentInstance.provides = Object.create(parentProvides)\n    }\n    // TS doesn't allow symbol as index type\n    provides[key as string] = value\n  }\n}\n\nexport function inject<T>(key: InjectionKey<T> | string): T | undefined\nexport function inject<T>(\n  key: InjectionKey<T> | string,\n  defaultValue: T,\n  treatDefaultAsFactory?: false,\n): T\nexport function inject<T>(\n  key: InjectionKey<T> | string,\n  defaultValue: T | (() => T),\n  treatDefaultAsFactory: true,\n): T\nexport function inject(\n  key: InjectionKey<any> | string,\n  defaultValue?: unknown,\n  treatDefaultAsFactory = false,\n) {\n  // fallback to `currentRenderingInstance` so that this can be called in\n  // a functional component\n  const instance = getCurrentInstance()\n\n  // also support looking up from app-level provides w/ `app.runWithContext()`\n  if (instance || currentApp) {\n    // #2400\n    // to support `app.use` plugins,\n    // fallback to appContext's `provides` if the instance is at root\n    // #11488, in a nested createApp, prioritize using the provides from currentApp\n    // #13212, for custom elements we must get injected values from its appContext\n    // as it already inherits the provides object from the parent element\n    let provides = currentApp\n      ? currentApp._context.provides\n      : instance\n        ? instance.parent == null || instance.ce\n          ? instance.vnode.appContext && instance.vnode.appContext.provides\n          : instance.parent.provides\n        : undefined\n\n    if (provides && (key as string | symbol) in provides) {\n      // TS doesn't allow symbol as index type\n      return provides[key as string]\n    } else if (arguments.length > 1) {\n      return treatDefaultAsFactory && isFunction(defaultValue)\n        ? defaultValue.call(instance && instance.proxy)\n        : defaultValue\n    } else if (__DEV__) {\n      warn(`injection \"${String(key)}\" not found.`)\n    }\n  } else if (__DEV__) {\n    warn(`inject() can only be used inside setup() or functional components.`)\n  }\n}\n\n/**\n * Returns true if `inject()` can be used without warning about being called in the wrong place (e.g. outside of\n * setup()). This is used by libraries that want to use `inject()` internally without triggering a warning to the end\n * user. One example is `useRoute()` in `vue-router`.\n */\nexport function hasInjectionContext(): boolean {\n  return !!(getCurrentInstance() || currentApp)\n}\n"
  },
  {
    "path": "packages/runtime-core/src/apiLifecycle.ts",
    "content": "import {\n  type ComponentInternalInstance,\n  currentInstance,\n  isInSSRComponentSetup,\n  setCurrentInstance,\n} from './component'\nimport type { ComponentPublicInstance } from './componentPublicInstance'\nimport { ErrorTypeStrings, callWithAsyncErrorHandling } from './errorHandling'\nimport { warn } from './warning'\nimport { toHandlerKey } from '@vue/shared'\nimport {\n  type DebuggerEvent,\n  pauseTracking,\n  resetTracking,\n} from '@vue/reactivity'\nimport { LifecycleHooks } from './enums'\n\nexport { onActivated, onDeactivated } from './components/KeepAlive'\n\nexport function injectHook(\n  type: LifecycleHooks,\n  hook: Function & { __weh?: Function },\n  target: ComponentInternalInstance | null = currentInstance,\n  prepend: boolean = false,\n): Function | undefined {\n  if (target) {\n    const hooks = target[type] || (target[type] = [])\n    // cache the error handling wrapper for injected hooks so the same hook\n    // can be properly deduped by the scheduler. \"__weh\" stands for \"with error\n    // handling\".\n    const wrappedHook =\n      hook.__weh ||\n      (hook.__weh = (...args: unknown[]) => {\n        // disable tracking inside all lifecycle hooks\n        // since they can potentially be called inside effects.\n        pauseTracking()\n        // Set currentInstance during hook invocation.\n        // This assumes the hook does not synchronously trigger other hooks, which\n        // can only be false when the user does something really funky.\n        const reset = setCurrentInstance(target)\n        const res = callWithAsyncErrorHandling(hook, target, type, args)\n        reset()\n        resetTracking()\n        return res\n      })\n    if (prepend) {\n      hooks.unshift(wrappedHook)\n    } else {\n      hooks.push(wrappedHook)\n    }\n    return wrappedHook\n  } else if (__DEV__) {\n    const apiName = toHandlerKey(ErrorTypeStrings[type].replace(/ hook$/, ''))\n    warn(\n      `${apiName} is called when there is no active component instance to be ` +\n        `associated with. ` +\n        `Lifecycle injection APIs can only be used during execution of setup().` +\n        (__FEATURE_SUSPENSE__\n          ? ` If you are using async setup(), make sure to register lifecycle ` +\n            `hooks before the first await statement.`\n          : ``),\n    )\n  }\n}\n\nconst createHook =\n  <T extends Function = () => any>(lifecycle: LifecycleHooks) =>\n  (\n    hook: T,\n    target: ComponentInternalInstance | null = currentInstance,\n  ): void => {\n    // post-create lifecycle registrations are noops during SSR (except for serverPrefetch)\n    if (\n      !isInSSRComponentSetup ||\n      lifecycle === LifecycleHooks.SERVER_PREFETCH\n    ) {\n      injectHook(lifecycle, (...args: unknown[]) => hook(...args), target)\n    }\n  }\ntype CreateHook<T = any> = (\n  hook: T,\n  target?: ComponentInternalInstance | null,\n) => void\n\nexport const onBeforeMount: CreateHook = createHook(LifecycleHooks.BEFORE_MOUNT)\nexport const onMounted: CreateHook = createHook(LifecycleHooks.MOUNTED)\nexport const onBeforeUpdate: CreateHook = createHook(\n  LifecycleHooks.BEFORE_UPDATE,\n)\nexport const onUpdated: CreateHook = createHook(LifecycleHooks.UPDATED)\nexport const onBeforeUnmount: CreateHook = createHook(\n  LifecycleHooks.BEFORE_UNMOUNT,\n)\nexport const onUnmounted: CreateHook = createHook(LifecycleHooks.UNMOUNTED)\nexport const onServerPrefetch: CreateHook = createHook(\n  LifecycleHooks.SERVER_PREFETCH,\n)\n\nexport type DebuggerHook = (e: DebuggerEvent) => void\nexport const onRenderTriggered: CreateHook<DebuggerHook> =\n  createHook<DebuggerHook>(LifecycleHooks.RENDER_TRIGGERED)\nexport const onRenderTracked: CreateHook<DebuggerHook> =\n  createHook<DebuggerHook>(LifecycleHooks.RENDER_TRACKED)\n\nexport type ErrorCapturedHook<TError = unknown> = (\n  err: TError,\n  instance: ComponentPublicInstance | null,\n  info: string,\n) => boolean | void\n\nexport function onErrorCaptured<TError = Error>(\n  hook: ErrorCapturedHook<TError>,\n  target: ComponentInternalInstance | null = currentInstance,\n): void {\n  injectHook(LifecycleHooks.ERROR_CAPTURED, hook, target)\n}\n"
  },
  {
    "path": "packages/runtime-core/src/apiSetupHelpers.ts",
    "content": "import {\n  type IfAny,\n  type LooseRequired,\n  type Prettify,\n  type UnionToIntersection,\n  extend,\n  isArray,\n  isFunction,\n  isPromise,\n} from '@vue/shared'\nimport {\n  type SetupContext,\n  createSetupContext,\n  getCurrentInstance,\n  isInSSRComponentSetup,\n  setCurrentInstance,\n  setInSSRSetupState,\n  unsetCurrentInstance,\n} from './component'\nimport type { EmitFn, EmitsOptions, ObjectEmitsOptions } from './componentEmits'\nimport type {\n  ComponentOptionsBase,\n  ComponentOptionsMixin,\n  ComputedOptions,\n  MethodOptions,\n} from './componentOptions'\nimport type {\n  ComponentObjectPropsOptions,\n  ComponentPropsOptions,\n  ExtractPropTypes,\n  PropOptions,\n} from './componentProps'\nimport { warn } from './warning'\nimport type { SlotsType, StrictUnwrapSlotsType } from './componentSlots'\nimport type { Ref } from '@vue/reactivity'\n\n// dev only\nconst warnRuntimeUsage = (method: string) =>\n  warn(\n    `${method}() is a compiler-hint helper that is only usable inside ` +\n      `<script setup> of a single file component. Its arguments should be ` +\n      `compiled away and passing it at runtime has no effect.`,\n  )\n\n/**\n * Vue `<script setup>` compiler macro for declaring component props. The\n * expected argument is the same as the component `props` option.\n *\n * Example runtime declaration:\n * ```js\n * // using Array syntax\n * const props = defineProps(['foo', 'bar'])\n * // using Object syntax\n * const props = defineProps({\n *   foo: String,\n *   bar: {\n *     type: Number,\n *     required: true\n *   }\n * })\n * ```\n *\n * Equivalent type-based declaration:\n * ```ts\n * // will be compiled into equivalent runtime declarations\n * const props = defineProps<{\n *   foo?: string\n *   bar: number\n * }>()\n * ```\n *\n * @see {@link https://vuejs.org/api/sfc-script-setup.html#defineprops-defineemits}\n *\n * This is only usable inside `<script setup>`, is compiled away in the\n * output and should **not** be actually called at runtime.\n */\n// overload 1: runtime props w/ array\nexport function defineProps<PropNames extends string = string>(\n  props: PropNames[],\n): Prettify<Readonly<{ [key in PropNames]?: any }>>\n// overload 2: runtime props w/ object\nexport function defineProps<\n  PP extends ComponentObjectPropsOptions = ComponentObjectPropsOptions,\n>(props: PP): Prettify<Readonly<ExtractPropTypes<PP>>>\n// overload 3: typed-based declaration\nexport function defineProps<TypeProps>(): DefineProps<\n  LooseRequired<TypeProps>,\n  BooleanKey<TypeProps>\n>\n// implementation\nexport function defineProps() {\n  if (__DEV__) {\n    warnRuntimeUsage(`defineProps`)\n  }\n  return null as any\n}\n\nexport type DefineProps<T, BKeys extends keyof T> = Readonly<T> & {\n  readonly [K in BKeys]-?: boolean\n}\n\ntype BooleanKey<T, K extends keyof T = keyof T> = K extends any\n  ? T[K] extends boolean | undefined\n    ? T[K] extends never | undefined\n      ? never\n      : K\n    : never\n  : never\n\n/**\n * Vue `<script setup>` compiler macro for declaring a component's emitted\n * events. The expected argument is the same as the component `emits` option.\n *\n * Example runtime declaration:\n * ```js\n * const emit = defineEmits(['change', 'update'])\n * ```\n *\n * Example type-based declaration:\n * ```ts\n * const emit = defineEmits<{\n *   // <eventName>: <expected arguments>\n *   change: []\n *   update: [value: number] // named tuple syntax\n * }>()\n *\n * emit('change')\n * emit('update', 1)\n * ```\n *\n * This is only usable inside `<script setup>`, is compiled away in the\n * output and should **not** be actually called at runtime.\n *\n * @see {@link https://vuejs.org/api/sfc-script-setup.html#defineprops-defineemits}\n */\n// overload 1: runtime emits w/ array\nexport function defineEmits<EE extends string = string>(\n  emitOptions: EE[],\n): EmitFn<EE[]>\nexport function defineEmits<E extends EmitsOptions = EmitsOptions>(\n  emitOptions: E,\n): EmitFn<E>\nexport function defineEmits<T extends ComponentTypeEmits>(): T extends (\n  ...args: any[]\n) => any\n  ? T\n  : ShortEmits<T>\n// implementation\nexport function defineEmits() {\n  if (__DEV__) {\n    warnRuntimeUsage(`defineEmits`)\n  }\n  return null as any\n}\n\nexport type ComponentTypeEmits = ((...args: any[]) => any) | Record<string, any>\n\ntype RecordToUnion<T extends Record<string, any>> = T[keyof T]\n\ntype ShortEmits<T extends Record<string, any>> = UnionToIntersection<\n  RecordToUnion<{\n    [K in keyof T]: (evt: K, ...args: T[K]) => void\n  }>\n>\n\n/**\n * Vue `<script setup>` compiler macro for declaring a component's exposed\n * instance properties when it is accessed by a parent component via template\n * refs.\n *\n * `<script setup>` components are closed by default - i.e. variables inside\n * the `<script setup>` scope is not exposed to parent unless explicitly exposed\n * via `defineExpose`.\n *\n * This is only usable inside `<script setup>`, is compiled away in the\n * output and should **not** be actually called at runtime.\n *\n * @see {@link https://vuejs.org/api/sfc-script-setup.html#defineexpose}\n */\nexport function defineExpose<\n  Exposed extends Record<string, any> = Record<string, any>,\n>(exposed?: Exposed): void {\n  if (__DEV__) {\n    warnRuntimeUsage(`defineExpose`)\n  }\n}\n\n/**\n * Vue `<script setup>` compiler macro for declaring a component's additional\n * options. This should be used only for options that cannot be expressed via\n * Composition API - e.g. `inheritAttrs`.\n *\n * @see {@link https://vuejs.org/api/sfc-script-setup.html#defineoptions}\n */\nexport function defineOptions<\n  RawBindings = {},\n  D = {},\n  C extends ComputedOptions = {},\n  M extends MethodOptions = {},\n  Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,\n  Extends extends ComponentOptionsMixin = ComponentOptionsMixin,\n>(\n  options?: ComponentOptionsBase<\n    {},\n    RawBindings,\n    D,\n    C,\n    M,\n    Mixin,\n    Extends,\n    {}\n  > & {\n    /**\n     * props should be defined via defineProps().\n     */\n    props?: never\n    /**\n     * emits should be defined via defineEmits().\n     */\n    emits?: never\n    /**\n     * expose should be defined via defineExpose().\n     */\n    expose?: never\n    /**\n     * slots should be defined via defineSlots().\n     */\n    slots?: never\n  },\n): void {\n  if (__DEV__) {\n    warnRuntimeUsage(`defineOptions`)\n  }\n}\n\n/**\n * Vue `<script setup>` compiler macro for providing type hints to IDEs for\n * slot name and slot props type checking.\n *\n * Example usage:\n * ```ts\n * const slots = defineSlots<{\n *   default(props: { msg: string }): any\n * }>()\n * ```\n *\n * This is only usable inside `<script setup>`, is compiled away in the\n * output and should **not** be actually called at runtime.\n *\n * @see {@link https://vuejs.org/api/sfc-script-setup.html#defineslots}\n */\nexport function defineSlots<\n  S extends Record<string, any> = Record<string, any>,\n>(): StrictUnwrapSlotsType<SlotsType<S>> {\n  if (__DEV__) {\n    warnRuntimeUsage(`defineSlots`)\n  }\n  return null as any\n}\n\nexport type ModelRef<T, M extends PropertyKey = string, G = T, S = T> = Ref<\n  G,\n  S\n> &\n  [ModelRef<T, M, G, S>, Record<M, true | undefined>]\n\nexport type DefineModelOptions<T = any, G = T, S = T> = {\n  get?: (v: T) => G\n  set?: (v: S) => any\n}\n\n/**\n * Vue `<script setup>` compiler macro for declaring a\n * two-way binding prop that can be consumed via `v-model` from the parent\n * component. This will declare a prop with the same name and a corresponding\n * `update:propName` event.\n *\n * If the first argument is a string, it will be used as the prop name;\n * Otherwise the prop name will default to \"modelValue\". In both cases, you\n * can also pass an additional object which will be used as the prop's options.\n *\n * The returned ref behaves differently depending on whether the parent\n * provided the corresponding v-model props or not:\n * - If yes, the returned ref's value will always be in sync with the parent\n *   prop.\n * - If not, the returned ref will behave like a normal local ref.\n *\n * @example\n * ```ts\n * // default model (consumed via `v-model`)\n * const modelValue = defineModel<string>()\n * modelValue.value = \"hello\"\n *\n * // default model with options\n * const modelValue = defineModel<string>({ required: true })\n *\n * // with specified name (consumed via `v-model:count`)\n * const count = defineModel<number>('count')\n * count.value++\n *\n * // with specified name and default value\n * const count = defineModel<number>('count', { default: 0 })\n * ```\n */\nexport function defineModel<T, M extends PropertyKey = string, G = T, S = T>(\n  options: ({ default: any } | { required: true }) &\n    PropOptions<T> &\n    DefineModelOptions<T, G, S>,\n): ModelRef<T, M, G, S>\n\nexport function defineModel<T, M extends PropertyKey = string, G = T, S = T>(\n  options?: PropOptions<T> & DefineModelOptions<T, G, S>,\n): ModelRef<T | undefined, M, G | undefined, S | undefined>\n\nexport function defineModel<T, M extends PropertyKey = string, G = T, S = T>(\n  name: string,\n  options: ({ default: any } | { required: true }) &\n    PropOptions<T> &\n    DefineModelOptions<T, G, S>,\n): ModelRef<T, M, G, S>\n\nexport function defineModel<T, M extends PropertyKey = string, G = T, S = T>(\n  name: string,\n  options?: PropOptions<T> & DefineModelOptions<T, G, S>,\n): ModelRef<T | undefined, M, G | undefined, S | undefined>\n\nexport function defineModel(): any {\n  if (__DEV__) {\n    warnRuntimeUsage('defineModel')\n  }\n}\n\ntype NotUndefined<T> = T extends undefined ? never : T\ntype MappedOmit<T, K extends keyof any> = {\n  [P in keyof T as P extends K ? never : P]: T[P]\n}\n\ntype InferDefaults<T> = {\n  [K in keyof T]?: InferDefault<T, T[K]>\n}\n\ntype NativeType =\n  | null\n  | undefined\n  | number\n  | string\n  | boolean\n  | symbol\n  | Function\n\ntype InferDefault<P, T> =\n  | ((props: P) => T & {})\n  | (T extends NativeType ? T : never)\n\ntype PropsWithDefaults<\n  T,\n  Defaults extends InferDefaults<T>,\n  BKeys extends keyof T,\n> = T extends unknown\n  ? Readonly<MappedOmit<T, keyof Defaults>> & {\n      readonly [K in keyof Defaults as K extends keyof T\n        ? K\n        : never]-?: K extends keyof T\n        ? Defaults[K] extends undefined\n          ? IfAny<Defaults[K], NotUndefined<T[K]>, T[K]>\n          : NotUndefined<T[K]>\n        : never\n    } & {\n      readonly [K in BKeys]-?: K extends keyof Defaults\n        ? Defaults[K] extends undefined\n          ? boolean | undefined\n          : boolean\n        : boolean\n    }\n  : never\n\n/**\n * Vue `<script setup>` compiler macro for providing props default values when\n * using type-based `defineProps` declaration.\n *\n * Example usage:\n * ```ts\n * withDefaults(defineProps<{\n *   size?: number\n *   labels?: string[]\n * }>(), {\n *   size: 3,\n *   labels: () => ['default label']\n * })\n * ```\n *\n * This is only usable inside `<script setup>`, is compiled away in the output\n * and should **not** be actually called at runtime.\n *\n * @see {@link https://vuejs.org/guide/typescript/composition-api.html#typing-component-props}\n */\nexport function withDefaults<\n  T,\n  BKeys extends keyof T,\n  Defaults extends InferDefaults<T>,\n>(\n  props: DefineProps<T, BKeys>,\n  defaults: Defaults,\n): PropsWithDefaults<T, Defaults, BKeys> {\n  if (__DEV__) {\n    warnRuntimeUsage(`withDefaults`)\n  }\n  return null as any\n}\n\nexport function useSlots(): SetupContext['slots'] {\n  return getContext('useSlots').slots\n}\n\nexport function useAttrs(): SetupContext['attrs'] {\n  return getContext('useAttrs').attrs\n}\n\nfunction getContext(calledFunctionName: string): SetupContext {\n  const i = getCurrentInstance()!\n  if (__DEV__ && !i) {\n    warn(`${calledFunctionName}() called without active instance.`)\n  }\n  return i.setupContext || (i.setupContext = createSetupContext(i))\n}\n\n/**\n * @internal\n */\nexport function normalizePropsOrEmits(\n  props: ComponentPropsOptions | EmitsOptions,\n): ComponentObjectPropsOptions | ObjectEmitsOptions {\n  return isArray(props)\n    ? props.reduce(\n        (normalized, p) => ((normalized[p] = null), normalized),\n        {} as ComponentObjectPropsOptions | ObjectEmitsOptions,\n      )\n    : props\n}\n\n/**\n * Runtime helper for merging default declarations. Imported by compiled code\n * only.\n * @internal\n */\nexport function mergeDefaults(\n  raw: ComponentPropsOptions,\n  defaults: Record<string, any>,\n): ComponentObjectPropsOptions {\n  const props = normalizePropsOrEmits(raw)\n  for (const key in defaults) {\n    if (key.startsWith('__skip')) continue\n    let opt = props[key]\n    if (opt) {\n      if (isArray(opt) || isFunction(opt)) {\n        opt = props[key] = { type: opt, default: defaults[key] }\n      } else {\n        opt.default = defaults[key]\n      }\n    } else if (opt === null) {\n      opt = props[key] = { default: defaults[key] }\n    } else if (__DEV__) {\n      warn(`props default key \"${key}\" has no corresponding declaration.`)\n    }\n    if (opt && defaults[`__skip_${key}`]) {\n      opt.skipFactory = true\n    }\n  }\n  return props\n}\n\n/**\n * Runtime helper for merging model declarations.\n * Imported by compiled code only.\n * @internal\n */\nexport function mergeModels(\n  a: ComponentPropsOptions | EmitsOptions,\n  b: ComponentPropsOptions | EmitsOptions,\n): ComponentPropsOptions | EmitsOptions {\n  if (!a || !b) return a || b\n  if (isArray(a) && isArray(b)) return a.concat(b)\n  return extend({}, normalizePropsOrEmits(a), normalizePropsOrEmits(b))\n}\n\n/**\n * Used to create a proxy for the rest element when destructuring props with\n * defineProps().\n * @internal\n */\nexport function createPropsRestProxy(\n  props: any,\n  excludedKeys: string[],\n): Record<string, any> {\n  const ret: Record<string, any> = {}\n  for (const key in props) {\n    if (!excludedKeys.includes(key)) {\n      Object.defineProperty(ret, key, {\n        enumerable: true,\n        get: () => props[key],\n      })\n    }\n  }\n  return ret\n}\n\n/**\n * `<script setup>` helper for persisting the current instance context over\n * async/await flows.\n *\n * `@vue/compiler-sfc` converts the following:\n *\n * ```ts\n * const x = await foo()\n * ```\n *\n * into:\n *\n * ```ts\n * let __temp, __restore\n * const x = (([__temp, __restore] = withAsyncContext(() => foo())),__temp=await __temp,__restore(),__temp)\n * ```\n * @internal\n */\nexport function withAsyncContext(getAwaitable: () => any): [any, () => void] {\n  const ctx = getCurrentInstance()!\n  const inSSRSetup = isInSSRComponentSetup\n  if (__DEV__ && !ctx) {\n    warn(\n      `withAsyncContext called without active current instance. ` +\n        `This is likely a bug.`,\n    )\n  }\n  let awaitable = getAwaitable()\n  unsetCurrentInstance()\n  if (inSSRSetup) {\n    setInSSRSetupState(false)\n  }\n\n  const restore = () => {\n    setCurrentInstance(ctx)\n    if (inSSRSetup) {\n      setInSSRSetupState(true)\n    }\n  }\n\n  // Never restore a captured \"prev\" instance here: in concurrent async setup\n  // continuations it may belong to a sibling component and cause leaks.\n  // We only need to balance ctx.scope.on() from setCurrentInstance(ctx),\n  // then clear global currentInstance for user microtasks.\n  const cleanup = () => {\n    if (getCurrentInstance() !== ctx) ctx.scope.off()\n    unsetCurrentInstance()\n    if (inSSRSetup) {\n      setInSSRSetupState(false)\n    }\n  }\n\n  if (isPromise(awaitable)) {\n    awaitable = awaitable.catch(e => {\n      restore()\n      // Defer cleanup so the async function's catch continuation\n      // still runs with the restored instance.\n      Promise.resolve().then(() => Promise.resolve().then(cleanup))\n      throw e\n    })\n  }\n  return [\n    awaitable,\n    () => {\n      restore()\n      // Keep instance for the current continuation, then cleanup.\n      Promise.resolve().then(cleanup)\n    },\n  ]\n}\n"
  },
  {
    "path": "packages/runtime-core/src/apiWatch.ts",
    "content": "import {\n  type WatchOptions as BaseWatchOptions,\n  type DebuggerOptions,\n  type ReactiveMarker,\n  type WatchCallback,\n  type WatchEffect,\n  type WatchHandle,\n  type WatchSource,\n  watch as baseWatch,\n} from '@vue/reactivity'\nimport { type SchedulerJob, SchedulerJobFlags, queueJob } from './scheduler'\nimport { EMPTY_OBJ, NOOP, extend, isFunction, isString } from '@vue/shared'\nimport {\n  type ComponentInternalInstance,\n  currentInstance,\n  isInSSRComponentSetup,\n  setCurrentInstance,\n} from './component'\nimport { callWithAsyncErrorHandling } from './errorHandling'\nimport { queuePostRenderEffect } from './renderer'\nimport { warn } from './warning'\nimport type { ObjectWatchOptionItem } from './componentOptions'\nimport { useSSRContext } from './helpers/useSsrContext'\nimport type { ComponentPublicInstance } from './componentPublicInstance'\n\nexport type {\n  WatchHandle,\n  WatchStopHandle,\n  WatchEffect,\n  WatchSource,\n  WatchCallback,\n  OnCleanup,\n} from '@vue/reactivity'\n\ntype MaybeUndefined<T, I> = I extends true ? T | undefined : T\n\ntype MapSources<T, Immediate> = {\n  [K in keyof T]: T[K] extends WatchSource<infer V>\n    ? MaybeUndefined<V, Immediate>\n    : T[K] extends object\n      ? MaybeUndefined<T[K], Immediate>\n      : never\n}\n\nexport interface WatchEffectOptions extends DebuggerOptions {\n  flush?: 'pre' | 'post' | 'sync'\n}\n\nexport interface WatchOptions<Immediate = boolean> extends WatchEffectOptions {\n  immediate?: Immediate\n  deep?: boolean | number\n  once?: boolean\n}\n\n// Simple effect.\nexport function watchEffect(\n  effect: WatchEffect,\n  options?: WatchEffectOptions,\n): WatchHandle {\n  return doWatch(effect, null, options)\n}\n\nexport function watchPostEffect(\n  effect: WatchEffect,\n  options?: DebuggerOptions,\n): WatchHandle {\n  return doWatch(\n    effect,\n    null,\n    __DEV__\n      ? extend({}, options as WatchEffectOptions, { flush: 'post' })\n      : { flush: 'post' },\n  )\n}\n\nexport function watchSyncEffect(\n  effect: WatchEffect,\n  options?: DebuggerOptions,\n): WatchHandle {\n  return doWatch(\n    effect,\n    null,\n    __DEV__\n      ? extend({}, options as WatchEffectOptions, { flush: 'sync' })\n      : { flush: 'sync' },\n  )\n}\n\nexport type MultiWatchSources = (WatchSource<unknown> | object)[]\n\n// overload: single source + cb\nexport function watch<T, Immediate extends Readonly<boolean> = false>(\n  source: WatchSource<T>,\n  cb: WatchCallback<T, MaybeUndefined<T, Immediate>>,\n  options?: WatchOptions<Immediate>,\n): WatchHandle\n\n// overload: reactive array or tuple of multiple sources + cb\nexport function watch<\n  T extends Readonly<MultiWatchSources>,\n  Immediate extends Readonly<boolean> = false,\n>(\n  sources: readonly [...T] | T,\n  cb: [T] extends [ReactiveMarker]\n    ? WatchCallback<T, MaybeUndefined<T, Immediate>>\n    : WatchCallback<MapSources<T, false>, MapSources<T, Immediate>>,\n  options?: WatchOptions<Immediate>,\n): WatchHandle\n\n// overload: array of multiple sources + cb\nexport function watch<\n  T extends MultiWatchSources,\n  Immediate extends Readonly<boolean> = false,\n>(\n  sources: [...T],\n  cb: WatchCallback<MapSources<T, false>, MapSources<T, Immediate>>,\n  options?: WatchOptions<Immediate>,\n): WatchHandle\n\n// overload: watching reactive object w/ cb\nexport function watch<\n  T extends object,\n  Immediate extends Readonly<boolean> = false,\n>(\n  source: T,\n  cb: WatchCallback<T, MaybeUndefined<T, Immediate>>,\n  options?: WatchOptions<Immediate>,\n): WatchHandle\n\n// implementation\nexport function watch<T = any, Immediate extends Readonly<boolean> = false>(\n  source: T | WatchSource<T>,\n  cb: any,\n  options?: WatchOptions<Immediate>,\n): WatchHandle {\n  if (__DEV__ && !isFunction(cb)) {\n    warn(\n      `\\`watch(fn, options?)\\` signature has been moved to a separate API. ` +\n        `Use \\`watchEffect(fn, options?)\\` instead. \\`watch\\` now only ` +\n        `supports \\`watch(source, cb, options?) signature.`,\n    )\n  }\n  return doWatch(source as any, cb, options)\n}\n\nfunction doWatch(\n  source: WatchSource | WatchSource[] | WatchEffect | object,\n  cb: WatchCallback | null,\n  options: WatchOptions = EMPTY_OBJ,\n): WatchHandle {\n  const { immediate, deep, flush, once } = options\n\n  if (__DEV__ && !cb) {\n    if (immediate !== undefined) {\n      warn(\n        `watch() \"immediate\" option is only respected when using the ` +\n          `watch(source, callback, options?) signature.`,\n      )\n    }\n    if (deep !== undefined) {\n      warn(\n        `watch() \"deep\" option is only respected when using the ` +\n          `watch(source, callback, options?) signature.`,\n      )\n    }\n    if (once !== undefined) {\n      warn(\n        `watch() \"once\" option is only respected when using the ` +\n          `watch(source, callback, options?) signature.`,\n      )\n    }\n  }\n\n  const baseWatchOptions: BaseWatchOptions = extend({}, options)\n\n  if (__DEV__) baseWatchOptions.onWarn = warn\n\n  // immediate watcher or watchEffect\n  const runsImmediately = (cb && immediate) || (!cb && flush !== 'post')\n  let ssrCleanup: (() => void)[] | undefined\n  if (__SSR__ && isInSSRComponentSetup) {\n    if (flush === 'sync') {\n      const ctx = useSSRContext()!\n      ssrCleanup = ctx.__watcherHandles || (ctx.__watcherHandles = [])\n    } else if (!runsImmediately) {\n      const watchStopHandle = () => {}\n      watchStopHandle.stop = NOOP\n      watchStopHandle.resume = NOOP\n      watchStopHandle.pause = NOOP\n      return watchStopHandle\n    }\n  }\n\n  const instance = currentInstance\n  baseWatchOptions.call = (fn, type, args) =>\n    callWithAsyncErrorHandling(fn, instance, type, args)\n\n  // scheduler\n  let isPre = false\n  if (flush === 'post') {\n    baseWatchOptions.scheduler = job => {\n      queuePostRenderEffect(job, instance && instance.suspense)\n    }\n  } else if (flush !== 'sync') {\n    // default: 'pre'\n    isPre = true\n    baseWatchOptions.scheduler = (job, isFirstRun) => {\n      if (isFirstRun) {\n        job()\n      } else {\n        queueJob(job)\n      }\n    }\n  }\n\n  baseWatchOptions.augmentJob = (job: SchedulerJob) => {\n    // important: mark the job as a watcher callback so that scheduler knows\n    // it is allowed to self-trigger (#1727)\n    if (cb) {\n      job.flags! |= SchedulerJobFlags.ALLOW_RECURSE\n    }\n    if (isPre) {\n      job.flags! |= SchedulerJobFlags.PRE\n      if (instance) {\n        job.id = instance.uid\n        ;(job as SchedulerJob).i = instance\n      }\n    }\n  }\n\n  const watchHandle = baseWatch(source, cb, baseWatchOptions)\n\n  if (__SSR__ && isInSSRComponentSetup) {\n    if (ssrCleanup) {\n      ssrCleanup.push(watchHandle)\n    } else if (runsImmediately) {\n      watchHandle()\n    }\n  }\n\n  return watchHandle\n}\n\n// this.$watch\nexport function instanceWatch(\n  this: ComponentInternalInstance,\n  source: string | Function,\n  value: WatchCallback | ObjectWatchOptionItem,\n  options?: WatchOptions,\n): WatchHandle {\n  const publicThis = this.proxy\n  const getter = isString(source)\n    ? source.includes('.')\n      ? createPathGetter(publicThis!, source)\n      : () => publicThis![source as keyof typeof publicThis]\n    : source.bind(publicThis, publicThis)\n  let cb\n  if (isFunction(value)) {\n    cb = value\n  } else {\n    cb = value.handler as Function\n    options = value\n  }\n  const reset = setCurrentInstance(this)\n  const res = doWatch(getter, cb.bind(publicThis), options)\n  reset()\n  return res\n}\n\nexport function createPathGetter(\n  ctx: ComponentPublicInstance,\n  path: string,\n): () => WatchSource | WatchSource[] | WatchEffect | object {\n  const segments = path.split('.')\n  return (): WatchSource | WatchSource[] | WatchEffect | object => {\n    let cur = ctx\n    for (let i = 0; i < segments.length && cur; i++) {\n      cur = cur[segments[i] as keyof typeof cur]\n    }\n    return cur\n  }\n}\n"
  },
  {
    "path": "packages/runtime-core/src/compat/attrsFallthrough.ts",
    "content": "import { isOn } from '@vue/shared'\nimport type { ComponentInternalInstance } from '../component'\nimport { DeprecationTypes, isCompatEnabled } from './compatConfig'\n\nexport function shouldSkipAttr(\n  key: string,\n  instance: ComponentInternalInstance,\n): boolean {\n  if (key === 'is') {\n    return true\n  }\n  if (\n    (key === 'class' || key === 'style') &&\n    isCompatEnabled(DeprecationTypes.INSTANCE_ATTRS_CLASS_STYLE, instance)\n  ) {\n    return true\n  }\n  if (\n    isOn(key) &&\n    isCompatEnabled(DeprecationTypes.INSTANCE_LISTENERS, instance)\n  ) {\n    return true\n  }\n  // vue-router\n  if (key.startsWith('routerView') || key === 'registerRouteInstance') {\n    return true\n  }\n  return false\n}\n"
  },
  {
    "path": "packages/runtime-core/src/compat/compatConfig.ts",
    "content": "import { extend, hasOwn, isArray, isFunction } from '@vue/shared'\nimport {\n  type Component,\n  type ComponentInternalInstance,\n  type ComponentOptions,\n  formatComponentName,\n  getComponentName,\n  getCurrentInstance,\n  isRuntimeOnly,\n} from '../component'\nimport { warn } from '../warning'\n\nexport enum DeprecationTypes {\n  GLOBAL_MOUNT = 'GLOBAL_MOUNT',\n  GLOBAL_MOUNT_CONTAINER = 'GLOBAL_MOUNT_CONTAINER',\n  GLOBAL_EXTEND = 'GLOBAL_EXTEND',\n  GLOBAL_PROTOTYPE = 'GLOBAL_PROTOTYPE',\n  GLOBAL_SET = 'GLOBAL_SET',\n  GLOBAL_DELETE = 'GLOBAL_DELETE',\n  GLOBAL_OBSERVABLE = 'GLOBAL_OBSERVABLE',\n  GLOBAL_PRIVATE_UTIL = 'GLOBAL_PRIVATE_UTIL',\n\n  CONFIG_SILENT = 'CONFIG_SILENT',\n  CONFIG_DEVTOOLS = 'CONFIG_DEVTOOLS',\n  CONFIG_KEY_CODES = 'CONFIG_KEY_CODES',\n  CONFIG_PRODUCTION_TIP = 'CONFIG_PRODUCTION_TIP',\n  CONFIG_IGNORED_ELEMENTS = 'CONFIG_IGNORED_ELEMENTS',\n  CONFIG_WHITESPACE = 'CONFIG_WHITESPACE',\n  CONFIG_OPTION_MERGE_STRATS = 'CONFIG_OPTION_MERGE_STRATS',\n\n  INSTANCE_SET = 'INSTANCE_SET',\n  INSTANCE_DELETE = 'INSTANCE_DELETE',\n  INSTANCE_DESTROY = 'INSTANCE_DESTROY',\n  INSTANCE_EVENT_EMITTER = 'INSTANCE_EVENT_EMITTER',\n  INSTANCE_EVENT_HOOKS = 'INSTANCE_EVENT_HOOKS',\n  INSTANCE_CHILDREN = 'INSTANCE_CHILDREN',\n  INSTANCE_LISTENERS = 'INSTANCE_LISTENERS',\n  INSTANCE_SCOPED_SLOTS = 'INSTANCE_SCOPED_SLOTS',\n  INSTANCE_ATTRS_CLASS_STYLE = 'INSTANCE_ATTRS_CLASS_STYLE',\n\n  OPTIONS_DATA_FN = 'OPTIONS_DATA_FN',\n  OPTIONS_DATA_MERGE = 'OPTIONS_DATA_MERGE',\n  OPTIONS_BEFORE_DESTROY = 'OPTIONS_BEFORE_DESTROY',\n  OPTIONS_DESTROYED = 'OPTIONS_DESTROYED',\n\n  WATCH_ARRAY = 'WATCH_ARRAY',\n  PROPS_DEFAULT_THIS = 'PROPS_DEFAULT_THIS',\n\n  V_ON_KEYCODE_MODIFIER = 'V_ON_KEYCODE_MODIFIER',\n  CUSTOM_DIR = 'CUSTOM_DIR',\n\n  ATTR_FALSE_VALUE = 'ATTR_FALSE_VALUE',\n  ATTR_ENUMERATED_COERCION = 'ATTR_ENUMERATED_COERCION',\n\n  TRANSITION_CLASSES = 'TRANSITION_CLASSES',\n  TRANSITION_GROUP_ROOT = 'TRANSITION_GROUP_ROOT',\n\n  COMPONENT_ASYNC = 'COMPONENT_ASYNC',\n  COMPONENT_FUNCTIONAL = 'COMPONENT_FUNCTIONAL',\n  COMPONENT_V_MODEL = 'COMPONENT_V_MODEL',\n\n  RENDER_FUNCTION = 'RENDER_FUNCTION',\n\n  FILTERS = 'FILTERS',\n\n  PRIVATE_APIS = 'PRIVATE_APIS',\n}\n\ntype DeprecationData = {\n  message: string | ((...args: any[]) => string)\n  link?: string\n}\n\nexport const deprecationData: Record<DeprecationTypes, DeprecationData> = {\n  [DeprecationTypes.GLOBAL_MOUNT]: {\n    message:\n      `The global app bootstrapping API has changed: vm.$mount() and the \"el\" ` +\n      `option have been removed. Use createApp(RootComponent).mount() instead.`,\n    link: `https://v3-migration.vuejs.org/breaking-changes/global-api.html#mounting-app-instance`,\n  },\n\n  [DeprecationTypes.GLOBAL_MOUNT_CONTAINER]: {\n    message:\n      `Vue detected directives on the mount container. ` +\n      `In Vue 3, the container is no longer considered part of the template ` +\n      `and will not be processed/replaced.`,\n    link: `https://v3-migration.vuejs.org/breaking-changes/mount-changes.html`,\n  },\n\n  [DeprecationTypes.GLOBAL_EXTEND]: {\n    message:\n      `Vue.extend() has been removed in Vue 3. ` +\n      `Use defineComponent() instead.`,\n    link: `https://vuejs.org/api/general.html#definecomponent`,\n  },\n\n  [DeprecationTypes.GLOBAL_PROTOTYPE]: {\n    message:\n      `Vue.prototype is no longer available in Vue 3. ` +\n      `Use app.config.globalProperties instead.`,\n    link: `https://v3-migration.vuejs.org/breaking-changes/global-api.html#vue-prototype-replaced-by-config-globalproperties`,\n  },\n\n  [DeprecationTypes.GLOBAL_SET]: {\n    message:\n      `Vue.set() has been removed as it is no longer needed in Vue 3. ` +\n      `Simply use native JavaScript mutations.`,\n  },\n\n  [DeprecationTypes.GLOBAL_DELETE]: {\n    message:\n      `Vue.delete() has been removed as it is no longer needed in Vue 3. ` +\n      `Simply use native JavaScript mutations.`,\n  },\n\n  [DeprecationTypes.GLOBAL_OBSERVABLE]: {\n    message:\n      `Vue.observable() has been removed. ` +\n      `Use \\`import { reactive } from \"vue\"\\` from Composition API instead.`,\n    link: `https://vuejs.org/api/reactivity-core.html#reactive`,\n  },\n\n  [DeprecationTypes.GLOBAL_PRIVATE_UTIL]: {\n    message:\n      `Vue.util has been removed. Please refactor to avoid its usage ` +\n      `since it was an internal API even in Vue 2.`,\n  },\n\n  [DeprecationTypes.CONFIG_SILENT]: {\n    message:\n      `config.silent has been removed because it is not good practice to ` +\n      `intentionally suppress warnings. You can use your browser console's ` +\n      `filter features to focus on relevant messages.`,\n  },\n\n  [DeprecationTypes.CONFIG_DEVTOOLS]: {\n    message:\n      `config.devtools has been removed. To enable devtools for ` +\n      `production, configure the __VUE_PROD_DEVTOOLS__ compile-time flag.`,\n    link: `https://github.com/vuejs/core/tree/main/packages/vue#bundler-build-feature-flags`,\n  },\n\n  [DeprecationTypes.CONFIG_KEY_CODES]: {\n    message:\n      `config.keyCodes has been removed. ` +\n      `In Vue 3, you can directly use the kebab-case key names as v-on modifiers.`,\n    link: `https://v3-migration.vuejs.org/breaking-changes/keycode-modifiers.html`,\n  },\n\n  [DeprecationTypes.CONFIG_PRODUCTION_TIP]: {\n    message: `config.productionTip has been removed.`,\n    link: `https://v3-migration.vuejs.org/breaking-changes/global-api.html#config-productiontip-removed`,\n  },\n\n  [DeprecationTypes.CONFIG_IGNORED_ELEMENTS]: {\n    message: () => {\n      let msg = `config.ignoredElements has been removed.`\n      if (isRuntimeOnly()) {\n        msg += ` Pass the \"isCustomElement\" option to @vue/compiler-dom instead.`\n      } else {\n        msg += ` Use config.isCustomElement instead.`\n      }\n      return msg\n    },\n    link: `https://v3-migration.vuejs.org/breaking-changes/global-api.html#config-ignoredelements-is-now-config-iscustomelement`,\n  },\n\n  [DeprecationTypes.CONFIG_WHITESPACE]: {\n    // this warning is only relevant in the full build when using runtime\n    // compilation, so it's put in the runtime compatConfig list.\n    message:\n      `Vue 3 compiler's whitespace option will default to \"condense\" instead of ` +\n      `\"preserve\". To suppress this warning, provide an explicit value for ` +\n      `\\`config.compilerOptions.whitespace\\`.`,\n  },\n\n  [DeprecationTypes.CONFIG_OPTION_MERGE_STRATS]: {\n    message:\n      `config.optionMergeStrategies no longer exposes internal strategies. ` +\n      `Use custom merge functions instead.`,\n  },\n\n  [DeprecationTypes.INSTANCE_SET]: {\n    message:\n      `vm.$set() has been removed as it is no longer needed in Vue 3. ` +\n      `Simply use native JavaScript mutations.`,\n  },\n\n  [DeprecationTypes.INSTANCE_DELETE]: {\n    message:\n      `vm.$delete() has been removed as it is no longer needed in Vue 3. ` +\n      `Simply use native JavaScript mutations.`,\n  },\n\n  [DeprecationTypes.INSTANCE_DESTROY]: {\n    message: `vm.$destroy() has been removed. Use app.unmount() instead.`,\n    link: `https://vuejs.org/api/application.html#app-unmount`,\n  },\n\n  [DeprecationTypes.INSTANCE_EVENT_EMITTER]: {\n    message:\n      `vm.$on/$once/$off() have been removed. ` +\n      `Use an external event emitter library instead.`,\n    link: `https://v3-migration.vuejs.org/breaking-changes/events-api.html`,\n  },\n\n  [DeprecationTypes.INSTANCE_EVENT_HOOKS]: {\n    message: event =>\n      `\"${event}\" lifecycle events are no longer supported. From templates, ` +\n      `use the \"vue:\" prefix instead of \"hook:\". For example, @${event} ` +\n      `should be changed to @vue:${event.slice(5)}. ` +\n      `From JavaScript, use Composition API to dynamically register lifecycle ` +\n      `hooks.`,\n    link: `https://v3-migration.vuejs.org/breaking-changes/vnode-lifecycle-events.html`,\n  },\n\n  [DeprecationTypes.INSTANCE_CHILDREN]: {\n    message:\n      `vm.$children has been removed. Consider refactoring your logic ` +\n      `to avoid relying on direct access to child components.`,\n    link: `https://v3-migration.vuejs.org/breaking-changes/children.html`,\n  },\n\n  [DeprecationTypes.INSTANCE_LISTENERS]: {\n    message:\n      `vm.$listeners has been removed. In Vue 3, parent v-on listeners are ` +\n      `included in vm.$attrs and it is no longer necessary to separately use ` +\n      `v-on=\"$listeners\" if you are already using v-bind=\"$attrs\". ` +\n      `(Note: the Vue 3 behavior only applies if this compat config is disabled)`,\n    link: `https://v3-migration.vuejs.org/breaking-changes/listeners-removed.html`,\n  },\n\n  [DeprecationTypes.INSTANCE_SCOPED_SLOTS]: {\n    message: `vm.$scopedSlots has been removed. Use vm.$slots instead.`,\n    link: `https://v3-migration.vuejs.org/breaking-changes/slots-unification.html`,\n  },\n\n  [DeprecationTypes.INSTANCE_ATTRS_CLASS_STYLE]: {\n    message: componentName =>\n      `Component <${\n        componentName || 'Anonymous'\n      }> has \\`inheritAttrs: false\\` but is ` +\n      `relying on class/style fallthrough from parent. In Vue 3, class/style ` +\n      `are now included in $attrs and will no longer fallthrough when ` +\n      `inheritAttrs is false. If you are already using v-bind=\"$attrs\" on ` +\n      `component root it should render the same end result. ` +\n      `If you are binding $attrs to a non-root element and expecting ` +\n      `class/style to fallthrough on root, you will need to now manually bind ` +\n      `them on root via :class=\"$attrs.class\".`,\n    link: `https://v3-migration.vuejs.org/breaking-changes/attrs-includes-class-style.html`,\n  },\n\n  [DeprecationTypes.OPTIONS_DATA_FN]: {\n    message:\n      `The \"data\" option can no longer be a plain object. ` +\n      `Always use a function.`,\n    link: `https://v3-migration.vuejs.org/breaking-changes/data-option.html`,\n  },\n\n  [DeprecationTypes.OPTIONS_DATA_MERGE]: {\n    message: (key: string) =>\n      `Detected conflicting key \"${key}\" when merging data option values. ` +\n      `In Vue 3, data keys are merged shallowly and will override one another.`,\n    link: `https://v3-migration.vuejs.org/breaking-changes/data-option.html#mixin-merge-behavior-change`,\n  },\n\n  [DeprecationTypes.OPTIONS_BEFORE_DESTROY]: {\n    message: `\\`beforeDestroy\\` has been renamed to \\`beforeUnmount\\`.`,\n  },\n\n  [DeprecationTypes.OPTIONS_DESTROYED]: {\n    message: `\\`destroyed\\` has been renamed to \\`unmounted\\`.`,\n  },\n\n  [DeprecationTypes.WATCH_ARRAY]: {\n    message:\n      `\"watch\" option or vm.$watch on an array value will no longer ` +\n      `trigger on array mutation unless the \"deep\" option is specified. ` +\n      `If current usage is intended, you can disable the compat behavior and ` +\n      `suppress this warning with:` +\n      `\\n\\n  configureCompat({ ${DeprecationTypes.WATCH_ARRAY}: false })\\n`,\n    link: `https://v3-migration.vuejs.org/breaking-changes/watch.html`,\n  },\n\n  [DeprecationTypes.PROPS_DEFAULT_THIS]: {\n    message: (key: string) =>\n      `props default value function no longer has access to \"this\". The compat ` +\n      `build only offers access to this.$options.` +\n      `(found in prop \"${key}\")`,\n    link: `https://v3-migration.vuejs.org/breaking-changes/props-default-this.html`,\n  },\n\n  [DeprecationTypes.CUSTOM_DIR]: {\n    message: (legacyHook: string, newHook: string) =>\n      `Custom directive hook \"${legacyHook}\" has been removed. ` +\n      `Use \"${newHook}\" instead.`,\n    link: `https://v3-migration.vuejs.org/breaking-changes/custom-directives.html`,\n  },\n\n  [DeprecationTypes.V_ON_KEYCODE_MODIFIER]: {\n    message:\n      `Using keyCode as v-on modifier is no longer supported. ` +\n      `Use kebab-case key name modifiers instead.`,\n    link: `https://v3-migration.vuejs.org/breaking-changes/keycode-modifiers.html`,\n  },\n\n  [DeprecationTypes.ATTR_FALSE_VALUE]: {\n    message: (name: string) =>\n      `Attribute \"${name}\" with v-bind value \\`false\\` will render ` +\n      `${name}=\"false\" instead of removing it in Vue 3. To remove the attribute, ` +\n      `use \\`null\\` or \\`undefined\\` instead. If the usage is intended, ` +\n      `you can disable the compat behavior and suppress this warning with:` +\n      `\\n\\n  configureCompat({ ${DeprecationTypes.ATTR_FALSE_VALUE}: false })\\n`,\n    link: `https://v3-migration.vuejs.org/breaking-changes/attribute-coercion.html`,\n  },\n\n  [DeprecationTypes.ATTR_ENUMERATED_COERCION]: {\n    message: (name: string, value: any, coerced: string) =>\n      `Enumerated attribute \"${name}\" with v-bind value \\`${value}\\` will ` +\n      `${\n        value === null ? `be removed` : `render the value as-is`\n      } instead of coercing the value to \"${coerced}\" in Vue 3. ` +\n      `Always use explicit \"true\" or \"false\" values for enumerated attributes. ` +\n      `If the usage is intended, ` +\n      `you can disable the compat behavior and suppress this warning with:` +\n      `\\n\\n  configureCompat({ ${DeprecationTypes.ATTR_ENUMERATED_COERCION}: false })\\n`,\n    link: `https://v3-migration.vuejs.org/breaking-changes/attribute-coercion.html`,\n  },\n\n  [DeprecationTypes.TRANSITION_CLASSES]: {\n    message: ``, // this feature cannot be runtime-detected\n  },\n\n  [DeprecationTypes.TRANSITION_GROUP_ROOT]: {\n    message:\n      `<TransitionGroup> no longer renders a root <span> element by ` +\n      `default if no \"tag\" prop is specified. If you do not rely on the span ` +\n      `for styling, you can disable the compat behavior and suppress this ` +\n      `warning with:` +\n      `\\n\\n  configureCompat({ ${DeprecationTypes.TRANSITION_GROUP_ROOT}: false })\\n`,\n    link: `https://v3-migration.vuejs.org/breaking-changes/transition-group.html`,\n  },\n\n  [DeprecationTypes.COMPONENT_ASYNC]: {\n    message: (comp: any) => {\n      const name = getComponentName(comp)\n      return (\n        `Async component${\n          name ? ` <${name}>` : `s`\n        } should be explicitly created via \\`defineAsyncComponent()\\` ` +\n        `in Vue 3. Plain functions will be treated as functional components in ` +\n        `non-compat build. If you have already migrated all async component ` +\n        `usage and intend to use plain functions for functional components, ` +\n        `you can disable the compat behavior and suppress this ` +\n        `warning with:` +\n        `\\n\\n  configureCompat({ ${DeprecationTypes.COMPONENT_ASYNC}: false })\\n`\n      )\n    },\n    link: `https://v3-migration.vuejs.org/breaking-changes/async-components.html`,\n  },\n\n  [DeprecationTypes.COMPONENT_FUNCTIONAL]: {\n    message: (comp: any) => {\n      const name = getComponentName(comp)\n      return (\n        `Functional component${\n          name ? ` <${name}>` : `s`\n        } should be defined as a plain function in Vue 3. The \"functional\" ` +\n        `option has been removed. NOTE: Before migrating to use plain ` +\n        `functions for functional components, first make sure that all async ` +\n        `components usage have been migrated and its compat behavior has ` +\n        `been disabled.`\n      )\n    },\n    link: `https://v3-migration.vuejs.org/breaking-changes/functional-components.html`,\n  },\n\n  [DeprecationTypes.COMPONENT_V_MODEL]: {\n    message: (comp: ComponentOptions) => {\n      const configMsg =\n        `opt-in to ` +\n        `Vue 3 behavior on a per-component basis with \\`compatConfig: { ${DeprecationTypes.COMPONENT_V_MODEL}: false }\\`.`\n      if (\n        comp.props &&\n        (isArray(comp.props)\n          ? comp.props.includes('modelValue')\n          : hasOwn(comp.props, 'modelValue'))\n      ) {\n        return (\n          `Component declares \"modelValue\" prop, which is Vue 3 usage, but ` +\n          `is running under Vue 2 compat v-model behavior. You can ${configMsg}`\n        )\n      }\n      return (\n        `v-model usage on component has changed in Vue 3. Component that expects ` +\n        `to work with v-model should now use the \"modelValue\" prop and emit the ` +\n        `\"update:modelValue\" event. You can update the usage and then ${configMsg}`\n      )\n    },\n    link: `https://v3-migration.vuejs.org/breaking-changes/v-model.html`,\n  },\n\n  [DeprecationTypes.RENDER_FUNCTION]: {\n    message:\n      `Vue 3's render function API has changed. ` +\n      `You can opt-in to the new API with:` +\n      `\\n\\n  configureCompat({ ${DeprecationTypes.RENDER_FUNCTION}: false })\\n` +\n      `\\n  (This can also be done per-component via the \"compatConfig\" option.)`,\n    link: `https://v3-migration.vuejs.org/breaking-changes/render-function-api.html`,\n  },\n\n  [DeprecationTypes.FILTERS]: {\n    message:\n      `filters have been removed in Vue 3. ` +\n      `The \"|\" symbol will be treated as native JavaScript bitwise OR operator. ` +\n      `Use method calls or computed properties instead.`,\n    link: `https://v3-migration.vuejs.org/breaking-changes/filters.html`,\n  },\n\n  [DeprecationTypes.PRIVATE_APIS]: {\n    message: name =>\n      `\"${name}\" is a Vue 2 private API that no longer exists in Vue 3. ` +\n      `If you are seeing this warning only due to a dependency, you can ` +\n      `suppress this warning via { PRIVATE_APIS: 'suppress-warning' }.`,\n  },\n}\n\nconst instanceWarned: Record<string, true> = Object.create(null)\nconst warnCount: Record<string, number> = Object.create(null)\n\n// test only\nlet warningEnabled = true\n\nexport function toggleDeprecationWarning(flag: boolean): void {\n  warningEnabled = flag\n}\n\nexport function warnDeprecation(\n  key: DeprecationTypes,\n  instance: ComponentInternalInstance | null,\n  ...args: any[]\n): void {\n  if (!__DEV__) {\n    return\n  }\n  if (__TEST__ && !warningEnabled) {\n    return\n  }\n\n  instance = instance || getCurrentInstance()\n\n  // check user config\n  const config = getCompatConfigForKey(key, instance)\n  if (config === 'suppress-warning') {\n    return\n  }\n\n  const dupKey = key + args.join('')\n  let compId: string | number | null =\n    instance && formatComponentName(instance, instance.type)\n  if (compId === 'Anonymous' && instance) {\n    compId = instance.uid\n  }\n\n  // skip if the same warning is emitted for the same component type\n  const componentDupKey = dupKey + compId\n  if (!__TEST__ && componentDupKey in instanceWarned) {\n    return\n  }\n  instanceWarned[componentDupKey] = true\n\n  // same warning, but different component. skip the long message and just\n  // log the key and count.\n  if (!__TEST__ && dupKey in warnCount) {\n    warn(`(deprecation ${key}) (${++warnCount[dupKey] + 1})`)\n    return\n  }\n\n  warnCount[dupKey] = 0\n\n  const { message, link } = deprecationData[key]\n  warn(\n    `(deprecation ${key}) ${\n      typeof message === 'function' ? message(...args) : message\n    }${link ? `\\n  Details: ${link}` : ``}`,\n  )\n  if (!isCompatEnabled(key, instance, true)) {\n    console.error(\n      `^ The above deprecation's compat behavior is disabled and will likely ` +\n        `lead to runtime errors.`,\n    )\n  }\n}\n\nexport type CompatConfig = Partial<\n  Record<DeprecationTypes, boolean | 'suppress-warning'>\n> & {\n  MODE?: 2 | 3 | ((comp: Component | null) => 2 | 3)\n}\n\nexport const globalCompatConfig: CompatConfig = {\n  MODE: 2,\n}\n\nexport function configureCompat(config: CompatConfig): void {\n  if (__DEV__) {\n    validateCompatConfig(config)\n  }\n  extend(globalCompatConfig, config)\n}\n\nconst seenConfigObjects = /*@__PURE__*/ new WeakSet<CompatConfig>()\nconst warnedInvalidKeys: Record<string, boolean> = {}\n\n// dev only\nexport function validateCompatConfig(\n  config: CompatConfig,\n  instance?: ComponentInternalInstance,\n): void {\n  if (seenConfigObjects.has(config)) {\n    return\n  }\n  seenConfigObjects.add(config)\n\n  for (const key of Object.keys(config)) {\n    if (\n      key !== 'MODE' &&\n      !(key in deprecationData) &&\n      !(key in warnedInvalidKeys)\n    ) {\n      if (key.startsWith('COMPILER_')) {\n        if (isRuntimeOnly()) {\n          warn(\n            `Deprecation config \"${key}\" is compiler-specific and you are ` +\n              `running a runtime-only build of Vue. This deprecation should be ` +\n              `configured via compiler options in your build setup instead.\\n` +\n              `Details: https://v3-migration.vuejs.org/breaking-changes/migration-build.html`,\n          )\n        }\n      } else {\n        warn(`Invalid deprecation config \"${key}\".`)\n      }\n      warnedInvalidKeys[key] = true\n    }\n  }\n\n  if (instance && config[DeprecationTypes.OPTIONS_DATA_MERGE] != null) {\n    warn(\n      `Deprecation config \"${DeprecationTypes.OPTIONS_DATA_MERGE}\" can only be configured globally.`,\n    )\n  }\n}\n\nexport function getCompatConfigForKey(\n  key: DeprecationTypes | 'MODE',\n  instance: ComponentInternalInstance | null,\n): CompatConfig[DeprecationTypes | 'MODE'] {\n  const instanceConfig =\n    instance && (instance.type as ComponentOptions).compatConfig\n  if (instanceConfig && key in instanceConfig) {\n    return instanceConfig[key]\n  }\n  return globalCompatConfig[key]\n}\n\nexport function isCompatEnabled(\n  key: DeprecationTypes,\n  instance: ComponentInternalInstance | null,\n  enableForBuiltIn = false,\n): boolean {\n  // skip compat for built-in components\n  if (!enableForBuiltIn && instance && instance.type.__isBuiltIn) {\n    return false\n  }\n\n  const rawMode = getCompatConfigForKey('MODE', instance) || 2\n  const val = getCompatConfigForKey(key, instance)\n\n  const mode = isFunction(rawMode)\n    ? rawMode(instance && instance.type)\n    : rawMode\n\n  if (mode === 2) {\n    return val !== false\n  } else {\n    return val === true || val === 'suppress-warning'\n  }\n}\n\n/**\n * Use this for features that are completely removed in non-compat build.\n */\nexport function assertCompatEnabled(\n  key: DeprecationTypes,\n  instance: ComponentInternalInstance | null,\n  ...args: any[]\n): void {\n  if (!isCompatEnabled(key, instance)) {\n    throw new Error(`${key} compat has been disabled.`)\n  } else if (__DEV__) {\n    warnDeprecation(key, instance, ...args)\n  }\n}\n\n/**\n * Use this for features where legacy usage is still possible, but will likely\n * lead to runtime error if compat is disabled. (warn in all cases)\n */\nexport function softAssertCompatEnabled(\n  key: DeprecationTypes,\n  instance: ComponentInternalInstance | null,\n  ...args: any[]\n): boolean {\n  if (__DEV__) {\n    warnDeprecation(key, instance, ...args)\n  }\n  return isCompatEnabled(key, instance)\n}\n\n/**\n * Use this for features with the same syntax but with mutually exclusive\n * behavior in 2 vs 3. Only warn if compat is enabled.\n * e.g. render function\n */\nexport function checkCompatEnabled(\n  key: DeprecationTypes,\n  instance: ComponentInternalInstance | null,\n  ...args: any[]\n): boolean {\n  const enabled = isCompatEnabled(key, instance)\n  if (__DEV__ && enabled) {\n    warnDeprecation(key, instance, ...args)\n  }\n  return enabled\n}\n\n// run tests in v3 mode by default\nif (__TEST__) {\n  configureCompat({\n    MODE: 3,\n  })\n}\n"
  },
  {
    "path": "packages/runtime-core/src/compat/component.ts",
    "content": "import { isFunction, isObject } from '@vue/shared'\nimport type { Component, ComponentInternalInstance } from '../component'\nimport {\n  DeprecationTypes,\n  checkCompatEnabled,\n  softAssertCompatEnabled,\n} from './compatConfig'\nimport { convertLegacyAsyncComponent } from './componentAsync'\nimport { convertLegacyFunctionalComponent } from './componentFunctional'\n\nexport function convertLegacyComponent(\n  comp: any,\n  instance: ComponentInternalInstance | null,\n): Component {\n  if (comp.__isBuiltIn) {\n    return comp\n  }\n\n  // 2.x constructor\n  if (isFunction(comp) && comp.cid) {\n    // #7766\n    if (comp.render) {\n      // only necessary when compiled from SFC\n      comp.options.render = comp.render\n    }\n    // copy over internal properties set by the SFC compiler\n    comp.options.__file = comp.__file\n    comp.options.__hmrId = comp.__hmrId\n    comp.options.__scopeId = comp.__scopeId\n    comp = comp.options\n  }\n\n  // 2.x async component\n  if (\n    isFunction(comp) &&\n    checkCompatEnabled(DeprecationTypes.COMPONENT_ASYNC, instance, comp)\n  ) {\n    // since after disabling this, plain functions are still valid usage, do not\n    // use softAssert here.\n    return convertLegacyAsyncComponent(comp)\n  }\n\n  // 2.x functional component\n  if (\n    isObject(comp) &&\n    comp.functional &&\n    softAssertCompatEnabled(\n      DeprecationTypes.COMPONENT_FUNCTIONAL,\n      instance,\n      comp,\n    )\n  ) {\n    return convertLegacyFunctionalComponent(comp)\n  }\n\n  return comp\n}\n"
  },
  {
    "path": "packages/runtime-core/src/compat/componentAsync.ts",
    "content": "import { isArray, isObject, isPromise } from '@vue/shared'\nimport { defineAsyncComponent } from '../apiAsyncComponent'\nimport type { Component } from '../component'\nimport { isVNode } from '../vnode'\n\ninterface LegacyAsyncOptions {\n  component: Promise<Component>\n  loading?: Component\n  error?: Component\n  delay?: number\n  timeout?: number\n}\n\ntype LegacyAsyncReturnValue = Promise<Component> | LegacyAsyncOptions\n\ntype LegacyAsyncComponent = (\n  resolve?: (res: LegacyAsyncReturnValue) => void,\n  reject?: (reason?: any) => void,\n) => LegacyAsyncReturnValue | undefined\n\nconst normalizedAsyncComponentMap = new WeakMap<\n  LegacyAsyncComponent,\n  Component\n>()\n\nexport function convertLegacyAsyncComponent(\n  comp: LegacyAsyncComponent,\n): Component {\n  if (normalizedAsyncComponentMap.has(comp)) {\n    return normalizedAsyncComponentMap.get(comp)!\n  }\n\n  // we have to call the function here due to how v2's API won't expose the\n  // options until we call it\n  let resolve: (res: LegacyAsyncReturnValue) => void\n  let reject: (reason?: any) => void\n  const fallbackPromise = new Promise<Component>((r, rj) => {\n    ;((resolve = r), (reject = rj))\n  })\n\n  const res = comp(resolve!, reject!)\n\n  let converted: Component\n  if (isPromise(res)) {\n    converted = defineAsyncComponent(() => res)\n  } else if (isObject(res) && !isVNode(res) && !isArray(res)) {\n    converted = defineAsyncComponent({\n      loader: () => res.component,\n      loadingComponent: res.loading,\n      errorComponent: res.error,\n      delay: res.delay,\n      timeout: res.timeout,\n    })\n  } else if (res == null) {\n    converted = defineAsyncComponent(() => fallbackPromise)\n  } else {\n    converted = comp as any // probably a v3 functional comp\n  }\n  normalizedAsyncComponentMap.set(comp, converted)\n  return converted\n}\n"
  },
  {
    "path": "packages/runtime-core/src/compat/componentFunctional.ts",
    "content": "import {\n  type ComponentOptions,\n  type FunctionalComponent,\n  getCurrentInstance,\n} from '../component'\nimport { resolveInjections } from '../componentOptions'\nimport type { InternalSlots } from '../componentSlots'\nimport { getCompatListeners } from './instanceListeners'\nimport { compatH } from './renderFn'\n\nconst normalizedFunctionalComponentMap = new WeakMap<\n  ComponentOptions,\n  FunctionalComponent\n>()\nexport const legacySlotProxyHandlers: ProxyHandler<InternalSlots> = {\n  get(target, key: string) {\n    const slot = target[key]\n    return slot && slot()\n  },\n}\n\nexport function convertLegacyFunctionalComponent(\n  comp: ComponentOptions,\n): FunctionalComponent {\n  if (normalizedFunctionalComponentMap.has(comp)) {\n    return normalizedFunctionalComponentMap.get(comp)!\n  }\n\n  const legacyFn = comp.render as any\n\n  const Func: FunctionalComponent = (props, ctx) => {\n    const instance = getCurrentInstance()!\n\n    const legacyCtx = {\n      props,\n      children: instance.vnode.children || [],\n      data: instance.vnode.props || {},\n      scopedSlots: ctx.slots,\n      parent: instance.parent && instance.parent.proxy,\n      slots() {\n        return new Proxy(ctx.slots, legacySlotProxyHandlers)\n      },\n      get listeners() {\n        return getCompatListeners(instance)\n      },\n      get injections() {\n        if (comp.inject) {\n          const injections = {}\n          resolveInjections(comp.inject, injections)\n          return injections\n        }\n        return {}\n      },\n    }\n    return legacyFn(compatH, legacyCtx)\n  }\n  Func.props = comp.props\n  Func.displayName = comp.name\n  Func.compatConfig = comp.compatConfig\n  // v2 functional components do not inherit attrs\n  Func.inheritAttrs = false\n\n  normalizedFunctionalComponentMap.set(comp, Func)\n  return Func\n}\n"
  },
  {
    "path": "packages/runtime-core/src/compat/componentVModel.ts",
    "content": "import { ShapeFlags, extend } from '@vue/shared'\nimport type { ComponentInternalInstance, ComponentOptions } from '../component'\nimport { createAppContext } from '../apiCreateApp'\nimport { ErrorCodes, callWithErrorHandling } from '../errorHandling'\nimport type { VNode } from '../vnode'\nimport { popWarningContext, pushWarningContext } from '../warning'\nimport {\n  DeprecationTypes,\n  isCompatEnabled,\n  warnDeprecation,\n} from './compatConfig'\n\nexport const compatModelEventPrefix = `onModelCompat:`\n\nconst warnedTypes = new WeakSet()\n\nexport function convertLegacyVModelProps(vnode: VNode): void {\n  const { type, shapeFlag, props, dynamicProps } = vnode\n  const comp = type as ComponentOptions\n  if (shapeFlag & ShapeFlags.COMPONENT && props && 'modelValue' in props) {\n    if (\n      !isCompatEnabled(\n        DeprecationTypes.COMPONENT_V_MODEL,\n        // this is a special case where we want to use the vnode component's\n        // compat config instead of the current rendering instance (which is the\n        // parent of the component that exposes v-model)\n        { type } as any,\n      )\n    ) {\n      return\n    }\n\n    if (__DEV__ && !warnedTypes.has(comp)) {\n      pushWarningContext(vnode)\n      warnDeprecation(\n        DeprecationTypes.COMPONENT_V_MODEL,\n        {\n          type,\n          appContext: (vnode.ctx && vnode.ctx.appContext) || createAppContext(),\n        } as any,\n        comp,\n      )\n      popWarningContext()\n      warnedTypes.add(comp)\n    }\n\n    // v3 compiled model code -> v2 compat props\n    // modelValue -> value\n    // onUpdate:modelValue -> onModelCompat:input\n    const model = comp.model || {}\n    applyModelFromMixins(model, comp.mixins)\n    const { prop = 'value', event = 'input' } = model\n    if (prop !== 'modelValue') {\n      props[prop] = props.modelValue\n      delete props.modelValue\n    }\n    // important: update dynamic props\n    if (dynamicProps) {\n      dynamicProps[dynamicProps.indexOf('modelValue')] = prop\n    }\n    props[compatModelEventPrefix + event] = props['onUpdate:modelValue']\n    delete props['onUpdate:modelValue']\n  }\n}\n\nfunction applyModelFromMixins(model: any, mixins?: ComponentOptions[]) {\n  if (mixins) {\n    mixins.forEach(m => {\n      if (m.model) extend(model, m.model)\n      if (m.mixins) applyModelFromMixins(model, m.mixins)\n    })\n  }\n}\n\nexport function compatModelEmit(\n  instance: ComponentInternalInstance,\n  event: string,\n  args: any[],\n): void {\n  if (!isCompatEnabled(DeprecationTypes.COMPONENT_V_MODEL, instance)) {\n    return\n  }\n  const props = instance.vnode.props\n  const modelHandler = props && props[compatModelEventPrefix + event]\n  if (modelHandler) {\n    callWithErrorHandling(\n      modelHandler,\n      instance,\n      ErrorCodes.COMPONENT_EVENT_HANDLER,\n      args,\n    )\n  }\n}\n"
  },
  {
    "path": "packages/runtime-core/src/compat/customDirective.ts",
    "content": "import { isArray } from '@vue/shared'\nimport type { ComponentInternalInstance } from '../component'\nimport type { DirectiveHook, ObjectDirective } from '../directives'\nimport { DeprecationTypes, softAssertCompatEnabled } from './compatConfig'\n\nexport interface LegacyDirective {\n  bind?: DirectiveHook\n  inserted?: DirectiveHook\n  update?: DirectiveHook\n  componentUpdated?: DirectiveHook\n  unbind?: DirectiveHook\n}\n\nconst legacyDirectiveHookMap: Partial<\n  Record<\n    keyof ObjectDirective,\n    keyof LegacyDirective | (keyof LegacyDirective)[]\n  >\n> = {\n  beforeMount: 'bind',\n  mounted: 'inserted',\n  updated: ['update', 'componentUpdated'],\n  unmounted: 'unbind',\n}\n\nexport function mapCompatDirectiveHook(\n  name: keyof ObjectDirective,\n  dir: ObjectDirective & LegacyDirective,\n  instance: ComponentInternalInstance | null,\n): DirectiveHook | DirectiveHook[] | undefined {\n  const mappedName = legacyDirectiveHookMap[name]\n  if (mappedName) {\n    if (isArray(mappedName)) {\n      const hook: DirectiveHook[] = []\n      mappedName.forEach(mapped => {\n        const mappedHook = dir[mapped]\n        if (mappedHook) {\n          softAssertCompatEnabled(\n            DeprecationTypes.CUSTOM_DIR,\n            instance,\n            mapped,\n            name,\n          )\n          hook.push(mappedHook)\n        }\n      })\n      return hook.length ? hook : undefined\n    } else {\n      if (dir[mappedName]) {\n        softAssertCompatEnabled(\n          DeprecationTypes.CUSTOM_DIR,\n          instance,\n          mappedName,\n          name,\n        )\n      }\n      return dir[mappedName]\n    }\n  }\n}\n"
  },
  {
    "path": "packages/runtime-core/src/compat/data.ts",
    "content": "import { isPlainObject } from '@vue/shared'\nimport { DeprecationTypes, warnDeprecation } from './compatConfig'\n\nexport function deepMergeData(to: any, from: any): any {\n  for (const key in from) {\n    const toVal = to[key]\n    const fromVal = from[key]\n    if (key in to && isPlainObject(toVal) && isPlainObject(fromVal)) {\n      __DEV__ && warnDeprecation(DeprecationTypes.OPTIONS_DATA_MERGE, null, key)\n      deepMergeData(toVal, fromVal)\n    } else {\n      to[key] = fromVal\n    }\n  }\n  return to\n}\n"
  },
  {
    "path": "packages/runtime-core/src/compat/global.ts",
    "content": "import {\n  TrackOpTypes,\n  TriggerOpTypes,\n  isReactive,\n  reactive,\n  track,\n  trigger,\n} from '@vue/reactivity'\nimport {\n  NOOP,\n  extend,\n  invokeArrayFns,\n  isArray,\n  isFunction,\n  isObject,\n  isString,\n} from '@vue/shared'\nimport { warn } from '../warning'\nimport { cloneVNode, createVNode } from '../vnode'\nimport type { ElementNamespace, RootRenderFunction } from '../renderer'\nimport type {\n  App,\n  AppConfig,\n  AppContext,\n  CreateAppFunction,\n  Plugin,\n} from '../apiCreateApp'\nimport {\n  type Component,\n  type ComponentOptions,\n  createComponentInstance,\n  finishComponentSetup,\n  isRuntimeOnly,\n  setupComponent,\n} from '../component'\nimport {\n  type RenderFunction,\n  internalOptionMergeStrats,\n  mergeOptions,\n} from '../componentOptions'\nimport type { ComponentPublicInstance } from '../componentPublicInstance'\nimport { devtoolsInitApp, devtoolsUnmountApp } from '../devtools'\nimport type { Directive } from '../directives'\nimport { nextTick } from '../scheduler'\nimport { version } from '..'\nimport {\n  type LegacyConfig,\n  installLegacyConfigWarnings,\n  installLegacyOptionMergeStrats,\n} from './globalConfig'\nimport type { LegacyDirective } from './customDirective'\nimport {\n  DeprecationTypes,\n  assertCompatEnabled,\n  configureCompat,\n  isCompatEnabled,\n  softAssertCompatEnabled,\n  warnDeprecation,\n} from './compatConfig'\nimport type { LegacyPublicInstance } from './instance'\n\n/**\n * @deprecated the default `Vue` export has been removed in Vue 3. The type for\n * the default export is provided only for migration purposes. Please use\n * named imports instead - e.g. `import { createApp } from 'vue'`.\n */\nexport type CompatVue = Pick<App, 'version' | 'component' | 'directive'> & {\n  configureCompat: typeof configureCompat\n\n  // no inference here since these types are not meant for actual use - they\n  // are merely here to provide type checks for internal implementation and\n  // information for migration.\n  new (options?: ComponentOptions): LegacyPublicInstance\n\n  version: string\n  config: AppConfig & LegacyConfig\n\n  nextTick: typeof nextTick\n\n  use<Options extends unknown[]>(\n    plugin: Plugin<Options>,\n    ...options: Options\n  ): CompatVue\n  use<Options>(plugin: Plugin<Options>, options: Options): CompatVue\n\n  mixin(mixin: ComponentOptions): CompatVue\n\n  component(name: string): Component | undefined\n  component(name: string, component: Component): CompatVue\n  directive<T = any, V = any>(name: string): Directive<T, V> | undefined\n  directive<T = any, V = any>(\n    name: string,\n    directive: Directive<T, V>,\n  ): CompatVue\n\n  compile(template: string): RenderFunction\n\n  /**\n   * @deprecated Vue 3 no longer supports extending constructors.\n   */\n  extend: (options?: ComponentOptions) => CompatVue\n  /**\n   * @deprecated Vue 3 no longer needs set() for adding new properties.\n   */\n  set(target: any, key: PropertyKey, value: any): void\n  /**\n   * @deprecated Vue 3 no longer needs delete() for property deletions.\n   */\n  delete(target: any, key: PropertyKey): void\n  /**\n   * @deprecated use `reactive` instead.\n   */\n  observable: typeof reactive\n  /**\n   * @deprecated filters have been removed from Vue 3.\n   */\n  filter(name: string, arg?: any): null\n  /**\n   * @internal\n   */\n  cid: number\n  /**\n   * @internal\n   */\n  options: ComponentOptions\n  /**\n   * @internal\n   */\n  util: any\n  /**\n   * @internal\n   */\n  super: CompatVue\n}\n\nexport let isCopyingConfig = false\n\n// exported only for test\nexport let singletonApp: App\nlet singletonCtor: CompatVue\n\n// Legacy global Vue constructor\nexport function createCompatVue(\n  createApp: CreateAppFunction<Element>,\n  createSingletonApp: CreateAppFunction<Element>,\n): CompatVue {\n  singletonApp = createSingletonApp({})\n\n  const Vue: CompatVue = (singletonCtor = function Vue(\n    options: ComponentOptions = {},\n  ) {\n    return createCompatApp(options, Vue)\n  } as any)\n\n  function createCompatApp(options: ComponentOptions = {}, Ctor: any) {\n    assertCompatEnabled(DeprecationTypes.GLOBAL_MOUNT, null)\n\n    const { data } = options\n    if (\n      data &&\n      !isFunction(data) &&\n      softAssertCompatEnabled(DeprecationTypes.OPTIONS_DATA_FN, null)\n    ) {\n      options.data = () => data\n    }\n\n    const app = createApp(options)\n\n    if (Ctor !== Vue) {\n      applySingletonPrototype(app, Ctor)\n    }\n\n    const vm = app._createRoot!(options)\n    if (options.el) {\n      return (vm as any).$mount(options.el)\n    } else {\n      return vm\n    }\n  }\n\n  Vue.version = `2.6.14-compat:${__VERSION__}`\n  Vue.config = singletonApp.config\n\n  Vue.use = (plugin: Plugin, ...options: any[]) => {\n    if (plugin && isFunction(plugin.install)) {\n      plugin.install(Vue as any, ...options)\n    } else if (isFunction(plugin)) {\n      plugin(Vue as any, ...options)\n    }\n    return Vue\n  }\n\n  Vue.mixin = m => {\n    singletonApp.mixin(m)\n    return Vue\n  }\n\n  Vue.component = ((name: string, comp: Component) => {\n    if (comp) {\n      singletonApp.component(name, comp)\n      return Vue\n    } else {\n      return singletonApp.component(name)\n    }\n  }) as any\n\n  Vue.directive = ((name: string, dir: Directive | LegacyDirective) => {\n    if (dir) {\n      singletonApp.directive(name, dir as Directive)\n      return Vue\n    } else {\n      return singletonApp.directive(name)\n    }\n  }) as any\n\n  Vue.options = { _base: Vue }\n\n  let cid = 1\n  Vue.cid = cid\n\n  Vue.nextTick = nextTick\n\n  const extendCache = new WeakMap()\n\n  function extendCtor(this: any, extendOptions: ComponentOptions = {}) {\n    assertCompatEnabled(DeprecationTypes.GLOBAL_EXTEND, null)\n    if (isFunction(extendOptions)) {\n      extendOptions = extendOptions.options\n    }\n\n    if (extendCache.has(extendOptions)) {\n      return extendCache.get(extendOptions)\n    }\n\n    const Super = this\n    function SubVue(inlineOptions?: ComponentOptions) {\n      if (!inlineOptions) {\n        return createCompatApp(SubVue.options, SubVue)\n      } else {\n        return createCompatApp(\n          mergeOptions(\n            extend({}, SubVue.options),\n            inlineOptions,\n            internalOptionMergeStrats as any,\n          ),\n          SubVue,\n        )\n      }\n    }\n    SubVue.super = Super\n    SubVue.prototype = Object.create(Vue.prototype)\n    SubVue.prototype.constructor = SubVue\n\n    // clone non-primitive base option values for edge case of mutating\n    // extended options\n    const mergeBase: any = {}\n    for (const key in Super.options) {\n      const superValue = Super.options[key]\n      mergeBase[key] = isArray(superValue)\n        ? superValue.slice()\n        : isObject(superValue)\n          ? extend(Object.create(null), superValue)\n          : superValue\n    }\n\n    SubVue.options = mergeOptions(\n      mergeBase,\n      extendOptions,\n      internalOptionMergeStrats as any,\n    )\n\n    SubVue.options._base = SubVue\n    SubVue.extend = extendCtor.bind(SubVue)\n    SubVue.mixin = Super.mixin\n    SubVue.use = Super.use\n    SubVue.cid = ++cid\n\n    extendCache.set(extendOptions, SubVue)\n    return SubVue\n  }\n\n  Vue.extend = extendCtor.bind(Vue) as any\n\n  Vue.set = (target, key, value) => {\n    assertCompatEnabled(DeprecationTypes.GLOBAL_SET, null)\n    target[key] = value\n  }\n\n  Vue.delete = (target, key) => {\n    assertCompatEnabled(DeprecationTypes.GLOBAL_DELETE, null)\n    delete target[key]\n  }\n\n  Vue.observable = (target: any) => {\n    assertCompatEnabled(DeprecationTypes.GLOBAL_OBSERVABLE, null)\n    return reactive(target)\n  }\n\n  Vue.filter = ((name: string, filter?: any) => {\n    if (filter) {\n      singletonApp.filter!(name, filter)\n      return Vue\n    } else {\n      return singletonApp.filter!(name)\n    }\n  }) as any\n\n  // internal utils - these are technically internal but some plugins use it.\n  const util = {\n    warn: __DEV__ ? warn : NOOP,\n    extend,\n    mergeOptions: (parent: any, child: any, vm?: ComponentPublicInstance) =>\n      mergeOptions(\n        parent,\n        child,\n        vm ? undefined : (internalOptionMergeStrats as any),\n      ),\n    defineReactive,\n  }\n  Object.defineProperty(Vue, 'util', {\n    get() {\n      assertCompatEnabled(DeprecationTypes.GLOBAL_PRIVATE_UTIL, null)\n      return util\n    },\n  })\n\n  Vue.configureCompat = configureCompat\n\n  return Vue\n}\n\nexport function installAppCompatProperties(\n  app: App,\n  context: AppContext,\n  render: RootRenderFunction<any>,\n): void {\n  installFilterMethod(app, context)\n  installLegacyOptionMergeStrats(app.config)\n\n  if (!singletonApp) {\n    // this is the call of creating the singleton itself so the rest is\n    // unnecessary\n    return\n  }\n\n  installCompatMount(app, context, render)\n  installLegacyAPIs(app)\n  applySingletonAppMutations(app)\n  if (__DEV__) installLegacyConfigWarnings(app.config)\n}\n\nfunction installFilterMethod(app: App, context: AppContext) {\n  context.filters = {}\n  app.filter = (name: string, filter?: Function): any => {\n    assertCompatEnabled(DeprecationTypes.FILTERS, null)\n    if (!filter) {\n      return context.filters![name]\n    }\n    if (__DEV__ && context.filters![name]) {\n      warn(`Filter \"${name}\" has already been registered.`)\n    }\n    context.filters![name] = filter\n    return app\n  }\n}\n\nfunction installLegacyAPIs(app: App) {\n  // expose global API on app instance for legacy plugins\n  Object.defineProperties(app, {\n    // so that app.use() can work with legacy plugins that extend prototypes\n    prototype: {\n      get() {\n        __DEV__ && warnDeprecation(DeprecationTypes.GLOBAL_PROTOTYPE, null)\n        return app.config.globalProperties\n      },\n    },\n    nextTick: { value: nextTick },\n    extend: { value: singletonCtor.extend },\n    set: { value: singletonCtor.set },\n    delete: { value: singletonCtor.delete },\n    observable: { value: singletonCtor.observable },\n    util: {\n      get() {\n        return singletonCtor.util\n      },\n    },\n  })\n}\n\nfunction applySingletonAppMutations(app: App) {\n  // copy over asset registries and deopt flag\n  app._context.mixins = [...singletonApp._context.mixins]\n  ;['components', 'directives', 'filters'].forEach(key => {\n    // @ts-expect-error\n    app._context[key] = Object.create(singletonApp._context[key])\n  })\n\n  // copy over global config mutations\n  isCopyingConfig = true\n  for (const key in singletonApp.config) {\n    if (key === 'isNativeTag') continue\n    if (\n      isRuntimeOnly() &&\n      (key === 'isCustomElement' || key === 'compilerOptions')\n    ) {\n      continue\n    }\n    const val = singletonApp.config[key as keyof AppConfig]\n    // @ts-expect-error\n    app.config[key] = isObject(val) ? Object.create(val) : val\n\n    // compat for runtime ignoredElements -> isCustomElement\n    if (\n      key === 'ignoredElements' &&\n      isCompatEnabled(DeprecationTypes.CONFIG_IGNORED_ELEMENTS, null) &&\n      !isRuntimeOnly() &&\n      isArray(val)\n    ) {\n      app.config.compilerOptions.isCustomElement = tag => {\n        return val.some(v => (isString(v) ? v === tag : v.test(tag)))\n      }\n    }\n  }\n  isCopyingConfig = false\n  applySingletonPrototype(app, singletonCtor)\n}\n\nfunction applySingletonPrototype(app: App, Ctor: Function) {\n  // copy prototype augmentations as config.globalProperties\n  const enabled = isCompatEnabled(DeprecationTypes.GLOBAL_PROTOTYPE, null)\n  if (enabled) {\n    app.config.globalProperties = Object.create(Ctor.prototype)\n  }\n  let hasPrototypeAugmentations = false\n  for (const key of Object.getOwnPropertyNames(Ctor.prototype)) {\n    if (key !== 'constructor') {\n      hasPrototypeAugmentations = true\n      if (enabled) {\n        Object.defineProperty(\n          app.config.globalProperties,\n          key,\n          Object.getOwnPropertyDescriptor(Ctor.prototype, key)!,\n        )\n      }\n    }\n  }\n  if (__DEV__ && hasPrototypeAugmentations) {\n    warnDeprecation(DeprecationTypes.GLOBAL_PROTOTYPE, null)\n  }\n}\n\nfunction installCompatMount(\n  app: App,\n  context: AppContext,\n  render: RootRenderFunction,\n) {\n  let isMounted = false\n\n  /**\n   * Vue 2 supports the behavior of creating a component instance but not\n   * mounting it, which is no longer possible in Vue 3 - this internal\n   * function simulates that behavior.\n   */\n  app._createRoot = options => {\n    const component = app._component\n    const vnode = createVNode(component, options.propsData || null)\n    vnode.appContext = context\n\n    const hasNoRender =\n      !isFunction(component) && !component.render && !component.template\n    const emptyRender = () => {}\n\n    // create root instance\n    const instance = createComponentInstance(vnode, null, null)\n    // suppress \"missing render fn\" warning since it can't be determined\n    // until $mount is called\n    if (hasNoRender) {\n      instance.render = emptyRender\n    }\n    setupComponent(instance)\n    vnode.component = instance\n    vnode.isCompatRoot = true\n\n    // $mount & $destroy\n    // these are defined on ctx and picked up by the $mount/$destroy\n    // public property getters on the instance proxy.\n    // Note: the following assumes DOM environment since the compat build\n    // only targets web. It essentially includes logic for app.mount from\n    // both runtime-core AND runtime-dom.\n    instance.ctx._compat_mount = (selectorOrEl?: string | Element) => {\n      if (isMounted) {\n        __DEV__ && warn(`Root instance is already mounted.`)\n        return\n      }\n\n      let container: Element\n      if (typeof selectorOrEl === 'string') {\n        // eslint-disable-next-line\n        const result = document.querySelector(selectorOrEl)\n        if (!result) {\n          __DEV__ &&\n            warn(\n              `Failed to mount root instance: selector \"${selectorOrEl}\" returned null.`,\n            )\n          return\n        }\n        container = result\n      } else {\n        // eslint-disable-next-line\n        container = selectorOrEl || document.createElement('div')\n      }\n\n      let namespace: ElementNamespace\n      if (container instanceof SVGElement) namespace = 'svg'\n      else if (\n        typeof MathMLElement === 'function' &&\n        container instanceof MathMLElement\n      )\n        namespace = 'mathml'\n\n      // HMR root reload\n      if (__DEV__) {\n        context.reload = () => {\n          const cloned = cloneVNode(vnode)\n          // compat mode will use instance if not reset to null\n          cloned.component = null\n          render(cloned, container, namespace)\n        }\n      }\n\n      // resolve in-DOM template if component did not provide render\n      // and no setup/mixin render functions are provided (by checking\n      // that the instance is still using the placeholder render fn)\n      if (hasNoRender && instance.render === emptyRender) {\n        // root directives check\n        if (__DEV__) {\n          for (let i = 0; i < container.attributes.length; i++) {\n            const attr = container.attributes[i]\n            if (attr.name !== 'v-cloak' && /^(?:v-|:|@)/.test(attr.name)) {\n              warnDeprecation(DeprecationTypes.GLOBAL_MOUNT_CONTAINER, null)\n              break\n            }\n          }\n        }\n        instance.render = null\n        ;(component as ComponentOptions).template = container.innerHTML\n        finishComponentSetup(instance, false, true /* skip options */)\n      }\n\n      // clear content before mounting\n      container.textContent = ''\n\n      // TODO hydration\n      render(vnode, container, namespace)\n\n      if (container instanceof Element) {\n        container.removeAttribute('v-cloak')\n        container.setAttribute('data-v-app', '')\n      }\n\n      isMounted = true\n      app._container = container\n      // for devtools and telemetry\n      ;(container as any).__vue_app__ = app\n      if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {\n        devtoolsInitApp(app, version)\n      }\n\n      return instance.proxy!\n    }\n\n    instance.ctx._compat_destroy = () => {\n      if (isMounted) {\n        render(null, app._container)\n        if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {\n          devtoolsUnmountApp(app)\n        }\n        delete app._container.__vue_app__\n      } else {\n        const { bum, scope, um } = instance\n        // beforeDestroy hooks\n        if (bum) {\n          invokeArrayFns(bum)\n        }\n        if (isCompatEnabled(DeprecationTypes.INSTANCE_EVENT_HOOKS, instance)) {\n          instance.emit('hook:beforeDestroy')\n        }\n        // stop effects\n        if (scope) {\n          scope.stop()\n        }\n        // unmounted hook\n        if (um) {\n          invokeArrayFns(um)\n        }\n        if (isCompatEnabled(DeprecationTypes.INSTANCE_EVENT_HOOKS, instance)) {\n          instance.emit('hook:destroyed')\n        }\n      }\n    }\n\n    return instance.proxy!\n  }\n}\n\nconst methodsToPatch = [\n  'push',\n  'pop',\n  'shift',\n  'unshift',\n  'splice',\n  'sort',\n  'reverse',\n]\n\nconst patched = new WeakSet<object>()\n\nfunction defineReactive(obj: any, key: string, val: any) {\n  // it's possible for the original object to be mutated after being defined\n  // and expecting reactivity... we are covering it here because this seems to\n  // be a bit more common.\n  if (isObject(val) && !isReactive(val) && !patched.has(val)) {\n    const reactiveVal = reactive(val)\n    if (isArray(val)) {\n      methodsToPatch.forEach((m: any) => {\n        val[m] = (...args: any[]) => {\n          Array.prototype[m].apply(reactiveVal, args)\n        }\n      })\n    } else {\n      Object.keys(val).forEach(key => {\n        try {\n          defineReactiveSimple(val, key, val[key])\n        } catch (e: any) {}\n      })\n    }\n  }\n\n  const i = obj.$\n  if (i && obj === i.proxy) {\n    // target is a Vue instance - define on instance.ctx\n    defineReactiveSimple(i.ctx, key, val)\n    i.accessCache = Object.create(null)\n  } else if (isReactive(obj)) {\n    obj[key] = val\n  } else {\n    defineReactiveSimple(obj, key, val)\n  }\n}\n\nfunction defineReactiveSimple(obj: any, key: string, val: any) {\n  val = isObject(val) ? reactive(val) : val\n  Object.defineProperty(obj, key, {\n    enumerable: true,\n    configurable: true,\n    get() {\n      track(obj, TrackOpTypes.GET, key)\n      return val\n    },\n    set(newVal) {\n      val = isObject(newVal) ? reactive(newVal) : newVal\n      trigger(obj, TriggerOpTypes.SET, key, newVal)\n    },\n  })\n}\n"
  },
  {
    "path": "packages/runtime-core/src/compat/globalConfig.ts",
    "content": "import type { AppConfig } from '../apiCreateApp'\nimport {\n  DeprecationTypes,\n  softAssertCompatEnabled,\n  warnDeprecation,\n} from './compatConfig'\nimport { isCopyingConfig } from './global'\nimport { internalOptionMergeStrats } from '../componentOptions'\n\n// legacy config warnings\nexport type LegacyConfig = {\n  /**\n   * @deprecated `config.silent` option has been removed\n   */\n  silent?: boolean\n  /**\n   * @deprecated use __VUE_PROD_DEVTOOLS__ compile-time feature flag instead\n   * https://github.com/vuejs/core/tree/main/packages/vue#bundler-build-feature-flags\n   */\n  devtools?: boolean\n  /**\n   * @deprecated use `config.isCustomElement` instead\n   * https://v3-migration.vuejs.org/breaking-changes/global-api.html#config-ignoredelements-is-now-config-iscustomelement\n   */\n  ignoredElements?: (string | RegExp)[]\n  /**\n   * @deprecated\n   * https://v3-migration.vuejs.org/breaking-changes/keycode-modifiers.html\n   */\n  keyCodes?: Record<string, number | number[]>\n  /**\n   * @deprecated\n   * https://v3-migration.vuejs.org/breaking-changes/global-api.html#config-productiontip-removed\n   */\n  productionTip?: boolean\n}\n\n// dev only\nexport function installLegacyConfigWarnings(config: AppConfig): void {\n  const legacyConfigOptions: Record<string, DeprecationTypes> = {\n    silent: DeprecationTypes.CONFIG_SILENT,\n    devtools: DeprecationTypes.CONFIG_DEVTOOLS,\n    ignoredElements: DeprecationTypes.CONFIG_IGNORED_ELEMENTS,\n    keyCodes: DeprecationTypes.CONFIG_KEY_CODES,\n    productionTip: DeprecationTypes.CONFIG_PRODUCTION_TIP,\n  }\n\n  Object.keys(legacyConfigOptions).forEach(key => {\n    let val = (config as any)[key]\n    Object.defineProperty(config, key, {\n      enumerable: true,\n      get() {\n        return val\n      },\n      set(newVal) {\n        if (!isCopyingConfig) {\n          warnDeprecation(legacyConfigOptions[key], null)\n        }\n        val = newVal\n      },\n    })\n  })\n}\n\nexport function installLegacyOptionMergeStrats(config: AppConfig): void {\n  config.optionMergeStrategies = new Proxy({} as any, {\n    get(target, key) {\n      if (key in target) {\n        return target[key]\n      }\n      if (\n        key in internalOptionMergeStrats &&\n        softAssertCompatEnabled(\n          DeprecationTypes.CONFIG_OPTION_MERGE_STRATS,\n          null,\n        )\n      ) {\n        return internalOptionMergeStrats[\n          key as keyof typeof internalOptionMergeStrats\n        ]\n      }\n    },\n  })\n}\n"
  },
  {
    "path": "packages/runtime-core/src/compat/instance.ts",
    "content": "import {\n  NOOP,\n  extend,\n  looseEqual,\n  looseIndexOf,\n  looseToNumber,\n  toDisplayString,\n} from '@vue/shared'\nimport type {\n  ComponentPublicInstance,\n  PublicPropertiesMap,\n} from '../componentPublicInstance'\nimport { getCompatChildren } from './instanceChildren'\nimport {\n  DeprecationTypes,\n  assertCompatEnabled,\n  isCompatEnabled,\n  warnDeprecation,\n} from './compatConfig'\nimport { off, on, once } from './instanceEventEmitter'\nimport { getCompatListeners } from './instanceListeners'\nimport { shallowReadonly } from '@vue/reactivity'\nimport { legacySlotProxyHandlers } from './componentFunctional'\nimport { compatH } from './renderFn'\nimport { createCommentVNode, createTextVNode } from '../vnode'\nimport { renderList } from '../helpers/renderList'\nimport {\n  legacyBindDynamicKeys,\n  legacyBindObjectListeners,\n  legacyBindObjectProps,\n  legacyCheckKeyCodes,\n  legacyMarkOnce,\n  legacyPrependModifier,\n  legacyRenderSlot,\n  legacyRenderStatic,\n  legacyResolveScopedSlots,\n} from './renderHelpers'\nimport { resolveFilter } from '../helpers/resolveAssets'\nimport type { Slots } from '../componentSlots'\nimport { resolveMergedOptions } from '../componentOptions'\n\nexport type LegacyPublicInstance = ComponentPublicInstance &\n  LegacyPublicProperties\n\nexport interface LegacyPublicProperties {\n  $set<T extends Record<keyof any, any>, K extends keyof T>(\n    target: T,\n    key: K,\n    value: T[K],\n  ): void\n  $delete<T extends Record<keyof any, any>, K extends keyof T>(\n    target: T,\n    key: K,\n  ): void\n  $mount(el?: string | Element): this\n  $destroy(): void\n  $scopedSlots: Slots\n  $on(event: string | string[], fn: Function): this\n  $once(event: string, fn: Function): this\n  $off(event?: string | string[], fn?: Function): this\n  $children: LegacyPublicProperties[]\n  $listeners: Record<string, Function | Function[]>\n}\n\nexport function installCompatInstanceProperties(\n  map: PublicPropertiesMap,\n): void {\n  const set = (target: any, key: any, val: any) => {\n    target[key] = val\n    return target[key]\n  }\n\n  const del = (target: any, key: any) => {\n    delete target[key]\n  }\n\n  extend(map, {\n    $set: i => {\n      assertCompatEnabled(DeprecationTypes.INSTANCE_SET, i)\n      return set\n    },\n\n    $delete: i => {\n      assertCompatEnabled(DeprecationTypes.INSTANCE_DELETE, i)\n      return del\n    },\n\n    $mount: i => {\n      assertCompatEnabled(\n        DeprecationTypes.GLOBAL_MOUNT,\n        null /* this warning is global */,\n      )\n      // root mount override from ./global.ts in installCompatMount\n      return i.ctx._compat_mount || NOOP\n    },\n\n    $destroy: i => {\n      assertCompatEnabled(DeprecationTypes.INSTANCE_DESTROY, i)\n      // root destroy override from ./global.ts in installCompatMount\n      return i.ctx._compat_destroy || NOOP\n    },\n\n    // overrides existing accessor\n    $slots: i => {\n      if (\n        isCompatEnabled(DeprecationTypes.RENDER_FUNCTION, i) &&\n        i.render &&\n        i.render._compatWrapped\n      ) {\n        return new Proxy(i.slots, legacySlotProxyHandlers)\n      }\n      return __DEV__ ? shallowReadonly(i.slots) : i.slots\n    },\n\n    $scopedSlots: i => {\n      assertCompatEnabled(DeprecationTypes.INSTANCE_SCOPED_SLOTS, i)\n      return __DEV__ ? shallowReadonly(i.slots) : i.slots\n    },\n\n    $on: i => on.bind(null, i),\n    $once: i => once.bind(null, i),\n    $off: i => off.bind(null, i),\n\n    $children: getCompatChildren,\n    $listeners: getCompatListeners,\n\n    // inject additional properties into $options for compat\n    // e.g. vuex needs this.$options.parent\n    $options: i => {\n      if (!isCompatEnabled(DeprecationTypes.PRIVATE_APIS, i)) {\n        return resolveMergedOptions(i)\n      }\n      if (i.resolvedOptions) {\n        return i.resolvedOptions\n      }\n      const res = (i.resolvedOptions = extend({}, resolveMergedOptions(i)))\n      Object.defineProperties(res, {\n        parent: {\n          get() {\n            warnDeprecation(DeprecationTypes.PRIVATE_APIS, i, '$options.parent')\n            return i.proxy!.$parent\n          },\n        },\n        propsData: {\n          get() {\n            warnDeprecation(\n              DeprecationTypes.PRIVATE_APIS,\n              i,\n              '$options.propsData',\n            )\n            return i.vnode.props\n          },\n        },\n      })\n      return res\n    },\n  } as PublicPropertiesMap)\n\n  const privateAPIs = {\n    // needed by many libs / render fns\n    $vnode: i => i.vnode,\n\n    // some private properties that are likely accessed...\n    _self: i => i.proxy,\n    _uid: i => i.uid,\n    _data: i => i.data,\n    _isMounted: i => i.isMounted,\n    _isDestroyed: i => i.isUnmounted,\n\n    // v2 render helpers\n    $createElement: () => compatH,\n    _c: () => compatH,\n    _o: () => legacyMarkOnce,\n    _n: () => looseToNumber,\n    _s: () => toDisplayString,\n    _l: () => renderList,\n    _t: i => legacyRenderSlot.bind(null, i),\n    _q: () => looseEqual,\n    _i: () => looseIndexOf,\n    _m: i => legacyRenderStatic.bind(null, i),\n    _f: () => resolveFilter,\n    _k: i => legacyCheckKeyCodes.bind(null, i),\n    _b: () => legacyBindObjectProps,\n    _v: () => createTextVNode,\n    _e: () => createCommentVNode,\n    _u: () => legacyResolveScopedSlots,\n    _g: () => legacyBindObjectListeners,\n    _d: () => legacyBindDynamicKeys,\n    _p: () => legacyPrependModifier,\n  } as PublicPropertiesMap\n\n  for (const key in privateAPIs) {\n    map[key] = i => {\n      if (isCompatEnabled(DeprecationTypes.PRIVATE_APIS, i)) {\n        return privateAPIs[key](i)\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "packages/runtime-core/src/compat/instanceChildren.ts",
    "content": "import { ShapeFlags } from '@vue/shared'\nimport type { ComponentInternalInstance } from '../component'\nimport type { ComponentPublicInstance } from '../componentPublicInstance'\nimport type { VNode } from '../vnode'\nimport { DeprecationTypes, assertCompatEnabled } from './compatConfig'\n\nexport function getCompatChildren(\n  instance: ComponentInternalInstance,\n): ComponentPublicInstance[] {\n  assertCompatEnabled(DeprecationTypes.INSTANCE_CHILDREN, instance)\n  const root = instance.subTree\n  const children: ComponentPublicInstance[] = []\n  if (root) {\n    walk(root, children)\n  }\n  return children\n}\n\nfunction walk(vnode: VNode, children: ComponentPublicInstance[]) {\n  if (vnode.component) {\n    children.push(vnode.component.proxy!)\n  } else if (vnode.shapeFlag & ShapeFlags.ARRAY_CHILDREN) {\n    const vnodes = vnode.children as VNode[]\n    for (let i = 0; i < vnodes.length; i++) {\n      walk(vnodes[i], children)\n    }\n  }\n}\n"
  },
  {
    "path": "packages/runtime-core/src/compat/instanceEventEmitter.ts",
    "content": "import { isArray } from '@vue/shared'\nimport type { ComponentInternalInstance } from '../component'\nimport { ErrorCodes, callWithAsyncErrorHandling } from '../errorHandling'\nimport { DeprecationTypes, assertCompatEnabled } from './compatConfig'\nimport type { ComponentPublicInstance } from '../componentPublicInstance'\n\ninterface EventRegistry {\n  [event: string]: Function[] | undefined\n}\n\nconst eventRegistryMap = /*@__PURE__*/ new WeakMap<\n  ComponentInternalInstance,\n  EventRegistry\n>()\n\nexport function getRegistry(\n  instance: ComponentInternalInstance,\n): EventRegistry {\n  let events = eventRegistryMap.get(instance)\n  if (!events) {\n    eventRegistryMap.set(instance, (events = Object.create(null)))\n  }\n  return events!\n}\n\nexport function on(\n  instance: ComponentInternalInstance,\n  event: string | string[],\n  fn: Function,\n): ComponentPublicInstance | null {\n  if (isArray(event)) {\n    event.forEach(e => on(instance, e, fn))\n  } else {\n    if (event.startsWith('hook:')) {\n      assertCompatEnabled(\n        DeprecationTypes.INSTANCE_EVENT_HOOKS,\n        instance,\n        event,\n      )\n    } else {\n      assertCompatEnabled(DeprecationTypes.INSTANCE_EVENT_EMITTER, instance)\n    }\n    const events = getRegistry(instance)\n    ;(events[event] || (events[event] = [])).push(fn)\n  }\n  return instance.proxy\n}\n\nexport function once(\n  instance: ComponentInternalInstance,\n  event: string,\n  fn: Function,\n): ComponentPublicInstance | null {\n  const wrapped = (...args: any[]) => {\n    off(instance, event, wrapped)\n    fn.apply(instance.proxy, args)\n  }\n  wrapped.fn = fn\n  on(instance, event, wrapped)\n  return instance.proxy\n}\n\nexport function off(\n  instance: ComponentInternalInstance,\n  event?: string | string[],\n  fn?: Function,\n): ComponentPublicInstance | null {\n  assertCompatEnabled(DeprecationTypes.INSTANCE_EVENT_EMITTER, instance)\n  const vm = instance.proxy\n  // all\n  if (!event) {\n    eventRegistryMap.set(instance, Object.create(null))\n    return vm\n  }\n  // array of events\n  if (isArray(event)) {\n    event.forEach(e => off(instance, e, fn))\n    return vm\n  }\n  // specific event\n  const events = getRegistry(instance)\n  const cbs = events[event!]\n  if (!cbs) {\n    return vm\n  }\n  if (!fn) {\n    events[event!] = undefined\n    return vm\n  }\n  events[event!] = cbs.filter(cb => !(cb === fn || (cb as any).fn === fn))\n  return vm\n}\n\nexport function emit(\n  instance: ComponentInternalInstance,\n  event: string,\n  args: any[],\n): ComponentPublicInstance | null {\n  const cbs = getRegistry(instance)[event]\n  if (cbs) {\n    callWithAsyncErrorHandling(\n      cbs.map(cb => cb.bind(instance.proxy)),\n      instance,\n      ErrorCodes.COMPONENT_EVENT_HANDLER,\n      args,\n    )\n  }\n  return instance.proxy\n}\n"
  },
  {
    "path": "packages/runtime-core/src/compat/instanceListeners.ts",
    "content": "import { isOn } from '@vue/shared'\nimport type { ComponentInternalInstance } from '../component'\nimport { DeprecationTypes, assertCompatEnabled } from './compatConfig'\n\nexport function getCompatListeners(\n  instance: ComponentInternalInstance,\n): Record<string, Function | Function[]> {\n  assertCompatEnabled(DeprecationTypes.INSTANCE_LISTENERS, instance)\n\n  const listeners: Record<string, Function | Function[]> = {}\n  const rawProps = instance.vnode.props\n  if (!rawProps) {\n    return listeners\n  }\n  for (const key in rawProps) {\n    if (isOn(key)) {\n      listeners[key[2].toLowerCase() + key.slice(3)] = rawProps[key]\n    }\n  }\n  return listeners\n}\n"
  },
  {
    "path": "packages/runtime-core/src/compat/props.ts",
    "content": "import { isArray } from '@vue/shared'\nimport { inject } from '../apiInject'\nimport type { ComponentInternalInstance, Data } from '../component'\nimport {\n  type ComponentOptions,\n  resolveMergedOptions,\n} from '../componentOptions'\nimport { DeprecationTypes, warnDeprecation } from './compatConfig'\n\nexport function createPropsDefaultThis(\n  instance: ComponentInternalInstance,\n  rawProps: Data,\n  propKey: string,\n): object {\n  return new Proxy(\n    {},\n    {\n      get(_, key: string) {\n        __DEV__ &&\n          warnDeprecation(DeprecationTypes.PROPS_DEFAULT_THIS, null, propKey)\n        // $options\n        if (key === '$options') {\n          return resolveMergedOptions(instance)\n        }\n        // props\n        if (key in rawProps) {\n          return rawProps[key]\n        }\n        // injections\n        const injections = (instance.type as ComponentOptions).inject\n        if (injections) {\n          if (isArray(injections)) {\n            if (injections.includes(key)) {\n              return inject(key)\n            }\n          } else if (key in injections) {\n            return inject(key)\n          }\n        }\n      },\n    },\n  )\n}\n"
  },
  {
    "path": "packages/runtime-core/src/compat/renderFn.ts",
    "content": "import {\n  ShapeFlags,\n  extend,\n  hyphenate,\n  isArray,\n  isObject,\n  isString,\n  makeMap,\n  normalizeClass,\n  normalizeStyle,\n  toHandlerKey,\n} from '@vue/shared'\nimport type {\n  Component,\n  ComponentInternalInstance,\n  ComponentOptions,\n  Data,\n  InternalRenderFunction,\n} from '../component'\nimport { currentRenderingInstance } from '../componentRenderContext'\nimport { type DirectiveArguments, withDirectives } from '../directives'\nimport {\n  resolveDirective,\n  resolveDynamicComponent,\n} from '../helpers/resolveAssets'\nimport {\n  Comment,\n  type VNode,\n  type VNodeArrayChildren,\n  type VNodeProps,\n  createVNode,\n  isVNode,\n  normalizeChildren,\n} from '../vnode'\nimport {\n  DeprecationTypes,\n  checkCompatEnabled,\n  isCompatEnabled,\n} from './compatConfig'\nimport { compatModelEventPrefix } from './componentVModel'\n\nexport function convertLegacyRenderFn(\n  instance: ComponentInternalInstance,\n): void {\n  const Component = instance.type as ComponentOptions\n  const render = Component.render as InternalRenderFunction | undefined\n\n  // v3 runtime compiled, or already checked / wrapped\n  if (!render || render._rc || render._compatChecked || render._compatWrapped) {\n    return\n  }\n\n  if (render.length >= 2) {\n    // v3 pre-compiled function, since v2 render functions never need more than\n    // 2 arguments, and v2 functional render functions would have already been\n    // normalized into v3 functional components\n    render._compatChecked = true\n    return\n  }\n\n  // v2 render function, try to provide compat\n  if (checkCompatEnabled(DeprecationTypes.RENDER_FUNCTION, instance)) {\n    const wrapped = (Component.render = function compatRender() {\n      // @ts-expect-error\n      return render.call(this, compatH)\n    })\n    // @ts-expect-error\n    wrapped._compatWrapped = true\n  }\n}\n\ninterface LegacyVNodeProps {\n  key?: string | number\n  ref?: string\n  refInFor?: boolean\n\n  staticClass?: string\n  class?: unknown\n  staticStyle?: Record<string, unknown>\n  style?: Record<string, unknown>\n  attrs?: Record<string, unknown>\n  domProps?: Record<string, unknown>\n  on?: Record<string, Function | Function[]>\n  nativeOn?: Record<string, Function | Function[]>\n  directives?: LegacyVNodeDirective[]\n\n  // component only\n  props?: Record<string, unknown>\n  slot?: string\n  scopedSlots?: Record<string, Function>\n  model?: {\n    value: any\n    callback: (v: any) => void\n    expression: string\n  }\n}\n\ninterface LegacyVNodeDirective {\n  name: string\n  value: unknown\n  arg?: string\n  modifiers?: Record<string, boolean>\n}\n\ntype LegacyVNodeChildren =\n  | string\n  | number\n  | boolean\n  | VNode\n  | VNodeArrayChildren\n\nexport function compatH(\n  type: string | Component,\n  children?: LegacyVNodeChildren,\n): VNode\nexport function compatH(\n  type: string | Component,\n  props?: Data & LegacyVNodeProps,\n  children?: LegacyVNodeChildren,\n): VNode\n\nexport function compatH(\n  type: any,\n  propsOrChildren?: any,\n  children?: any,\n): VNode {\n  if (!type) {\n    type = Comment\n  }\n\n  // to support v2 string component name look!up\n  if (typeof type === 'string') {\n    const t = hyphenate(type)\n    if (t === 'transition' || t === 'transition-group' || t === 'keep-alive') {\n      // since transition and transition-group are runtime-dom-specific,\n      // we cannot import them directly here. Instead they are registered using\n      // special keys in @vue/compat entry.\n      type = `__compat__${t}`\n    }\n    type = resolveDynamicComponent(type)\n  }\n\n  const l = arguments.length\n  const is2ndArgArrayChildren = isArray(propsOrChildren)\n  if (l === 2 || is2ndArgArrayChildren) {\n    if (isObject(propsOrChildren) && !is2ndArgArrayChildren) {\n      // single vnode without props\n      if (isVNode(propsOrChildren)) {\n        return convertLegacySlots(createVNode(type, null, [propsOrChildren]))\n      }\n      // props without children\n      return convertLegacySlots(\n        convertLegacyDirectives(\n          createVNode(type, convertLegacyProps(propsOrChildren, type)),\n          propsOrChildren,\n        ),\n      )\n    } else {\n      // omit props\n      return convertLegacySlots(createVNode(type, null, propsOrChildren))\n    }\n  } else {\n    if (isVNode(children)) {\n      children = [children]\n    }\n    return convertLegacySlots(\n      convertLegacyDirectives(\n        createVNode(type, convertLegacyProps(propsOrChildren, type), children),\n        propsOrChildren,\n      ),\n    )\n  }\n}\n\nconst skipLegacyRootLevelProps = /*@__PURE__*/ makeMap(\n  'staticStyle,staticClass,directives,model,hook',\n)\n\nfunction convertLegacyProps(\n  legacyProps: LegacyVNodeProps | undefined,\n  type: any,\n): (Data & VNodeProps) | null {\n  if (!legacyProps) {\n    return null\n  }\n\n  const converted: Data & VNodeProps = {}\n\n  for (const key in legacyProps) {\n    if (key === 'attrs' || key === 'domProps' || key === 'props') {\n      extend(converted, legacyProps[key])\n    } else if (key === 'on' || key === 'nativeOn') {\n      const listeners = legacyProps[key]\n      for (const event in listeners) {\n        let handlerKey = convertLegacyEventKey(event)\n        if (key === 'nativeOn') handlerKey += `Native`\n        const existing = converted[handlerKey]\n        const incoming = listeners[event]\n        if (existing !== incoming) {\n          if (existing) {\n            converted[handlerKey] = [].concat(existing as any, incoming as any)\n          } else {\n            converted[handlerKey] = incoming\n          }\n        }\n      }\n    } else if (!skipLegacyRootLevelProps(key)) {\n      converted[key] = legacyProps[key as keyof LegacyVNodeProps]\n    }\n  }\n\n  if (legacyProps.staticClass) {\n    converted.class = normalizeClass([legacyProps.staticClass, converted.class])\n  }\n  if (legacyProps.staticStyle) {\n    converted.style = normalizeStyle([legacyProps.staticStyle, converted.style])\n  }\n\n  if (legacyProps.model && isObject(type)) {\n    // v2 compiled component v-model\n    const { prop = 'value', event = 'input' } = (type as any).model || {}\n    converted[prop] = legacyProps.model.value\n    converted[compatModelEventPrefix + event] = legacyProps.model.callback\n  }\n\n  return converted\n}\n\nfunction convertLegacyEventKey(event: string): string {\n  // normalize v2 event prefixes\n  if (event[0] === '&') {\n    event = event.slice(1) + 'Passive'\n  }\n  if (event[0] === '~') {\n    event = event.slice(1) + 'Once'\n  }\n  if (event[0] === '!') {\n    event = event.slice(1) + 'Capture'\n  }\n  return toHandlerKey(event)\n}\n\nfunction convertLegacyDirectives(\n  vnode: VNode,\n  props?: LegacyVNodeProps,\n): VNode {\n  if (props && props.directives) {\n    return withDirectives(\n      vnode,\n      props.directives.map(({ name, value, arg, modifiers }) => {\n        return [\n          resolveDirective(name)!,\n          value,\n          arg,\n          modifiers,\n        ] as DirectiveArguments[number]\n      }),\n    )\n  }\n  return vnode\n}\n\nfunction convertLegacySlots(vnode: VNode): VNode {\n  const { props, children } = vnode\n\n  let slots: Record<string, any> | undefined\n\n  if (vnode.shapeFlag & ShapeFlags.COMPONENT && isArray(children)) {\n    slots = {}\n    // check \"slot\" property on vnodes and turn them into v3 function slots\n    for (let i = 0; i < children.length; i++) {\n      const child = children[i]\n      const slotName =\n        (isVNode(child) && child.props && child.props.slot) || 'default'\n      const slot = slots[slotName] || (slots[slotName] = [] as any[])\n      if (isVNode(child) && child.type === 'template') {\n        slot.push(child.children)\n      } else {\n        slot.push(child)\n      }\n    }\n    if (slots) {\n      for (const key in slots) {\n        const slotChildren = slots[key]\n        slots[key] = () => slotChildren\n        slots[key]._ns = true /* non-scoped slot */\n      }\n    }\n  }\n\n  const scopedSlots = props && props.scopedSlots\n  if (scopedSlots) {\n    delete props!.scopedSlots\n    if (slots) {\n      extend(slots, scopedSlots)\n    } else {\n      slots = scopedSlots\n    }\n  }\n\n  if (slots) {\n    normalizeChildren(vnode, slots)\n  }\n\n  return vnode\n}\n\nexport function defineLegacyVNodeProperties(vnode: VNode): void {\n  /* v8 ignore start */\n  if (\n    isCompatEnabled(\n      DeprecationTypes.RENDER_FUNCTION,\n      currentRenderingInstance,\n      true /* enable for built-ins */,\n    ) &&\n    isCompatEnabled(\n      DeprecationTypes.PRIVATE_APIS,\n      currentRenderingInstance,\n      true /* enable for built-ins */,\n    )\n  ) {\n    const context = currentRenderingInstance\n    const getInstance = () => vnode.component && vnode.component.proxy\n    let componentOptions: any\n    Object.defineProperties(vnode, {\n      tag: { get: () => vnode.type },\n      data: { get: () => vnode.props || {}, set: p => (vnode.props = p) },\n      elm: { get: () => vnode.el },\n      componentInstance: { get: getInstance },\n      child: { get: getInstance },\n      text: { get: () => (isString(vnode.children) ? vnode.children : null) },\n      context: { get: () => context && context.proxy },\n      componentOptions: {\n        get: () => {\n          if (vnode.shapeFlag & ShapeFlags.STATEFUL_COMPONENT) {\n            if (componentOptions) {\n              return componentOptions\n            }\n            return (componentOptions = {\n              Ctor: vnode.type,\n              propsData: vnode.props,\n              children: vnode.children,\n            })\n          }\n        },\n      },\n    })\n  }\n  /* v8 ignore stop */\n}\n"
  },
  {
    "path": "packages/runtime-core/src/compat/renderHelpers.ts",
    "content": "import {\n  camelize,\n  extend,\n  hyphenate,\n  isArray,\n  isObject,\n  isReservedProp,\n  normalizeClass,\n} from '@vue/shared'\nimport type { ComponentInternalInstance, Data } from '../component'\nimport type { Slot } from '../componentSlots'\nimport { createSlots } from '../helpers/createSlots'\nimport { renderSlot } from '../helpers/renderSlot'\nimport { toHandlers } from '../helpers/toHandlers'\nimport { type VNode, mergeProps } from '../vnode'\n\nfunction toObject(arr: Array<any>): Object {\n  const res = {}\n  for (let i = 0; i < arr.length; i++) {\n    if (arr[i]) {\n      extend(res, arr[i])\n    }\n  }\n  return res\n}\n\nexport function legacyBindObjectProps(\n  data: any,\n  _tag: string,\n  value: any,\n  _asProp: boolean,\n  isSync?: boolean,\n): any {\n  if (value && isObject(value)) {\n    if (isArray(value)) {\n      value = toObject(value)\n    }\n    for (const key in value) {\n      if (isReservedProp(key)) {\n        data[key] = value[key]\n      } else if (key === 'class') {\n        data.class = normalizeClass([data.class, value.class])\n      } else if (key === 'style') {\n        data.style = normalizeClass([data.style, value.style])\n      } else {\n        const attrs = data.attrs || (data.attrs = {})\n        const camelizedKey = camelize(key)\n        const hyphenatedKey = hyphenate(key)\n        if (!(camelizedKey in attrs) && !(hyphenatedKey in attrs)) {\n          attrs[key] = value[key]\n\n          if (isSync) {\n            const on = data.on || (data.on = {})\n            on[`update:${key}`] = function ($event: any) {\n              value[key] = $event\n            }\n          }\n        }\n      }\n    }\n  }\n  return data\n}\n\nexport function legacyBindObjectListeners(props: any, listeners: any): Data {\n  return mergeProps(props, toHandlers(listeners))\n}\n\nexport function legacyRenderSlot(\n  instance: ComponentInternalInstance,\n  name: string,\n  fallback?: VNode[],\n  props?: any,\n  bindObject?: any,\n): VNode {\n  if (bindObject) {\n    props = mergeProps(props, bindObject)\n  }\n  return renderSlot(instance.slots, name, props, fallback && (() => fallback))\n}\n\ntype LegacyScopedSlotsData = Array<\n  | {\n      key: string\n      fn: Function\n    }\n  | LegacyScopedSlotsData\n>\n\nexport function legacyResolveScopedSlots(\n  fns: LegacyScopedSlotsData,\n  raw?: Record<string, Slot>,\n  // the following are added in 2.6\n  hasDynamicKeys?: boolean,\n): ReturnType<typeof createSlots> {\n  // v2 default slot doesn't have name\n  return createSlots(\n    raw || ({ $stable: !hasDynamicKeys } as any),\n    mapKeyToName(fns),\n  )\n}\n\nfunction mapKeyToName(slots: LegacyScopedSlotsData) {\n  for (let i = 0; i < slots.length; i++) {\n    const fn = slots[i]\n    if (fn) {\n      if (isArray(fn)) {\n        mapKeyToName(fn)\n      } else {\n        ;(fn as any).name = fn.key || 'default'\n      }\n    }\n  }\n  return slots as any\n}\n\nconst staticCacheMap = /*@__PURE__*/ new WeakMap<\n  ComponentInternalInstance,\n  any[]\n>()\n\nexport function legacyRenderStatic(\n  instance: ComponentInternalInstance,\n  index: number,\n): any {\n  let cache = staticCacheMap.get(instance)\n  if (!cache) {\n    staticCacheMap.set(instance, (cache = []))\n  }\n  if (cache[index]) {\n    return cache[index]\n  }\n  const fn = (instance.type as any).staticRenderFns[index]\n  const ctx = instance.proxy\n  return (cache[index] = fn.call(ctx, null, ctx))\n}\n\nexport function legacyCheckKeyCodes(\n  instance: ComponentInternalInstance,\n  eventKeyCode: number,\n  key: string,\n  builtInKeyCode?: number | number[],\n  eventKeyName?: string,\n  builtInKeyName?: string | string[],\n): boolean | undefined {\n  const config = instance.appContext.config as any\n  const configKeyCodes = config.keyCodes || {}\n  const mappedKeyCode = configKeyCodes[key] || builtInKeyCode\n  if (builtInKeyName && eventKeyName && !configKeyCodes[key]) {\n    return isKeyNotMatch(builtInKeyName, eventKeyName)\n  } else if (mappedKeyCode) {\n    return isKeyNotMatch(mappedKeyCode, eventKeyCode)\n  } else if (eventKeyName) {\n    return hyphenate(eventKeyName) !== key\n  }\n}\n\nfunction isKeyNotMatch<T>(expect: T | T[], actual: T): boolean {\n  if (isArray(expect)) {\n    return !expect.includes(actual)\n  } else {\n    return expect !== actual\n  }\n}\n\nexport function legacyMarkOnce(tree: VNode): VNode {\n  return tree\n}\n\nexport function legacyBindDynamicKeys(props: any, values: any[]): any {\n  for (let i = 0; i < values.length; i += 2) {\n    const key = values[i]\n    if (typeof key === 'string' && key) {\n      props[values[i]] = values[i + 1]\n    }\n  }\n  return props\n}\n\nexport function legacyPrependModifier(value: any, symbol: string): any {\n  return typeof value === 'string' ? symbol + value : value\n}\n"
  },
  {
    "path": "packages/runtime-core/src/component.ts",
    "content": "import { type VNode, type VNodeChild, isVNode } from './vnode'\nimport {\n  EffectScope,\n  type ReactiveEffect,\n  TrackOpTypes,\n  isRef,\n  markRaw,\n  pauseTracking,\n  proxyRefs,\n  resetTracking,\n  shallowReadonly,\n  track,\n} from '@vue/reactivity'\nimport {\n  type ComponentPublicInstance,\n  type ComponentPublicInstanceConstructor,\n  PublicInstanceProxyHandlers,\n  RuntimeCompiledPublicInstanceProxyHandlers,\n  createDevRenderContext,\n  exposePropsOnRenderContext,\n  exposeSetupStateOnRenderContext,\n  publicPropertiesMap,\n} from './componentPublicInstance'\nimport {\n  type ComponentPropsOptions,\n  type NormalizedPropsOptions,\n  initProps,\n  normalizePropsOptions,\n} from './componentProps'\nimport {\n  type InternalSlots,\n  type Slots,\n  type SlotsType,\n  type UnwrapSlotsType,\n  initSlots,\n} from './componentSlots'\nimport { warn } from './warning'\nimport { ErrorCodes, callWithErrorHandling, handleError } from './errorHandling'\nimport {\n  type AppConfig,\n  type AppContext,\n  createAppContext,\n} from './apiCreateApp'\nimport { type Directive, validateDirectiveName } from './directives'\nimport {\n  type ComponentOptions,\n  type ComputedOptions,\n  type MergedComponentOptions,\n  type MethodOptions,\n  applyOptions,\n  resolveMergedOptions,\n} from './componentOptions'\nimport {\n  type EmitFn,\n  type EmitsOptions,\n  type EmitsToProps,\n  type ObjectEmitsOptions,\n  type ShortEmitsToObject,\n  emit,\n  normalizeEmitsOptions,\n} from './componentEmits'\nimport {\n  EMPTY_OBJ,\n  type IfAny,\n  NOOP,\n  ShapeFlags,\n  extend,\n  getGlobalThis,\n  isArray,\n  isFunction,\n  isObject,\n  isPromise,\n  makeMap,\n} from '@vue/shared'\nimport type { SuspenseBoundary } from './components/Suspense'\nimport type { CompilerOptions } from '@vue/compiler-core'\nimport { markAttrsAccessed } from './componentRenderUtils'\nimport { currentRenderingInstance } from './componentRenderContext'\nimport { endMeasure, startMeasure } from './profiling'\nimport { convertLegacyRenderFn } from './compat/renderFn'\nimport {\n  type CompatConfig,\n  globalCompatConfig,\n  validateCompatConfig,\n} from './compat/compatConfig'\nimport type { SchedulerJob } from './scheduler'\nimport type { LifecycleHooks } from './enums'\n\n// Augment GlobalComponents\nimport type { TeleportProps } from './components/Teleport'\nimport type { SuspenseProps } from './components/Suspense'\nimport type { KeepAliveProps } from './components/KeepAlive'\nimport type { BaseTransitionProps } from './components/BaseTransition'\nimport type { DefineComponent } from './apiDefineComponent'\nimport { markAsyncBoundary } from './helpers/useId'\nimport { isAsyncWrapper } from './apiAsyncComponent'\nimport type { RendererElement } from './renderer'\n\nexport type Data = Record<string, unknown>\n\n/**\n * For extending allowed non-declared attrs on components in TSX\n */\nexport interface AllowedAttrs {}\n\nexport type Attrs = Data & AllowedAttrs\n\n/**\n * Public utility type for extracting the instance type of a component.\n * Works with all valid component definition types. This is intended to replace\n * the usage of `InstanceType<typeof Comp>` which only works for\n * constructor-based component definition types.\n *\n * @example\n * ```ts\n * const MyComp = { ... }\n * declare const instance: ComponentInstance<typeof MyComp>\n * ```\n */\nexport type ComponentInstance<T> = T extends { new (): ComponentPublicInstance }\n  ? InstanceType<T>\n  : T extends FunctionalComponent<infer Props, infer Emits>\n    ? ComponentPublicInstance<Props, {}, {}, {}, {}, ShortEmitsToObject<Emits>>\n    : T extends Component<\n          infer PropsOrInstance,\n          infer RawBindings,\n          infer D,\n          infer C,\n          infer M\n        >\n      ? PropsOrInstance extends { $props: unknown }\n        ? // T is returned by `defineComponent()`\n          PropsOrInstance\n        : // NOTE we override Props/RawBindings/D to make sure is not `unknown`\n          ComponentPublicInstance<\n            unknown extends PropsOrInstance ? {} : PropsOrInstance,\n            unknown extends RawBindings ? {} : RawBindings,\n            unknown extends D ? {} : D,\n            C,\n            M\n          >\n      : never // not a vue Component\n\n/**\n * For extending allowed non-declared props on components in TSX\n */\nexport interface ComponentCustomProps {}\n\n/**\n * For globally defined Directives\n * Here is an example of adding a directive `VTooltip` as global directive:\n *\n * @example\n * ```ts\n * import VTooltip from 'v-tooltip'\n *\n * declare module '@vue/runtime-core' {\n *   interface GlobalDirectives {\n *     VTooltip\n *   }\n * }\n * ```\n */\nexport interface GlobalDirectives {}\n\n/**\n * For globally defined Components\n * Here is an example of adding a component `RouterView` as global component:\n *\n * @example\n * ```ts\n * import { RouterView } from 'vue-router'\n *\n * declare module '@vue/runtime-core' {\n *   interface GlobalComponents {\n *     RouterView\n *   }\n * }\n * ```\n */\nexport interface GlobalComponents {\n  Teleport: DefineComponent<TeleportProps>\n  Suspense: DefineComponent<SuspenseProps>\n  KeepAlive: DefineComponent<KeepAliveProps>\n  BaseTransition: DefineComponent<BaseTransitionProps>\n}\n\n/**\n * Default allowed non-declared props on component in TSX\n */\nexport interface AllowedComponentProps {\n  class?: unknown\n  style?: unknown\n}\n\n// Note: can't mark this whole interface internal because some public interfaces\n// extend it.\nexport interface ComponentInternalOptions {\n  /**\n   * @internal\n   */\n  __scopeId?: string\n  /**\n   * @internal\n   */\n  __cssModules?: Data\n  /**\n   * @internal\n   */\n  __hmrId?: string\n  /**\n   * Compat build only, for bailing out of certain compatibility behavior\n   */\n  __isBuiltIn?: boolean\n  /**\n   * This one should be exposed so that devtools can make use of it\n   */\n  __file?: string\n  /**\n   * name inferred from filename\n   */\n  __name?: string\n}\n\nexport interface FunctionalComponent<\n  P = {},\n  E extends EmitsOptions | Record<string, any[]> = {},\n  S extends Record<string, any> = any,\n  EE extends EmitsOptions = ShortEmitsToObject<E>,\n> extends ComponentInternalOptions {\n  // use of any here is intentional so it can be a valid JSX Element constructor\n  (\n    props: P & EmitsToProps<EE>,\n    ctx: Omit<SetupContext<EE, IfAny<S, {}, SlotsType<S>>>, 'expose'>,\n  ): any\n  props?: ComponentPropsOptions<P>\n  emits?: EE | (keyof EE)[]\n  slots?: IfAny<S, Slots, SlotsType<S>>\n  inheritAttrs?: boolean\n  displayName?: string\n  compatConfig?: CompatConfig\n}\n\nexport interface ClassComponent {\n  new (...args: any[]): ComponentPublicInstance<any, any, any, any, any>\n  __vccOpts: ComponentOptions\n}\n\n/**\n * Concrete component type matches its actual value: it's either an options\n * object, or a function. Use this where the code expects to work with actual\n * values, e.g. checking if its a function or not. This is mostly for internal\n * implementation code.\n */\nexport type ConcreteComponent<\n  Props = {},\n  RawBindings = any,\n  D = any,\n  C extends ComputedOptions = ComputedOptions,\n  M extends MethodOptions = MethodOptions,\n  E extends EmitsOptions | Record<string, any[]> = {},\n  S extends Record<string, any> = any,\n> =\n  | ComponentOptions<Props, RawBindings, D, C, M>\n  | FunctionalComponent<Props, E, S>\n\n/**\n * A type used in public APIs where a component type is expected.\n * The constructor type is an artificial type returned by defineComponent().\n */\nexport type Component<\n  PropsOrInstance = any,\n  RawBindings = any,\n  D = any,\n  C extends ComputedOptions = ComputedOptions,\n  M extends MethodOptions = MethodOptions,\n  E extends EmitsOptions | Record<string, any[]> = {},\n  S extends Record<string, any> = any,\n> =\n  | ConcreteComponent<PropsOrInstance, RawBindings, D, C, M, E, S>\n  | ComponentPublicInstanceConstructor<PropsOrInstance>\n\nexport type { ComponentOptions }\n\nexport type LifecycleHook<TFn = Function> = (TFn & SchedulerJob)[] | null\n\n// use `E extends any` to force evaluating type to fix #2362\nexport type SetupContext<\n  E = EmitsOptions,\n  S extends SlotsType = {},\n> = E extends any\n  ? {\n      attrs: Attrs\n      slots: UnwrapSlotsType<S>\n      emit: EmitFn<E>\n      expose: <Exposed extends Record<string, any> = Record<string, any>>(\n        exposed?: Exposed,\n      ) => void\n    }\n  : never\n\n/**\n * @internal\n */\nexport type InternalRenderFunction = {\n  (\n    ctx: ComponentPublicInstance,\n    cache: ComponentInternalInstance['renderCache'],\n    // for compiler-optimized bindings\n    $props: ComponentInternalInstance['props'],\n    $setup: ComponentInternalInstance['setupState'],\n    $data: ComponentInternalInstance['data'],\n    $options: ComponentInternalInstance['ctx'],\n  ): VNodeChild\n  _rc?: boolean // isRuntimeCompiled\n\n  // __COMPAT__ only\n  _compatChecked?: boolean // v3 and already checked for v2 compat\n  _compatWrapped?: boolean // is wrapped for v2 compat\n}\n\n/**\n * We expose a subset of properties on the internal instance as they are\n * useful for advanced external libraries and tools.\n */\nexport interface ComponentInternalInstance {\n  uid: number\n  type: ConcreteComponent\n  parent: ComponentInternalInstance | null\n  root: ComponentInternalInstance\n  appContext: AppContext\n  /**\n   * Vnode representing this component in its parent's vdom tree\n   */\n  vnode: VNode\n  /**\n   * The pending new vnode from parent updates\n   * @internal\n   */\n  next: VNode | null\n  /**\n   * Root vnode of this component's own vdom tree\n   */\n  subTree: VNode\n  /**\n   * Render effect instance\n   */\n  effect: ReactiveEffect\n  /**\n   * Force update render effect\n   */\n  update: () => void\n  /**\n   * Render effect job to be passed to scheduler (checks if dirty)\n   */\n  job: SchedulerJob\n  /**\n   * The render function that returns vdom tree.\n   * @internal\n   */\n  render: InternalRenderFunction | null\n  /**\n   * SSR render function\n   * @internal\n   */\n  ssrRender?: Function | null\n  /**\n   * Object containing values this component provides for its descendants\n   * @internal\n   */\n  provides: Data\n  /**\n   * for tracking useId()\n   * first element is the current boundary prefix\n   * second number is the index of the useId call within that boundary\n   * @internal\n   */\n  ids: [string, number, number]\n  /**\n   * Tracking reactive effects (e.g. watchers) associated with this component\n   * so that they can be automatically stopped on component unmount\n   * @internal\n   */\n  scope: EffectScope\n  /**\n   * cache for proxy access type to avoid hasOwnProperty calls\n   * @internal\n   */\n  accessCache: Data | null\n  /**\n   * cache for render function values that rely on _ctx but won't need updates\n   * after initialized (e.g. inline handlers)\n   * @internal\n   */\n  renderCache: (Function | VNode | undefined)[]\n\n  /**\n   * Resolved component registry, only for components with mixins or extends\n   * @internal\n   */\n  components: Record<string, ConcreteComponent> | null\n  /**\n   * Resolved directive registry, only for components with mixins or extends\n   * @internal\n   */\n  directives: Record<string, Directive> | null\n  /**\n   * Resolved filters registry, v2 compat only\n   * @internal\n   */\n  filters?: Record<string, Function>\n  /**\n   * resolved props options\n   * @internal\n   */\n  propsOptions: NormalizedPropsOptions\n  /**\n   * resolved emits options\n   * @internal\n   */\n  emitsOptions: ObjectEmitsOptions | null\n  /**\n   * resolved inheritAttrs options\n   * @internal\n   */\n  inheritAttrs?: boolean\n  /**\n   * Custom Element instance (if component is created by defineCustomElement)\n   * @internal\n   */\n  ce?: ComponentCustomElementInterface\n  /**\n   * is custom element? (kept only for compatibility)\n   * @internal\n   */\n  isCE?: boolean\n  /**\n   * custom element specific HMR method\n   * @internal\n   */\n  ceReload?: (newStyles?: string[]) => void\n\n  // the rest are only for stateful components ---------------------------------\n\n  // main proxy that serves as the public instance (`this`)\n  proxy: ComponentPublicInstance | null\n\n  // exposed properties via expose()\n  exposed: Record<string, any> | null\n  exposeProxy: Record<string, any> | null\n\n  /**\n   * alternative proxy used only for runtime-compiled render functions using\n   * `with` block\n   * @internal\n   */\n  withProxy: ComponentPublicInstance | null\n  /**\n   * This is the target for the public instance proxy. It also holds properties\n   * injected by user options (computed, methods etc.) and user-attached\n   * custom properties (via `this.x = ...`)\n   * @internal\n   */\n  ctx: Data\n\n  // state\n  data: Data\n  props: Data\n  attrs: Data\n  slots: InternalSlots\n  refs: Data\n  emit: EmitFn\n\n  /**\n   * used for keeping track of .once event handlers on components\n   * @internal\n   */\n  emitted: Record<string, boolean> | null\n  /**\n   * used for caching the value returned from props default factory functions to\n   * avoid unnecessary watcher trigger\n   * @internal\n   */\n  propsDefaults: Data\n  /**\n   * setup related\n   * @internal\n   */\n  setupState: Data\n  /**\n   * devtools access to additional info\n   * @internal\n   */\n  devtoolsRawSetupState?: any\n  /**\n   * @internal\n   */\n  setupContext: SetupContext | null\n\n  /**\n   * suspense related\n   * @internal\n   */\n  suspense: SuspenseBoundary | null\n  /**\n   * suspense pending batch id\n   * @internal\n   */\n  suspenseId: number\n  /**\n   * @internal\n   */\n  asyncDep: Promise<any> | null\n  /**\n   * @internal\n   */\n  asyncResolved: boolean\n\n  // lifecycle\n  isMounted: boolean\n  isUnmounted: boolean\n  isDeactivated: boolean\n  /**\n   * @internal\n   */\n  [LifecycleHooks.BEFORE_CREATE]: LifecycleHook\n  /**\n   * @internal\n   */\n  [LifecycleHooks.CREATED]: LifecycleHook\n  /**\n   * @internal\n   */\n  [LifecycleHooks.BEFORE_MOUNT]: LifecycleHook\n  /**\n   * @internal\n   */\n  [LifecycleHooks.MOUNTED]: LifecycleHook\n  /**\n   * @internal\n   */\n  [LifecycleHooks.BEFORE_UPDATE]: LifecycleHook\n  /**\n   * @internal\n   */\n  [LifecycleHooks.UPDATED]: LifecycleHook\n  /**\n   * @internal\n   */\n  [LifecycleHooks.BEFORE_UNMOUNT]: LifecycleHook\n  /**\n   * @internal\n   */\n  [LifecycleHooks.UNMOUNTED]: LifecycleHook\n  /**\n   * @internal\n   */\n  [LifecycleHooks.RENDER_TRACKED]: LifecycleHook\n  /**\n   * @internal\n   */\n  [LifecycleHooks.RENDER_TRIGGERED]: LifecycleHook\n  /**\n   * @internal\n   */\n  [LifecycleHooks.ACTIVATED]: LifecycleHook\n  /**\n   * @internal\n   */\n  [LifecycleHooks.DEACTIVATED]: LifecycleHook\n  /**\n   * @internal\n   */\n  [LifecycleHooks.ERROR_CAPTURED]: LifecycleHook\n  /**\n   * @internal\n   */\n  [LifecycleHooks.SERVER_PREFETCH]: LifecycleHook<() => Promise<unknown>>\n\n  /**\n   * For caching bound $forceUpdate on public proxy access\n   * @internal\n   */\n  f?: () => void\n  /**\n   * For caching bound $nextTick on public proxy access\n   * @internal\n   */\n  n?: () => Promise<void>\n  /**\n   * `updateTeleportCssVars`\n   * For updating css vars on contained teleports\n   * @internal\n   */\n  ut?: (vars?: Record<string, unknown>) => void\n\n  /**\n   * dev only. For style v-bind hydration mismatch checks\n   * @internal\n   */\n  getCssVars?: () => Record<string, unknown>\n\n  /**\n   * v2 compat only, for caching mutated $options\n   * @internal\n   */\n  resolvedOptions?: MergedComponentOptions\n}\n\nconst emptyAppContext = createAppContext()\n\nlet uid = 0\n\nexport function createComponentInstance(\n  vnode: VNode,\n  parent: ComponentInternalInstance | null,\n  suspense: SuspenseBoundary | null,\n): ComponentInternalInstance {\n  const type = vnode.type as ConcreteComponent\n  // inherit parent app context - or - if root, adopt from root vnode\n  const appContext =\n    (parent ? parent.appContext : vnode.appContext) || emptyAppContext\n\n  const instance: ComponentInternalInstance = {\n    uid: uid++,\n    vnode,\n    type,\n    parent,\n    appContext,\n    root: null!, // to be immediately set\n    next: null,\n    subTree: null!, // will be set synchronously right after creation\n    effect: null!,\n    update: null!, // will be set synchronously right after creation\n    job: null!,\n    scope: new EffectScope(true /* detached */),\n    render: null,\n    proxy: null,\n    exposed: null,\n    exposeProxy: null,\n    withProxy: null,\n\n    provides: parent ? parent.provides : Object.create(appContext.provides),\n    ids: parent ? parent.ids : ['', 0, 0],\n    accessCache: null!,\n    renderCache: [],\n\n    // local resolved assets\n    components: null,\n    directives: null,\n\n    // resolved props and emits options\n    propsOptions: normalizePropsOptions(type, appContext),\n    emitsOptions: normalizeEmitsOptions(type, appContext),\n\n    // emit\n    emit: null!, // to be set immediately\n    emitted: null,\n\n    // props default value\n    propsDefaults: EMPTY_OBJ,\n\n    // inheritAttrs\n    inheritAttrs: type.inheritAttrs,\n\n    // state\n    ctx: EMPTY_OBJ,\n    data: EMPTY_OBJ,\n    props: EMPTY_OBJ,\n    attrs: EMPTY_OBJ,\n    slots: EMPTY_OBJ,\n    refs: EMPTY_OBJ,\n    setupState: EMPTY_OBJ,\n    setupContext: null,\n\n    // suspense related\n    suspense,\n    suspenseId: suspense ? suspense.pendingId : 0,\n    asyncDep: null,\n    asyncResolved: false,\n\n    // lifecycle hooks\n    // not using enums here because it results in computed properties\n    isMounted: false,\n    isUnmounted: false,\n    isDeactivated: false,\n    bc: null,\n    c: null,\n    bm: null,\n    m: null,\n    bu: null,\n    u: null,\n    um: null,\n    bum: null,\n    da: null,\n    a: null,\n    rtg: null,\n    rtc: null,\n    ec: null,\n    sp: null,\n  }\n  if (__DEV__) {\n    instance.ctx = createDevRenderContext(instance)\n  } else {\n    instance.ctx = { _: instance }\n  }\n  instance.root = parent ? parent.root : instance\n  instance.emit = emit.bind(null, instance)\n\n  // apply custom element special handling\n  if (vnode.ce) {\n    vnode.ce(instance)\n  }\n\n  return instance\n}\n\nexport let currentInstance: ComponentInternalInstance | null = null\n\nexport const getCurrentInstance: () => ComponentInternalInstance | null = () =>\n  currentInstance || currentRenderingInstance\n\nlet internalSetCurrentInstance: (\n  instance: ComponentInternalInstance | null,\n) => void\nexport let setInSSRSetupState: (state: boolean) => void\n\n/**\n * The following makes getCurrentInstance() usage across multiple copies of Vue\n * work. Some cases of how this can happen are summarized in #7590. In principle\n * the duplication should be avoided, but in practice there are often cases\n * where the user is unable to resolve on their own, especially in complicated\n * SSR setups.\n *\n * Note this fix is technically incomplete, as we still rely on other singletons\n * for effectScope and global reactive dependency maps. However, it does make\n * some of the most common cases work. It also warns if the duplication is\n * found during browser execution.\n */\nif (__SSR__) {\n  type Setter = (v: any) => void\n  const g = getGlobalThis()\n  const registerGlobalSetter = (key: string, setter: Setter) => {\n    let setters: Setter[]\n    if (!(setters = g[key])) setters = g[key] = []\n    setters.push(setter)\n    return (v: any) => {\n      if (setters.length > 1) setters.forEach(set => set(v))\n      else setters[0](v)\n    }\n  }\n  internalSetCurrentInstance = registerGlobalSetter(\n    `__VUE_INSTANCE_SETTERS__`,\n    v => (currentInstance = v),\n  )\n  // also make `isInSSRComponentSetup` sharable across copies of Vue.\n  // this is needed in the SFC playground when SSRing async components, since\n  // we have to load both the runtime and the server-renderer from CDNs, they\n  // contain duplicated copies of Vue runtime code.\n  setInSSRSetupState = registerGlobalSetter(\n    `__VUE_SSR_SETTERS__`,\n    v => (isInSSRComponentSetup = v),\n  )\n} else {\n  internalSetCurrentInstance = i => {\n    currentInstance = i\n  }\n  setInSSRSetupState = v => {\n    isInSSRComponentSetup = v\n  }\n}\n\nexport const setCurrentInstance = (instance: ComponentInternalInstance) => {\n  const prev = currentInstance\n  internalSetCurrentInstance(instance)\n  instance.scope.on()\n  return (): void => {\n    instance.scope.off()\n    internalSetCurrentInstance(prev)\n  }\n}\n\nexport const unsetCurrentInstance = (): void => {\n  currentInstance && currentInstance.scope.off()\n  internalSetCurrentInstance(null)\n}\n\nconst isBuiltInTag = /*@__PURE__*/ makeMap('slot,component')\n\nexport function validateComponentName(\n  name: string,\n  { isNativeTag }: AppConfig,\n): void {\n  if (isBuiltInTag(name) || isNativeTag(name)) {\n    warn(\n      'Do not use built-in or reserved HTML elements as component id: ' + name,\n    )\n  }\n}\n\nexport function isStatefulComponent(\n  instance: ComponentInternalInstance,\n): number {\n  return instance.vnode.shapeFlag & ShapeFlags.STATEFUL_COMPONENT\n}\n\nexport let isInSSRComponentSetup = false\n\nexport function setupComponent(\n  instance: ComponentInternalInstance,\n  isSSR = false,\n  optimized = false,\n): Promise<void> | undefined {\n  isSSR && setInSSRSetupState(isSSR)\n\n  const { props, children } = instance.vnode\n  const isStateful = isStatefulComponent(instance)\n  initProps(instance, props, isStateful, isSSR)\n  initSlots(instance, children, optimized || isSSR)\n\n  const setupResult = isStateful\n    ? setupStatefulComponent(instance, isSSR)\n    : undefined\n\n  isSSR && setInSSRSetupState(false)\n  return setupResult\n}\n\nfunction setupStatefulComponent(\n  instance: ComponentInternalInstance,\n  isSSR: boolean,\n) {\n  const Component = instance.type as ComponentOptions\n\n  if (__DEV__) {\n    if (Component.name) {\n      validateComponentName(Component.name, instance.appContext.config)\n    }\n    if (Component.components) {\n      const names = Object.keys(Component.components)\n      for (let i = 0; i < names.length; i++) {\n        validateComponentName(names[i], instance.appContext.config)\n      }\n    }\n    if (Component.directives) {\n      const names = Object.keys(Component.directives)\n      for (let i = 0; i < names.length; i++) {\n        validateDirectiveName(names[i])\n      }\n    }\n    if (Component.compilerOptions && isRuntimeOnly()) {\n      warn(\n        `\"compilerOptions\" is only supported when using a build of Vue that ` +\n          `includes the runtime compiler. Since you are using a runtime-only ` +\n          `build, the options should be passed via your build tool config instead.`,\n      )\n    }\n  }\n  // 0. create render proxy property access cache\n  instance.accessCache = Object.create(null)\n  // 1. create public instance / render proxy\n  instance.proxy = new Proxy(instance.ctx, PublicInstanceProxyHandlers)\n  if (__DEV__) {\n    exposePropsOnRenderContext(instance)\n  }\n  // 2. call setup()\n  const { setup } = Component\n  if (setup) {\n    pauseTracking()\n    const setupContext = (instance.setupContext =\n      setup.length > 1 ? createSetupContext(instance) : null)\n    const reset = setCurrentInstance(instance)\n    const setupResult = callWithErrorHandling(\n      setup,\n      instance,\n      ErrorCodes.SETUP_FUNCTION,\n      [\n        __DEV__ ? shallowReadonly(instance.props) : instance.props,\n        setupContext,\n      ],\n    )\n    const isAsyncSetup = isPromise(setupResult)\n    resetTracking()\n    reset()\n\n    if ((isAsyncSetup || instance.sp) && !isAsyncWrapper(instance)) {\n      // async setup / serverPrefetch, mark as async boundary for useId()\n      markAsyncBoundary(instance)\n    }\n\n    if (isAsyncSetup) {\n      setupResult.then(unsetCurrentInstance, unsetCurrentInstance)\n      if (isSSR) {\n        // return the promise so server-renderer can wait on it\n        return setupResult\n          .then((resolvedResult: unknown) => {\n            handleSetupResult(instance, resolvedResult, isSSR)\n          })\n          .catch(e => {\n            handleError(e, instance, ErrorCodes.SETUP_FUNCTION)\n          })\n      } else if (__FEATURE_SUSPENSE__) {\n        // async setup returned Promise.\n        // bail here and wait for re-entry.\n        instance.asyncDep = setupResult\n        if (__DEV__ && !instance.suspense) {\n          const name = formatComponentName(instance, Component)\n          warn(\n            `Component <${name}>: setup function returned a promise, but no ` +\n              `<Suspense> boundary was found in the parent component tree. ` +\n              `A component with async setup() must be nested in a <Suspense> ` +\n              `in order to be rendered.`,\n          )\n        }\n      } else if (__DEV__) {\n        warn(\n          `setup() returned a Promise, but the version of Vue you are using ` +\n            `does not support it yet.`,\n        )\n      }\n    } else {\n      handleSetupResult(instance, setupResult, isSSR)\n    }\n  } else {\n    finishComponentSetup(instance, isSSR)\n  }\n}\n\nexport function handleSetupResult(\n  instance: ComponentInternalInstance,\n  setupResult: unknown,\n  isSSR: boolean,\n): void {\n  if (isFunction(setupResult)) {\n    // setup returned an inline render function\n    if (__SSR__ && (instance.type as ComponentOptions).__ssrInlineRender) {\n      // when the function's name is `ssrRender` (compiled by SFC inline mode),\n      // set it as ssrRender instead.\n      instance.ssrRender = setupResult\n    } else {\n      instance.render = setupResult as InternalRenderFunction\n    }\n  } else if (isObject(setupResult)) {\n    if (__DEV__ && isVNode(setupResult)) {\n      warn(\n        `setup() should not return VNodes directly - ` +\n          `return a render function instead.`,\n      )\n    }\n    // setup returned bindings.\n    // assuming a render function compiled from template is present.\n    if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {\n      instance.devtoolsRawSetupState = setupResult\n    }\n    instance.setupState = proxyRefs(setupResult)\n    if (__DEV__) {\n      exposeSetupStateOnRenderContext(instance)\n    }\n  } else if (__DEV__ && setupResult !== undefined) {\n    warn(\n      `setup() should return an object. Received: ${\n        setupResult === null ? 'null' : typeof setupResult\n      }`,\n    )\n  }\n  finishComponentSetup(instance, isSSR)\n}\n\ntype CompileFunction = (\n  template: string | object,\n  options?: CompilerOptions,\n) => InternalRenderFunction\n\nlet compile: CompileFunction | undefined\nlet installWithProxy: (i: ComponentInternalInstance) => void\n\n/**\n * For runtime-dom to register the compiler.\n * Note the exported method uses any to avoid d.ts relying on the compiler types.\n */\nexport function registerRuntimeCompiler(_compile: any): void {\n  compile = _compile\n  installWithProxy = i => {\n    if (i.render!._rc) {\n      i.withProxy = new Proxy(i.ctx, RuntimeCompiledPublicInstanceProxyHandlers)\n    }\n  }\n}\n\n// dev only\nexport const isRuntimeOnly = (): boolean => !compile\n\nexport function finishComponentSetup(\n  instance: ComponentInternalInstance,\n  isSSR: boolean,\n  skipOptions?: boolean,\n): void {\n  const Component = instance.type as ComponentOptions\n\n  if (__COMPAT__) {\n    convertLegacyRenderFn(instance)\n\n    if (__DEV__ && Component.compatConfig) {\n      validateCompatConfig(Component.compatConfig)\n    }\n  }\n\n  // template / render function normalization\n  // could be already set when returned from setup()\n  if (!instance.render) {\n    // only do on-the-fly compile if not in SSR - SSR on-the-fly compilation\n    // is done by server-renderer\n    if (!isSSR && compile && !Component.render) {\n      const template =\n        (__COMPAT__ &&\n          instance.vnode.props &&\n          instance.vnode.props['inline-template']) ||\n        Component.template ||\n        (__FEATURE_OPTIONS_API__ && resolveMergedOptions(instance).template)\n      if (template) {\n        if (__DEV__) {\n          startMeasure(instance, `compile`)\n        }\n        const { isCustomElement, compilerOptions } = instance.appContext.config\n        const { delimiters, compilerOptions: componentCompilerOptions } =\n          Component\n        const finalCompilerOptions: CompilerOptions = extend(\n          extend(\n            {\n              isCustomElement,\n              delimiters,\n            },\n            compilerOptions,\n          ),\n          componentCompilerOptions,\n        )\n        if (__COMPAT__) {\n          // pass runtime compat config into the compiler\n          finalCompilerOptions.compatConfig = Object.create(globalCompatConfig)\n          if (Component.compatConfig) {\n            // @ts-expect-error types are not compatible\n            extend(finalCompilerOptions.compatConfig, Component.compatConfig)\n          }\n        }\n        Component.render = compile(template, finalCompilerOptions)\n        if (__DEV__) {\n          endMeasure(instance, `compile`)\n        }\n      }\n    }\n\n    instance.render = (Component.render || NOOP) as InternalRenderFunction\n\n    // for runtime-compiled render functions using `with` blocks, the render\n    // proxy used needs a different `has` handler which is more performant and\n    // also only allows a whitelist of globals to fallthrough.\n    if (installWithProxy) {\n      installWithProxy(instance)\n    }\n  }\n\n  // support for 2.x options\n  if (__FEATURE_OPTIONS_API__ && !(__COMPAT__ && skipOptions)) {\n    const reset = setCurrentInstance(instance)\n    pauseTracking()\n    try {\n      applyOptions(instance)\n    } finally {\n      resetTracking()\n      reset()\n    }\n  }\n\n  // warn missing template/render\n  // the runtime compilation of template in SSR is done by server-render\n  if (__DEV__ && !Component.render && instance.render === NOOP && !isSSR) {\n    if (!compile && Component.template) {\n      /* v8 ignore start */\n      warn(\n        `Component provided template option but ` +\n          `runtime compilation is not supported in this build of Vue.` +\n          (__ESM_BUNDLER__\n            ? ` Configure your bundler to alias \"vue\" to \"vue/dist/vue.esm-bundler.js\".`\n            : __ESM_BROWSER__\n              ? ` Use \"vue.esm-browser.js\" instead.`\n              : __GLOBAL__\n                ? ` Use \"vue.global.js\" instead.`\n                : ``) /* should not happen */,\n      )\n      /* v8 ignore stop */\n    } else {\n      warn(`Component is missing template or render function: `, Component)\n    }\n  }\n}\n\nconst attrsProxyHandlers = __DEV__\n  ? {\n      get(target: Data, key: string) {\n        markAttrsAccessed()\n        track(target, TrackOpTypes.GET, '')\n        return target[key]\n      },\n      set() {\n        warn(`setupContext.attrs is readonly.`)\n        return false\n      },\n      deleteProperty() {\n        warn(`setupContext.attrs is readonly.`)\n        return false\n      },\n    }\n  : {\n      get(target: Data, key: string) {\n        track(target, TrackOpTypes.GET, '')\n        return target[key]\n      },\n    }\n\n/**\n * Dev-only\n */\nfunction getSlotsProxy(instance: ComponentInternalInstance): Slots {\n  return new Proxy(instance.slots, {\n    get(target, key: string) {\n      track(instance, TrackOpTypes.GET, '$slots')\n      return target[key]\n    },\n  })\n}\n\nexport function createSetupContext(\n  instance: ComponentInternalInstance,\n): SetupContext {\n  const expose: SetupContext['expose'] = exposed => {\n    if (__DEV__) {\n      if (instance.exposed) {\n        warn(`expose() should be called only once per setup().`)\n      }\n      if (exposed != null) {\n        let exposedType: string = typeof exposed\n        if (exposedType === 'object') {\n          if (isArray(exposed)) {\n            exposedType = 'array'\n          } else if (isRef(exposed)) {\n            exposedType = 'ref'\n          }\n        }\n        if (exposedType !== 'object') {\n          warn(\n            `expose() should be passed a plain object, received ${exposedType}.`,\n          )\n        }\n      }\n    }\n    instance.exposed = exposed || {}\n  }\n\n  if (__DEV__) {\n    // We use getters in dev in case libs like test-utils overwrite instance\n    // properties (overwrites should not be done in prod)\n    let attrsProxy: Attrs\n    let slotsProxy: Slots\n    return Object.freeze({\n      get attrs() {\n        return (\n          attrsProxy ||\n          (attrsProxy = new Proxy(instance.attrs, attrsProxyHandlers) as Attrs)\n        )\n      },\n      get slots() {\n        return slotsProxy || (slotsProxy = getSlotsProxy(instance))\n      },\n      get emit() {\n        return (event: string, ...args: any[]) => instance.emit(event, ...args)\n      },\n      expose,\n    })\n  } else {\n    return {\n      attrs: new Proxy(instance.attrs, attrsProxyHandlers) as Attrs,\n      slots: instance.slots,\n      emit: instance.emit,\n      expose,\n    }\n  }\n}\n\nexport function getComponentPublicInstance(\n  instance: ComponentInternalInstance,\n): ComponentPublicInstance | ComponentInternalInstance['exposed'] | null {\n  if (instance.exposed) {\n    return (\n      instance.exposeProxy ||\n      (instance.exposeProxy = new Proxy(proxyRefs(markRaw(instance.exposed)), {\n        get(target, key: string) {\n          if (key in target) {\n            return target[key]\n          } else if (key in publicPropertiesMap) {\n            return publicPropertiesMap[key](instance)\n          }\n        },\n        has(target, key: string) {\n          return key in target || key in publicPropertiesMap\n        },\n      }))\n    )\n  } else {\n    return instance.proxy\n  }\n}\n\nconst classifyRE = /(?:^|[-_])\\w/g\nconst classify = (str: string): string =>\n  str.replace(classifyRE, c => c.toUpperCase()).replace(/[-_]/g, '')\n\nexport function getComponentName(\n  Component: ConcreteComponent,\n  includeInferred = true,\n): string | false | undefined {\n  return isFunction(Component)\n    ? Component.displayName || Component.name\n    : Component.name || (includeInferred && Component.__name)\n}\n\nexport function formatComponentName(\n  instance: ComponentInternalInstance | null,\n  Component: ConcreteComponent,\n  isRoot = false,\n): string {\n  let name = getComponentName(Component)\n  if (!name && Component.__file) {\n    const match = Component.__file.match(/([^/\\\\]+)\\.\\w+$/)\n    if (match) {\n      name = match[1]\n    }\n  }\n\n  if (!name && instance) {\n    // try to infer the name based on reverse resolution\n    const inferFromRegistry = (\n      registry: Record<string, any> | undefined | null,\n    ) => {\n      for (const key in registry) {\n        if (registry[key] === Component) {\n          return key\n        }\n      }\n    }\n    name =\n      inferFromRegistry(instance.components) ||\n      (instance.parent &&\n        inferFromRegistry(\n          (instance.parent.type as ComponentOptions).components,\n        )) ||\n      inferFromRegistry(instance.appContext.components)\n  }\n\n  return name ? classify(name) : isRoot ? `App` : `Anonymous`\n}\n\nexport function isClassComponent(value: unknown): value is ClassComponent {\n  return isFunction(value) && '__vccOpts' in value\n}\n\nexport interface ComponentCustomElementInterface {\n  /**\n   * @internal\n   */\n  _isVueCE: boolean\n  /**\n   * @internal\n   */\n  _injectChildStyle(type: ConcreteComponent, parent?: ConcreteComponent): void\n  /**\n   * @internal\n   */\n  _removeChildStyle(type: ConcreteComponent): void\n  /**\n   * @internal\n   */\n  _setProp(\n    key: string,\n    val: any,\n    shouldReflect?: boolean,\n    shouldUpdate?: boolean,\n  ): void\n  /**\n   * @internal\n   */\n  _beginPatch(): void\n  /**\n   * @internal\n   */\n  _endPatch(): void\n  /**\n   * @internal attached by the nested Teleport when shadowRoot is false.\n   */\n  _teleportTargets?: Set<RendererElement>\n  /**\n   * @internal check if shadow root is enabled\n   */\n  _hasShadowRoot(): boolean\n}\n"
  },
  {
    "path": "packages/runtime-core/src/componentEmits.ts",
    "content": "import {\n  EMPTY_OBJ,\n  type OverloadParameters,\n  type UnionToIntersection,\n  camelize,\n  extend,\n  hasOwn,\n  hyphenate,\n  isArray,\n  isFunction,\n  isObject,\n  isOn,\n  isString,\n  looseToNumber,\n  toHandlerKey,\n} from '@vue/shared'\nimport {\n  type ComponentInternalInstance,\n  type ComponentOptions,\n  type ConcreteComponent,\n  formatComponentName,\n} from './component'\nimport { ErrorCodes, callWithAsyncErrorHandling } from './errorHandling'\nimport { warn } from './warning'\nimport { devtoolsComponentEmit } from './devtools'\nimport type { AppContext } from './apiCreateApp'\nimport { emit as compatInstanceEmit } from './compat/instanceEventEmitter'\nimport {\n  compatModelEmit,\n  compatModelEventPrefix,\n} from './compat/componentVModel'\nimport type { ComponentTypeEmits } from './apiSetupHelpers'\nimport { getModelModifiers } from './helpers/useModel'\nimport type { ComponentPublicInstance } from './componentPublicInstance'\n\nexport type ObjectEmitsOptions = Record<\n  string,\n  ((...args: any[]) => any) | null\n>\n\nexport type EmitsOptions = ObjectEmitsOptions | string[]\n\nexport type EmitsToProps<T extends EmitsOptions | ComponentTypeEmits> =\n  T extends string[]\n    ? {\n        [K in `on${Capitalize<T[number]>}`]?: (...args: any[]) => any\n      }\n    : T extends ObjectEmitsOptions\n      ? {\n          [K in string & keyof T as `on${Capitalize<K>}`]?: (\n            ...args: T[K] extends (...args: infer P) => any\n              ? P\n              : T[K] extends null\n                ? any[]\n                : never\n          ) => any\n        }\n      : {}\n\nexport type TypeEmitsToOptions<T extends ComponentTypeEmits> = {\n  [K in keyof T & string]: T[K] extends [...args: infer Args]\n    ? (...args: Args) => any\n    : () => any\n} & (T extends (...args: any[]) => any\n  ? ParametersToFns<OverloadParameters<T>>\n  : {})\n\ntype ParametersToFns<T extends any[]> = {\n  [K in T[0]]: IsStringLiteral<K> extends true\n    ? (\n        ...args: T extends [e: infer E, ...args: infer P]\n          ? K extends E\n            ? P\n            : never\n          : never\n      ) => any\n    : never\n}\n\ntype IsStringLiteral<T> = T extends string\n  ? string extends T\n    ? false\n    : true\n  : false\n\nexport type ShortEmitsToObject<E> =\n  E extends Record<string, any[]>\n    ? {\n        [K in keyof E]: (...args: E[K]) => any\n      }\n    : E\n\nexport type EmitFn<\n  Options = ObjectEmitsOptions,\n  Event extends keyof Options = keyof Options,\n> =\n  Options extends Array<infer V>\n    ? (event: V, ...args: any[]) => void\n    : {} extends Options // if the emit is empty object (usually the default value for emit) should be converted to function\n      ? (event: string, ...args: any[]) => void\n      : UnionToIntersection<\n          {\n            [key in Event]: Options[key] extends (...args: infer Args) => any\n              ? (event: key, ...args: Args) => void\n              : Options[key] extends any[]\n                ? (event: key, ...args: Options[key]) => void\n                : (event: key, ...args: any[]) => void\n          }[Event]\n        >\n\nexport function emit(\n  instance: ComponentInternalInstance,\n  event: string,\n  ...rawArgs: any[]\n): ComponentPublicInstance | null | undefined {\n  if (instance.isUnmounted) return\n  const props = instance.vnode.props || EMPTY_OBJ\n\n  if (__DEV__) {\n    const {\n      emitsOptions,\n      propsOptions: [propsOptions],\n    } = instance\n    if (emitsOptions) {\n      if (\n        !(event in emitsOptions) &&\n        !(\n          __COMPAT__ &&\n          (event.startsWith('hook:') ||\n            event.startsWith(compatModelEventPrefix))\n        )\n      ) {\n        if (!propsOptions || !(toHandlerKey(camelize(event)) in propsOptions)) {\n          warn(\n            `Component emitted event \"${event}\" but it is neither declared in ` +\n              `the emits option nor as an \"${toHandlerKey(camelize(event))}\" prop.`,\n          )\n        }\n      } else {\n        const validator = emitsOptions[event]\n        if (isFunction(validator)) {\n          const isValid = validator(...rawArgs)\n          if (!isValid) {\n            warn(\n              `Invalid event arguments: event validation failed for event \"${event}\".`,\n            )\n          }\n        }\n      }\n    }\n  }\n\n  let args = rawArgs\n  const isCompatModelListener =\n    __COMPAT__ && compatModelEventPrefix + event in props\n  const isModelListener = isCompatModelListener || event.startsWith('update:')\n  const modifiers = isCompatModelListener\n    ? props.modelModifiers\n    : isModelListener && getModelModifiers(props, event.slice(7))\n\n  // for v-model update:xxx events, apply modifiers on args\n  if (modifiers) {\n    if (modifiers.trim) {\n      args = rawArgs.map(a => (isString(a) ? a.trim() : a))\n    }\n    if (modifiers.number) {\n      args = rawArgs.map(looseToNumber)\n    }\n  }\n\n  if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {\n    devtoolsComponentEmit(instance, event, args)\n  }\n\n  if (__DEV__) {\n    const lowerCaseEvent = event.toLowerCase()\n    if (lowerCaseEvent !== event && props[toHandlerKey(lowerCaseEvent)]) {\n      warn(\n        `Event \"${lowerCaseEvent}\" is emitted in component ` +\n          `${formatComponentName(\n            instance,\n            instance.type,\n          )} but the handler is registered for \"${event}\". ` +\n          `Note that HTML attributes are case-insensitive and you cannot use ` +\n          `v-on to listen to camelCase events when using in-DOM templates. ` +\n          `You should probably use \"${hyphenate(\n            event,\n          )}\" instead of \"${event}\".`,\n      )\n    }\n  }\n\n  let handlerName\n  let handler =\n    props[(handlerName = toHandlerKey(event))] ||\n    // also try camelCase event handler (#2249)\n    props[(handlerName = toHandlerKey(camelize(event)))]\n  // for v-model update:xxx events, also trigger kebab-case equivalent\n  // for props passed via kebab-case\n  if (!handler && isModelListener) {\n    handler = props[(handlerName = toHandlerKey(hyphenate(event)))]\n  }\n\n  if (handler) {\n    callWithAsyncErrorHandling(\n      handler,\n      instance,\n      ErrorCodes.COMPONENT_EVENT_HANDLER,\n      args,\n    )\n  }\n\n  const onceHandler = props[handlerName + `Once`]\n  if (onceHandler) {\n    if (!instance.emitted) {\n      instance.emitted = {}\n    } else if (instance.emitted[handlerName]) {\n      return\n    }\n    instance.emitted[handlerName] = true\n    callWithAsyncErrorHandling(\n      onceHandler,\n      instance,\n      ErrorCodes.COMPONENT_EVENT_HANDLER,\n      args,\n    )\n  }\n\n  if (__COMPAT__) {\n    compatModelEmit(instance, event, args)\n    return compatInstanceEmit(instance, event, args)\n  }\n}\n\nconst mixinEmitsCache = new WeakMap<ConcreteComponent, ObjectEmitsOptions>()\nexport function normalizeEmitsOptions(\n  comp: ConcreteComponent,\n  appContext: AppContext,\n  asMixin = false,\n): ObjectEmitsOptions | null {\n  const cache =\n    __FEATURE_OPTIONS_API__ && asMixin ? mixinEmitsCache : appContext.emitsCache\n  const cached = cache.get(comp)\n  if (cached !== undefined) {\n    return cached\n  }\n\n  const raw = comp.emits\n  let normalized: ObjectEmitsOptions = {}\n\n  // apply mixin/extends props\n  let hasExtends = false\n  if (__FEATURE_OPTIONS_API__ && !isFunction(comp)) {\n    const extendEmits = (raw: ComponentOptions) => {\n      const normalizedFromExtend = normalizeEmitsOptions(raw, appContext, true)\n      if (normalizedFromExtend) {\n        hasExtends = true\n        extend(normalized, normalizedFromExtend)\n      }\n    }\n    if (!asMixin && appContext.mixins.length) {\n      appContext.mixins.forEach(extendEmits)\n    }\n    if (comp.extends) {\n      extendEmits(comp.extends)\n    }\n    if (comp.mixins) {\n      comp.mixins.forEach(extendEmits)\n    }\n  }\n\n  if (!raw && !hasExtends) {\n    if (isObject(comp)) {\n      cache.set(comp, null)\n    }\n    return null\n  }\n\n  if (isArray(raw)) {\n    raw.forEach(key => (normalized[key] = null))\n  } else {\n    extend(normalized, raw)\n  }\n\n  if (isObject(comp)) {\n    cache.set(comp, normalized)\n  }\n  return normalized\n}\n\n// Check if an incoming prop key is a declared emit event listener.\n// e.g. With `emits: { click: null }`, props named `onClick` and `onclick` are\n// both considered matched listeners.\nexport function isEmitListener(\n  options: ObjectEmitsOptions | null,\n  key: string,\n): boolean {\n  if (!options || !isOn(key)) {\n    return false\n  }\n\n  if (__COMPAT__ && key.startsWith(compatModelEventPrefix)) {\n    return true\n  }\n\n  key = key.slice(2).replace(/Once$/, '')\n  return (\n    hasOwn(options, key[0].toLowerCase() + key.slice(1)) ||\n    hasOwn(options, hyphenate(key)) ||\n    hasOwn(options, key)\n  )\n}\n"
  },
  {
    "path": "packages/runtime-core/src/componentOptions.ts",
    "content": "import {\n  type Component,\n  type ComponentInternalInstance,\n  type ComponentInternalOptions,\n  type ConcreteComponent,\n  type Data,\n  type InternalRenderFunction,\n  type SetupContext,\n  currentInstance,\n} from './component'\nimport {\n  type LooseRequired,\n  NOOP,\n  type Prettify,\n  extend,\n  isArray,\n  isFunction,\n  isObject,\n  isPromise,\n  isString,\n} from '@vue/shared'\nimport { type Ref, getCurrentScope, isRef, traverse } from '@vue/reactivity'\nimport { computed } from './apiComputed'\nimport {\n  type WatchCallback,\n  type WatchOptions,\n  createPathGetter,\n  watch,\n} from './apiWatch'\nimport { inject, provide } from './apiInject'\nimport {\n  type DebuggerHook,\n  type ErrorCapturedHook,\n  onActivated,\n  onBeforeMount,\n  onBeforeUnmount,\n  onBeforeUpdate,\n  onDeactivated,\n  onErrorCaptured,\n  onMounted,\n  onRenderTracked,\n  onRenderTriggered,\n  onServerPrefetch,\n  onUnmounted,\n  onUpdated,\n} from './apiLifecycle'\nimport {\n  type ComputedGetter,\n  type WritableComputedOptions,\n  reactive,\n} from '@vue/reactivity'\nimport type {\n  ComponentObjectPropsOptions,\n  ComponentPropsOptions,\n  ExtractDefaultPropTypes,\n  ExtractPropTypes,\n} from './componentProps'\nimport type {\n  EmitsOptions,\n  EmitsToProps,\n  TypeEmitsToOptions,\n} from './componentEmits'\nimport type { Directive } from './directives'\nimport {\n  type ComponentPublicInstance,\n  type CreateComponentPublicInstanceWithMixins,\n  type IntersectionMixin,\n  type UnwrapMixinsType,\n  isReservedPrefix,\n} from './componentPublicInstance'\nimport { warn } from './warning'\nimport type { VNodeChild } from './vnode'\nimport { callWithAsyncErrorHandling } from './errorHandling'\nimport { deepMergeData } from './compat/data'\nimport { DeprecationTypes, checkCompatEnabled } from './compat/compatConfig'\nimport {\n  type CompatConfig,\n  isCompatEnabled,\n  softAssertCompatEnabled,\n} from './compat/compatConfig'\nimport type { OptionMergeFunction } from './apiCreateApp'\nimport { LifecycleHooks } from './enums'\nimport type { SlotsType } from './componentSlots'\nimport {\n  type ComponentTypeEmits,\n  normalizePropsOrEmits,\n} from './apiSetupHelpers'\nimport { markAsyncBoundary } from './helpers/useId'\n\n/**\n * Interface for declaring custom options.\n *\n * @example\n * ```ts\n * declare module 'vue' {\n *   interface ComponentCustomOptions {\n *     beforeRouteUpdate?(\n *       to: Route,\n *       from: Route,\n *       next: () => void\n *     ): void\n *   }\n * }\n * ```\n */\nexport interface ComponentCustomOptions {}\n\nexport type RenderFunction = () => VNodeChild\n\nexport interface ComponentOptionsBase<\n  Props,\n  RawBindings,\n  D,\n  C extends ComputedOptions,\n  M extends MethodOptions,\n  Mixin extends ComponentOptionsMixin,\n  Extends extends ComponentOptionsMixin,\n  E extends EmitsOptions,\n  EE extends string = string,\n  Defaults = {},\n  I extends ComponentInjectOptions = {},\n  II extends string = string,\n  S extends SlotsType = {},\n  LC extends Record<string, Component> = {},\n  Directives extends Record<string, Directive> = {},\n  Exposed extends string = string,\n  Provide extends ComponentProvideOptions = ComponentProvideOptions,\n>\n  extends\n    LegacyOptions<Props, D, C, M, Mixin, Extends, I, II, Provide>,\n    ComponentInternalOptions,\n    ComponentCustomOptions {\n  setup?: (\n    this: void,\n    props: LooseRequired<\n      Props &\n        Prettify<\n          UnwrapMixinsType<\n            IntersectionMixin<Mixin> & IntersectionMixin<Extends>,\n            'P'\n          >\n        >\n    >,\n    ctx: SetupContext<E, S>,\n  ) => Promise<RawBindings> | RawBindings | RenderFunction | void\n  name?: string\n  template?: string | object // can be a direct DOM node\n  // Note: we are intentionally using the signature-less `Function` type here\n  // since any type with signature will cause the whole inference to fail when\n  // the return expression contains reference to `this`.\n  // Luckily `render()` doesn't need any arguments nor does it care about return\n  // type.\n  render?: Function\n  // NOTE: extending both LC and Record<string, Component> allows objects to be forced\n  // to be of type Component, while still inferring LC generic\n  components?: LC & Record<string, Component>\n  // NOTE: extending both Directives and Record<string, Directive> allows objects to be forced\n  // to be of type Directive, while still inferring Directives generic\n  directives?: Directives & Record<string, Directive>\n  inheritAttrs?: boolean\n  emits?: (E | EE[]) & ThisType<void>\n  slots?: S\n  expose?: Exposed[]\n  serverPrefetch?(): void | Promise<any>\n\n  // Runtime compiler only -----------------------------------------------------\n  compilerOptions?: RuntimeCompilerOptions\n\n  // Internal ------------------------------------------------------------------\n\n  /**\n   * SSR only. This is produced by compiler-ssr and attached in compiler-sfc\n   * not user facing, so the typing is lax and for test only.\n   * @internal\n   */\n  ssrRender?: (\n    ctx: any,\n    push: (item: any) => void,\n    parentInstance: ComponentInternalInstance,\n    attrs: Data | undefined,\n    // for compiler-optimized bindings\n    $props: ComponentInternalInstance['props'],\n    $setup: ComponentInternalInstance['setupState'],\n    $data: ComponentInternalInstance['data'],\n    $options: ComponentInternalInstance['ctx'],\n  ) => void\n\n  /**\n   * Only generated by compiler-sfc to mark a ssr render function inlined and\n   * returned from setup()\n   * @internal\n   */\n  __ssrInlineRender?: boolean\n\n  /**\n   * marker for AsyncComponentWrapper\n   * @internal\n   */\n  __asyncLoader?: () => Promise<ConcreteComponent>\n  /**\n   * the inner component resolved by the AsyncComponentWrapper\n   * @internal\n   */\n  __asyncResolved?: ConcreteComponent\n  /**\n   * Exposed for lazy hydration\n   * @internal\n   */\n  __asyncHydrate?: (\n    el: Element,\n    instance: ComponentInternalInstance,\n    hydrate: () => void,\n  ) => void\n\n  // Type differentiators ------------------------------------------------------\n\n  // Note these are internal but need to be exposed in d.ts for type inference\n  // to work!\n\n  // type-only differentiator to separate OptionWithoutProps from a constructor\n  // type returned by defineComponent() or FunctionalComponent\n  call?: (this: unknown, ...args: unknown[]) => never\n  // type-only differentiators for built-in Vnode types\n  __isFragment?: never\n  __isTeleport?: never\n  __isSuspense?: never\n\n  __defaults?: Defaults\n}\n\n/**\n * Subset of compiler options that makes sense for the runtime.\n */\nexport interface RuntimeCompilerOptions {\n  isCustomElement?: (tag: string) => boolean\n  whitespace?: 'preserve' | 'condense'\n  comments?: boolean\n  delimiters?: [string, string]\n}\n\nexport type ComponentOptions<\n  Props = {},\n  RawBindings = any,\n  D = any,\n  C extends ComputedOptions = any,\n  M extends MethodOptions = any,\n  Mixin extends ComponentOptionsMixin = any,\n  Extends extends ComponentOptionsMixin = any,\n  E extends EmitsOptions = any,\n  EE extends string = string,\n  Defaults = {},\n  I extends ComponentInjectOptions = {},\n  II extends string = string,\n  S extends SlotsType = {},\n  LC extends Record<string, Component> = {},\n  Directives extends Record<string, Directive> = {},\n  Exposed extends string = string,\n  Provide extends ComponentProvideOptions = ComponentProvideOptions,\n> = ComponentOptionsBase<\n  Props,\n  RawBindings,\n  D,\n  C,\n  M,\n  Mixin,\n  Extends,\n  E,\n  EE,\n  Defaults,\n  I,\n  II,\n  S,\n  LC,\n  Directives,\n  Exposed,\n  Provide\n> &\n  ThisType<\n    CreateComponentPublicInstanceWithMixins<\n      {},\n      RawBindings,\n      D,\n      C,\n      M,\n      Mixin,\n      Extends,\n      E,\n      Readonly<Props>,\n      Defaults,\n      false,\n      I,\n      S,\n      LC,\n      Directives\n    >\n  >\n\nexport type ComponentOptionsMixin = ComponentOptionsBase<\n  any,\n  any,\n  any,\n  any,\n  any,\n  any,\n  any,\n  any,\n  any,\n  any,\n  any,\n  any,\n  any,\n  any,\n  any,\n  any,\n  any\n>\n\nexport type ComputedOptions = Record<\n  string,\n  ComputedGetter<any> | WritableComputedOptions<any>\n>\n\nexport interface MethodOptions {\n  [key: string]: Function\n}\n\nexport type ExtractComputedReturns<T extends any> = {\n  [key in keyof T]: T[key] extends { get: (...args: any[]) => infer TReturn }\n    ? TReturn\n    : T[key] extends (...args: any[]) => infer TReturn\n      ? TReturn\n      : never\n}\n\nexport type ObjectWatchOptionItem = {\n  handler: WatchCallback | string\n} & WatchOptions\n\ntype WatchOptionItem = string | WatchCallback | ObjectWatchOptionItem\n\ntype ComponentWatchOptionItem = WatchOptionItem | WatchOptionItem[]\n\ntype ComponentWatchOptions = Record<string, ComponentWatchOptionItem>\n\nexport type ComponentProvideOptions = ObjectProvideOptions | Function\n\ntype ObjectProvideOptions = Record<string | symbol, unknown>\n\nexport type ComponentInjectOptions = string[] | ObjectInjectOptions\n\ntype ObjectInjectOptions = Record<\n  string | symbol,\n  string | symbol | { from?: string | symbol; default?: unknown }\n>\n\nexport type InjectToObject<T extends ComponentInjectOptions> =\n  T extends string[]\n    ? {\n        [K in T[number]]?: unknown\n      }\n    : T extends ObjectInjectOptions\n      ? {\n          [K in keyof T]?: unknown\n        }\n      : never\n\ninterface LegacyOptions<\n  Props,\n  D,\n  C extends ComputedOptions,\n  M extends MethodOptions,\n  Mixin extends ComponentOptionsMixin,\n  Extends extends ComponentOptionsMixin,\n  I extends ComponentInjectOptions,\n  II extends string,\n  Provide extends ComponentProvideOptions = ComponentProvideOptions,\n> {\n  compatConfig?: CompatConfig\n\n  // allow any custom options\n  [key: string]: any\n\n  // state\n  // Limitation: we cannot expose RawBindings on the `this` context for data\n  // since that leads to some sort of circular inference and breaks ThisType\n  // for the entire component.\n  data?: (\n    this: CreateComponentPublicInstanceWithMixins<\n      Props,\n      {},\n      {},\n      {},\n      MethodOptions,\n      Mixin,\n      Extends\n    >,\n    vm: CreateComponentPublicInstanceWithMixins<\n      Props,\n      {},\n      {},\n      {},\n      MethodOptions,\n      Mixin,\n      Extends\n    >,\n  ) => D\n  computed?: C\n  methods?: M\n  watch?: ComponentWatchOptions\n  provide?: Provide\n  inject?: I | II[]\n\n  // assets\n  filters?: Record<string, Function>\n\n  // composition\n  mixins?: Mixin[]\n  extends?: Extends\n\n  // lifecycle\n  beforeCreate?(): any\n  created?(): any\n  beforeMount?(): any\n  mounted?(): any\n  beforeUpdate?(): any\n  updated?(): any\n  activated?(): any\n  deactivated?(): any\n  /** @deprecated use `beforeUnmount` instead */\n  beforeDestroy?(): any\n  beforeUnmount?(): any\n  /** @deprecated use `unmounted` instead */\n  destroyed?(): any\n  unmounted?(): any\n  renderTracked?: DebuggerHook\n  renderTriggered?: DebuggerHook\n  errorCaptured?: ErrorCapturedHook\n\n  /**\n   * runtime compile only\n   * @deprecated use `compilerOptions.delimiters` instead.\n   */\n  delimiters?: [string, string]\n\n  /**\n   * #3468\n   *\n   * type-only, used to assist Mixin's type inference,\n   * TypeScript will try to simplify the inferred `Mixin` type,\n   * with the `__differentiator`, TypeScript won't be able to combine different mixins,\n   * because the `__differentiator` will be different\n   */\n  __differentiator?: keyof D | keyof C | keyof M\n}\n\ntype MergedHook<T = () => void> = T | T[]\n\nexport type MergedComponentOptions = ComponentOptions &\n  MergedComponentOptionsOverride\n\nexport type MergedComponentOptionsOverride = {\n  beforeCreate?: MergedHook\n  created?: MergedHook\n  beforeMount?: MergedHook\n  mounted?: MergedHook\n  beforeUpdate?: MergedHook\n  updated?: MergedHook\n  activated?: MergedHook\n  deactivated?: MergedHook\n  /** @deprecated use `beforeUnmount` instead */\n  beforeDestroy?: MergedHook\n  beforeUnmount?: MergedHook\n  /** @deprecated use `unmounted` instead */\n  destroyed?: MergedHook\n  unmounted?: MergedHook\n  renderTracked?: MergedHook<DebuggerHook>\n  renderTriggered?: MergedHook<DebuggerHook>\n  errorCaptured?: MergedHook<ErrorCapturedHook>\n}\n\nexport type OptionTypesKeys = 'P' | 'B' | 'D' | 'C' | 'M' | 'Defaults'\n\nexport type OptionTypesType<\n  P = {},\n  B = {},\n  D = {},\n  C extends ComputedOptions = {},\n  M extends MethodOptions = {},\n  Defaults = {},\n> = {\n  P: P\n  B: B\n  D: D\n  C: C\n  M: M\n  Defaults: Defaults\n}\n\nenum OptionTypes {\n  PROPS = 'Props',\n  DATA = 'Data',\n  COMPUTED = 'Computed',\n  METHODS = 'Methods',\n  INJECT = 'Inject',\n}\n\nfunction createDuplicateChecker() {\n  const cache = Object.create(null)\n  return (type: OptionTypes, key: string) => {\n    if (cache[key]) {\n      warn(`${type} property \"${key}\" is already defined in ${cache[key]}.`)\n    } else {\n      cache[key] = type\n    }\n  }\n}\n\nexport let shouldCacheAccess = true\n\nexport function applyOptions(instance: ComponentInternalInstance): void {\n  const options = resolveMergedOptions(instance)\n  const publicThis = instance.proxy! as any\n  const ctx = instance.ctx\n\n  // do not cache property access on public proxy during state initialization\n  shouldCacheAccess = false\n\n  // call beforeCreate first before accessing other options since\n  // the hook may mutate resolved options (#2791)\n  if (options.beforeCreate) {\n    callHook(options.beforeCreate, instance, LifecycleHooks.BEFORE_CREATE)\n  }\n\n  const {\n    // state\n    data: dataOptions,\n    computed: computedOptions,\n    methods,\n    watch: watchOptions,\n    provide: provideOptions,\n    inject: injectOptions,\n    // lifecycle\n    created,\n    beforeMount,\n    mounted,\n    beforeUpdate,\n    updated,\n    activated,\n    deactivated,\n    beforeDestroy,\n    beforeUnmount,\n    destroyed,\n    unmounted,\n    render,\n    renderTracked,\n    renderTriggered,\n    errorCaptured,\n    serverPrefetch,\n    // public API\n    expose,\n    inheritAttrs,\n    // assets\n    components,\n    directives,\n    filters,\n  } = options\n\n  const checkDuplicateProperties = __DEV__ ? createDuplicateChecker() : null\n\n  if (__DEV__) {\n    const [propsOptions] = instance.propsOptions\n    if (propsOptions) {\n      for (const key in propsOptions) {\n        checkDuplicateProperties!(OptionTypes.PROPS, key)\n      }\n    }\n  }\n\n  // options initialization order (to be consistent with Vue 2):\n  // - props (already done outside of this function)\n  // - inject\n  // - methods\n  // - data (deferred since it relies on `this` access)\n  // - computed\n  // - watch (deferred since it relies on `this` access)\n\n  if (injectOptions) {\n    resolveInjections(injectOptions, ctx, checkDuplicateProperties)\n  }\n\n  if (methods) {\n    for (const key in methods) {\n      const methodHandler = (methods as MethodOptions)[key]\n      if (isFunction(methodHandler)) {\n        // In dev mode, we use the `createRenderContext` function to define\n        // methods to the proxy target, and those are read-only but\n        // reconfigurable, so it needs to be redefined here\n        if (__DEV__) {\n          Object.defineProperty(ctx, key, {\n            value: methodHandler.bind(publicThis),\n            configurable: true,\n            enumerable: true,\n            writable: true,\n          })\n        } else {\n          ctx[key] = methodHandler.bind(publicThis)\n        }\n        if (__DEV__) {\n          checkDuplicateProperties!(OptionTypes.METHODS, key)\n        }\n      } else if (__DEV__) {\n        warn(\n          `Method \"${key}\" has type \"${typeof methodHandler}\" in the component definition. ` +\n            `Did you reference the function correctly?`,\n        )\n      }\n    }\n  }\n\n  if (dataOptions) {\n    if (__DEV__ && !isFunction(dataOptions)) {\n      warn(\n        `The data option must be a function. ` +\n          `Plain object usage is no longer supported.`,\n      )\n    }\n    const data = dataOptions.call(publicThis, publicThis)\n    if (__DEV__ && isPromise(data)) {\n      warn(\n        `data() returned a Promise - note data() cannot be async; If you ` +\n          `intend to perform data fetching before component renders, use ` +\n          `async setup() + <Suspense>.`,\n      )\n    }\n    if (!isObject(data)) {\n      __DEV__ && warn(`data() should return an object.`)\n    } else {\n      instance.data = reactive(data)\n      if (__DEV__) {\n        for (const key in data) {\n          checkDuplicateProperties!(OptionTypes.DATA, key)\n          // expose data on ctx during dev\n          if (!isReservedPrefix(key[0])) {\n            Object.defineProperty(ctx, key, {\n              configurable: true,\n              enumerable: true,\n              get: () => data[key],\n              set: NOOP,\n            })\n          }\n        }\n      }\n    }\n  }\n\n  // state initialization complete at this point - start caching access\n  shouldCacheAccess = true\n\n  if (computedOptions) {\n    for (const key in computedOptions) {\n      const opt = (computedOptions as ComputedOptions)[key]\n      const get = isFunction(opt)\n        ? opt.bind(publicThis, publicThis)\n        : isFunction(opt.get)\n          ? opt.get.bind(publicThis, publicThis)\n          : NOOP\n      if (__DEV__ && get === NOOP) {\n        warn(`Computed property \"${key}\" has no getter.`)\n      }\n      const set =\n        !isFunction(opt) && isFunction(opt.set)\n          ? opt.set.bind(publicThis)\n          : __DEV__\n            ? () => {\n                warn(\n                  `Write operation failed: computed property \"${key}\" is readonly.`,\n                )\n              }\n            : NOOP\n      const c = computed({\n        get,\n        set,\n      })\n      Object.defineProperty(ctx, key, {\n        enumerable: true,\n        configurable: true,\n        get: () => c.value,\n        set: v => (c.value = v),\n      })\n      if (__DEV__) {\n        checkDuplicateProperties!(OptionTypes.COMPUTED, key)\n      }\n    }\n  }\n\n  if (watchOptions) {\n    for (const key in watchOptions) {\n      createWatcher(watchOptions[key], ctx, publicThis, key)\n    }\n  }\n\n  if (provideOptions) {\n    const provides = isFunction(provideOptions)\n      ? provideOptions.call(publicThis)\n      : provideOptions\n    Reflect.ownKeys(provides).forEach(key => {\n      provide(key, provides[key])\n    })\n  }\n\n  if (created) {\n    callHook(created, instance, LifecycleHooks.CREATED)\n  }\n\n  function registerLifecycleHook(\n    register: Function,\n    hook?: Function | Function[],\n  ) {\n    if (isArray(hook)) {\n      hook.forEach(_hook => register(_hook.bind(publicThis)))\n    } else if (hook) {\n      register(hook.bind(publicThis))\n    }\n  }\n\n  registerLifecycleHook(onBeforeMount, beforeMount)\n  registerLifecycleHook(onMounted, mounted)\n  registerLifecycleHook(onBeforeUpdate, beforeUpdate)\n  registerLifecycleHook(onUpdated, updated)\n  registerLifecycleHook(onActivated, activated)\n  registerLifecycleHook(onDeactivated, deactivated)\n  registerLifecycleHook(onErrorCaptured, errorCaptured)\n  registerLifecycleHook(onRenderTracked, renderTracked)\n  registerLifecycleHook(onRenderTriggered, renderTriggered)\n  registerLifecycleHook(onBeforeUnmount, beforeUnmount)\n  registerLifecycleHook(onUnmounted, unmounted)\n  registerLifecycleHook(onServerPrefetch, serverPrefetch)\n\n  if (__COMPAT__) {\n    if (\n      beforeDestroy &&\n      softAssertCompatEnabled(DeprecationTypes.OPTIONS_BEFORE_DESTROY, instance)\n    ) {\n      registerLifecycleHook(onBeforeUnmount, beforeDestroy)\n    }\n    if (\n      destroyed &&\n      softAssertCompatEnabled(DeprecationTypes.OPTIONS_DESTROYED, instance)\n    ) {\n      registerLifecycleHook(onUnmounted, destroyed)\n    }\n  }\n\n  if (isArray(expose)) {\n    if (expose.length) {\n      const exposed = instance.exposed || (instance.exposed = {})\n      expose.forEach(key => {\n        Object.defineProperty(exposed, key, {\n          get: () => publicThis[key],\n          set: val => (publicThis[key] = val),\n          enumerable: true,\n        })\n      })\n    } else if (!instance.exposed) {\n      instance.exposed = {}\n    }\n  }\n\n  // options that are handled when creating the instance but also need to be\n  // applied from mixins\n  if (render && instance.render === NOOP) {\n    instance.render = render as InternalRenderFunction\n  }\n  if (inheritAttrs != null) {\n    instance.inheritAttrs = inheritAttrs\n  }\n\n  // asset options.\n  if (components) instance.components = components as any\n  if (directives) instance.directives = directives\n  if (\n    __COMPAT__ &&\n    filters &&\n    isCompatEnabled(DeprecationTypes.FILTERS, instance)\n  ) {\n    instance.filters = filters\n  }\n\n  if (__SSR__ && serverPrefetch) {\n    markAsyncBoundary(instance)\n  }\n}\n\nexport function resolveInjections(\n  injectOptions: ComponentInjectOptions,\n  ctx: any,\n  checkDuplicateProperties = NOOP as any,\n): void {\n  if (isArray(injectOptions)) {\n    injectOptions = normalizeInject(injectOptions)!\n  }\n  for (const key in injectOptions) {\n    const opt = injectOptions[key]\n    let injected: unknown\n    if (isObject(opt)) {\n      if ('default' in opt) {\n        injected = inject(\n          opt.from || key,\n          opt.default,\n          true /* treat default function as factory */,\n        )\n      } else {\n        injected = inject(opt.from || key)\n      }\n    } else {\n      injected = inject(opt)\n    }\n    if (isRef(injected)) {\n      // unwrap injected refs (ref #4196)\n      Object.defineProperty(ctx, key, {\n        enumerable: true,\n        configurable: true,\n        get: () => (injected as Ref).value,\n        set: v => ((injected as Ref).value = v),\n      })\n    } else {\n      ctx[key] = injected\n    }\n    if (__DEV__) {\n      checkDuplicateProperties!(OptionTypes.INJECT, key)\n    }\n  }\n}\n\nfunction callHook(\n  hook: Function,\n  instance: ComponentInternalInstance,\n  type: LifecycleHooks,\n) {\n  callWithAsyncErrorHandling(\n    isArray(hook)\n      ? hook.map(h => h.bind(instance.proxy!))\n      : hook.bind(instance.proxy!),\n    instance,\n    type,\n  )\n}\n\nexport function createWatcher(\n  raw: ComponentWatchOptionItem,\n  ctx: Data,\n  publicThis: ComponentPublicInstance,\n  key: string,\n): void {\n  let getter = key.includes('.')\n    ? createPathGetter(publicThis, key)\n    : () => publicThis[key as keyof typeof publicThis]\n\n  const options: WatchOptions = {}\n  if (__COMPAT__) {\n    const instance =\n      currentInstance && getCurrentScope() === currentInstance.scope\n        ? currentInstance\n        : null\n\n    const newValue = getter()\n    if (\n      isArray(newValue) &&\n      isCompatEnabled(DeprecationTypes.WATCH_ARRAY, instance)\n    ) {\n      options.deep = true\n    }\n\n    const baseGetter = getter\n    getter = () => {\n      const val = baseGetter()\n      if (\n        isArray(val) &&\n        checkCompatEnabled(DeprecationTypes.WATCH_ARRAY, instance)\n      ) {\n        traverse(val)\n      }\n      return val\n    }\n  }\n\n  if (isString(raw)) {\n    const handler = ctx[raw]\n    if (isFunction(handler)) {\n      if (__COMPAT__) {\n        watch(getter, handler as WatchCallback, options)\n      } else {\n        watch(getter, handler as WatchCallback)\n      }\n    } else if (__DEV__) {\n      warn(`Invalid watch handler specified by key \"${raw}\"`, handler)\n    }\n  } else if (isFunction(raw)) {\n    if (__COMPAT__) {\n      watch(getter, raw.bind(publicThis), options)\n    } else {\n      watch(getter, raw.bind(publicThis))\n    }\n  } else if (isObject(raw)) {\n    if (isArray(raw)) {\n      raw.forEach(r => createWatcher(r, ctx, publicThis, key))\n    } else {\n      const handler = isFunction(raw.handler)\n        ? raw.handler.bind(publicThis)\n        : (ctx[raw.handler] as WatchCallback)\n      if (isFunction(handler)) {\n        watch(getter, handler, __COMPAT__ ? extend(raw, options) : raw)\n      } else if (__DEV__) {\n        warn(`Invalid watch handler specified by key \"${raw.handler}\"`, handler)\n      }\n    }\n  } else if (__DEV__) {\n    warn(`Invalid watch option: \"${key}\"`, raw)\n  }\n}\n\n/**\n * Resolve merged options and cache it on the component.\n * This is done only once per-component since the merging does not involve\n * instances.\n */\nexport function resolveMergedOptions(\n  instance: ComponentInternalInstance,\n): MergedComponentOptions {\n  const base = instance.type as ComponentOptions\n  const { mixins, extends: extendsOptions } = base\n  const {\n    mixins: globalMixins,\n    optionsCache: cache,\n    config: { optionMergeStrategies },\n  } = instance.appContext\n  const cached = cache.get(base)\n\n  let resolved: MergedComponentOptions\n\n  if (cached) {\n    resolved = cached\n  } else if (!globalMixins.length && !mixins && !extendsOptions) {\n    if (\n      __COMPAT__ &&\n      isCompatEnabled(DeprecationTypes.PRIVATE_APIS, instance)\n    ) {\n      resolved = extend({}, base) as MergedComponentOptions\n      resolved.parent = instance.parent && instance.parent.proxy\n      resolved.propsData = instance.vnode.props\n    } else {\n      resolved = base as MergedComponentOptions\n    }\n  } else {\n    resolved = {}\n    if (globalMixins.length) {\n      globalMixins.forEach(m =>\n        mergeOptions(resolved, m, optionMergeStrategies, true),\n      )\n    }\n    mergeOptions(resolved, base, optionMergeStrategies)\n  }\n  if (isObject(base)) {\n    cache.set(base, resolved)\n  }\n  return resolved\n}\n\nexport function mergeOptions(\n  to: any,\n  from: any,\n  strats: Record<string, OptionMergeFunction>,\n  asMixin = false,\n): any {\n  if (__COMPAT__ && isFunction(from)) {\n    from = from.options\n  }\n\n  const { mixins, extends: extendsOptions } = from\n\n  if (extendsOptions) {\n    mergeOptions(to, extendsOptions, strats, true)\n  }\n  if (mixins) {\n    mixins.forEach((m: ComponentOptionsMixin) =>\n      mergeOptions(to, m, strats, true),\n    )\n  }\n\n  for (const key in from) {\n    if (asMixin && key === 'expose') {\n      __DEV__ &&\n        warn(\n          `\"expose\" option is ignored when declared in mixins or extends. ` +\n            `It should only be declared in the base component itself.`,\n        )\n    } else {\n      const strat = internalOptionMergeStrats[key] || (strats && strats[key])\n      to[key] = strat ? strat(to[key], from[key]) : from[key]\n    }\n  }\n  return to\n}\n\nexport const internalOptionMergeStrats: Record<string, Function> = {\n  data: mergeDataFn,\n  props: mergeEmitsOrPropsOptions,\n  emits: mergeEmitsOrPropsOptions,\n  // objects\n  methods: mergeObjectOptions,\n  computed: mergeObjectOptions,\n  // lifecycle\n  beforeCreate: mergeAsArray,\n  created: mergeAsArray,\n  beforeMount: mergeAsArray,\n  mounted: mergeAsArray,\n  beforeUpdate: mergeAsArray,\n  updated: mergeAsArray,\n  beforeDestroy: mergeAsArray,\n  beforeUnmount: mergeAsArray,\n  destroyed: mergeAsArray,\n  unmounted: mergeAsArray,\n  activated: mergeAsArray,\n  deactivated: mergeAsArray,\n  errorCaptured: mergeAsArray,\n  serverPrefetch: mergeAsArray,\n  // assets\n  components: mergeObjectOptions,\n  directives: mergeObjectOptions,\n  // watch\n  watch: mergeWatchOptions,\n  // provide / inject\n  provide: mergeDataFn,\n  inject: mergeInject,\n}\n\nif (__COMPAT__) {\n  internalOptionMergeStrats.filters = mergeObjectOptions\n}\n\nfunction mergeDataFn(to: any, from: any) {\n  if (!from) {\n    return to\n  }\n  if (!to) {\n    return from\n  }\n  return function mergedDataFn(this: ComponentPublicInstance) {\n    return (\n      __COMPAT__ && isCompatEnabled(DeprecationTypes.OPTIONS_DATA_MERGE, null)\n        ? deepMergeData\n        : extend\n    )(\n      isFunction(to) ? to.call(this, this) : to,\n      isFunction(from) ? from.call(this, this) : from,\n    )\n  }\n}\n\nfunction mergeInject(\n  to: ComponentInjectOptions | undefined,\n  from: ComponentInjectOptions,\n) {\n  return mergeObjectOptions(normalizeInject(to), normalizeInject(from))\n}\n\nfunction normalizeInject(\n  raw: ComponentInjectOptions | undefined,\n): ObjectInjectOptions | undefined {\n  if (isArray(raw)) {\n    const res: ObjectInjectOptions = {}\n    for (let i = 0; i < raw.length; i++) {\n      res[raw[i]] = raw[i]\n    }\n    return res\n  }\n  return raw\n}\n\nfunction mergeAsArray<T = Function>(to: T[] | T | undefined, from: T | T[]) {\n  return to ? [...new Set([].concat(to as any, from as any))] : from\n}\n\nfunction mergeObjectOptions(to: Object | undefined, from: Object | undefined) {\n  return to ? extend(Object.create(null), to, from) : from\n}\n\nfunction mergeEmitsOrPropsOptions(\n  to: EmitsOptions | undefined,\n  from: EmitsOptions | undefined,\n): EmitsOptions | undefined\nfunction mergeEmitsOrPropsOptions(\n  to: ComponentPropsOptions | undefined,\n  from: ComponentPropsOptions | undefined,\n): ComponentPropsOptions | undefined\nfunction mergeEmitsOrPropsOptions(\n  to: ComponentPropsOptions | EmitsOptions | undefined,\n  from: ComponentPropsOptions | EmitsOptions | undefined,\n) {\n  if (to) {\n    if (isArray(to) && isArray(from)) {\n      return [...new Set([...to, ...from])]\n    }\n    return extend(\n      Object.create(null),\n      normalizePropsOrEmits(to),\n      normalizePropsOrEmits(from ?? {}),\n    )\n  } else {\n    return from\n  }\n}\n\nfunction mergeWatchOptions(\n  to: ComponentWatchOptions | undefined,\n  from: ComponentWatchOptions | undefined,\n) {\n  if (!to) return from\n  if (!from) return to\n  const merged = extend(Object.create(null), to)\n  for (const key in from) {\n    merged[key] = mergeAsArray(to[key], from[key])\n  }\n  return merged\n}\n\n// Deprecated legacy types, kept because they were previously exported ---------\n\n/**\n * @deprecated\n */\nexport type ComponentOptionsWithoutProps<\n  Props = {},\n  RawBindings = {},\n  D = {},\n  C extends ComputedOptions = {},\n  M extends MethodOptions = {},\n  Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,\n  Extends extends ComponentOptionsMixin = ComponentOptionsMixin,\n  E extends EmitsOptions = {},\n  EE extends string = string,\n  I extends ComponentInjectOptions = {},\n  II extends string = string,\n  S extends SlotsType = {},\n  LC extends Record<string, Component> = {},\n  Directives extends Record<string, Directive> = {},\n  Exposed extends string = string,\n  Provide extends ComponentProvideOptions = ComponentProvideOptions,\n  TE extends ComponentTypeEmits = {},\n  ResolvedEmits extends EmitsOptions = {} extends E\n    ? TypeEmitsToOptions<TE>\n    : E,\n  PE = Props & EmitsToProps<ResolvedEmits>,\n> = ComponentOptionsBase<\n  PE,\n  RawBindings,\n  D,\n  C,\n  M,\n  Mixin,\n  Extends,\n  E,\n  EE,\n  {},\n  I,\n  II,\n  S,\n  LC,\n  Directives,\n  Exposed,\n  Provide\n> & {\n  props?: never\n  /**\n   * @private for language-tools use only\n   */\n  __typeProps?: Props\n  /**\n   * @private for language-tools use only\n   */\n  __typeEmits?: TE\n} & ThisType<\n    CreateComponentPublicInstanceWithMixins<\n      PE,\n      RawBindings,\n      D,\n      C,\n      M,\n      Mixin,\n      Extends,\n      ResolvedEmits,\n      EE,\n      {},\n      false,\n      I,\n      S,\n      LC,\n      Directives,\n      string\n    >\n  >\n\n/**\n * @deprecated\n */\nexport type ComponentOptionsWithArrayProps<\n  PropNames extends string = string,\n  RawBindings = {},\n  D = {},\n  C extends ComputedOptions = {},\n  M extends MethodOptions = {},\n  Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,\n  Extends extends ComponentOptionsMixin = ComponentOptionsMixin,\n  E extends EmitsOptions = EmitsOptions,\n  EE extends string = string,\n  I extends ComponentInjectOptions = {},\n  II extends string = string,\n  S extends SlotsType = {},\n  LC extends Record<string, Component> = {},\n  Directives extends Record<string, Directive> = {},\n  Exposed extends string = string,\n  Provide extends ComponentProvideOptions = ComponentProvideOptions,\n  Props = Prettify<Readonly<{ [key in PropNames]?: any } & EmitsToProps<E>>>,\n> = ComponentOptionsBase<\n  Props,\n  RawBindings,\n  D,\n  C,\n  M,\n  Mixin,\n  Extends,\n  E,\n  EE,\n  {},\n  I,\n  II,\n  S,\n  LC,\n  Directives,\n  Exposed,\n  Provide\n> & {\n  props: PropNames[]\n} & ThisType<\n    CreateComponentPublicInstanceWithMixins<\n      Props,\n      RawBindings,\n      D,\n      C,\n      M,\n      Mixin,\n      Extends,\n      E,\n      Props,\n      {},\n      false,\n      I,\n      S,\n      LC,\n      Directives,\n      string\n    >\n  >\n\n/**\n * @deprecated\n */\nexport type ComponentOptionsWithObjectProps<\n  PropsOptions = ComponentObjectPropsOptions,\n  RawBindings = {},\n  D = {},\n  C extends ComputedOptions = {},\n  M extends MethodOptions = {},\n  Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,\n  Extends extends ComponentOptionsMixin = ComponentOptionsMixin,\n  E extends EmitsOptions = EmitsOptions,\n  EE extends string = string,\n  I extends ComponentInjectOptions = {},\n  II extends string = string,\n  S extends SlotsType = {},\n  LC extends Record<string, Component> = {},\n  Directives extends Record<string, Directive> = {},\n  Exposed extends string = string,\n  Provide extends ComponentProvideOptions = ComponentProvideOptions,\n  Props = Prettify<\n    Readonly<ExtractPropTypes<PropsOptions>> & Readonly<EmitsToProps<E>>\n  >,\n  Defaults = ExtractDefaultPropTypes<PropsOptions>,\n> = ComponentOptionsBase<\n  Props,\n  RawBindings,\n  D,\n  C,\n  M,\n  Mixin,\n  Extends,\n  E,\n  EE,\n  Defaults,\n  I,\n  II,\n  S,\n  LC,\n  Directives,\n  Exposed,\n  Provide\n> & {\n  props: PropsOptions & ThisType<void>\n} & ThisType<\n    CreateComponentPublicInstanceWithMixins<\n      Props,\n      RawBindings,\n      D,\n      C,\n      M,\n      Mixin,\n      Extends,\n      E,\n      Props,\n      Defaults,\n      false,\n      I,\n      S,\n      LC,\n      Directives\n    >\n  >\n"
  },
  {
    "path": "packages/runtime-core/src/componentProps.ts",
    "content": "import {\n  TriggerOpTypes,\n  shallowReactive,\n  shallowReadonly,\n  toRaw,\n  trigger,\n} from '@vue/reactivity'\nimport {\n  EMPTY_ARR,\n  EMPTY_OBJ,\n  type IfAny,\n  PatchFlags,\n  camelize,\n  capitalize,\n  extend,\n  hasOwn,\n  hyphenate,\n  isArray,\n  isFunction,\n  isObject,\n  isOn,\n  isReservedProp,\n  isString,\n  makeMap,\n  toRawType,\n} from '@vue/shared'\nimport { warn } from './warning'\nimport {\n  type ComponentInternalInstance,\n  type ComponentOptions,\n  type ConcreteComponent,\n  type Data,\n  setCurrentInstance,\n} from './component'\nimport { isEmitListener } from './componentEmits'\nimport type { AppContext } from './apiCreateApp'\nimport { createPropsDefaultThis } from './compat/props'\nimport { isCompatEnabled, softAssertCompatEnabled } from './compat/compatConfig'\nimport { DeprecationTypes } from './compat/compatConfig'\nimport { shouldSkipAttr } from './compat/attrsFallthrough'\nimport { createInternalObject } from './internalObject'\n\nexport type ComponentPropsOptions<P = Data> =\n  | ComponentObjectPropsOptions<P>\n  | string[]\n\nexport type ComponentObjectPropsOptions<P = Data> = {\n  [K in keyof P]: Prop<P[K]> | null\n}\n\nexport type Prop<T, D = T> = PropOptions<T, D> | PropType<T>\n\ntype DefaultFactory<T> = (props: Data) => T | null | undefined\n\nexport interface PropOptions<T = any, D = T> {\n  type?: PropType<T> | true | null\n  required?: boolean\n  default?: D | DefaultFactory<D> | null | undefined | object\n  validator?(value: unknown, props: Data): boolean\n  /**\n   * @internal\n   */\n  skipCheck?: boolean\n  /**\n   * @internal\n   */\n  skipFactory?: boolean\n}\n\nexport type PropType<T> = PropConstructor<T> | (PropConstructor<T> | null)[]\n\ntype PropConstructor<T = any> =\n  | { new (...args: any[]): T & {} }\n  | { (): T }\n  | PropMethod<T>\n\ntype PropMethod<T, TConstructor = any> = [T] extends [\n  ((...args: any) => any) | undefined,\n] // if is function with args, allowing non-required functions\n  ? { new (): TConstructor; (): T; readonly prototype: TConstructor } // Create Function like constructor\n  : never\n\ntype RequiredKeys<T> = {\n  [K in keyof T]: T[K] extends\n    | { required: true }\n    | { default: any }\n    // don't mark Boolean props as undefined\n    | BooleanConstructor\n    | { type: BooleanConstructor }\n    ? T[K] extends { default: undefined | (() => undefined) }\n      ? never\n      : K\n    : never\n}[keyof T]\n\ntype OptionalKeys<T> = Exclude<keyof T, RequiredKeys<T>>\n\ntype DefaultKeys<T> = {\n  [K in keyof T]: T[K] extends\n    | { default: any }\n    // Boolean implicitly defaults to false\n    | BooleanConstructor\n    | { type: BooleanConstructor }\n    ? T[K] extends { type: BooleanConstructor; required: true } // not default if Boolean is marked as required\n      ? never\n      : K\n    : never\n}[keyof T]\n\ntype InferPropType<T, NullAsAny = true> = [T] extends [null]\n  ? NullAsAny extends true\n    ? any\n    : null\n  : [T] extends [{ type: null | true }]\n    ? any // As TS issue https://github.com/Microsoft/TypeScript/issues/14829 // somehow `ObjectConstructor` when inferred from { (): T } becomes `any` // `BooleanConstructor` when inferred from PropConstructor(with PropMethod) becomes `Boolean`\n    : [T] extends [ObjectConstructor | { type: ObjectConstructor }]\n      ? Record<string, any>\n      : [T] extends [BooleanConstructor | { type: BooleanConstructor }]\n        ? boolean\n        : [T] extends [DateConstructor | { type: DateConstructor }]\n          ? Date\n          : [T] extends [(infer U)[] | { type: (infer U)[] }]\n            ? U extends DateConstructor\n              ? Date | InferPropType<U, false>\n              : InferPropType<U, false>\n            : [T] extends [Prop<infer V, infer D>]\n              ? unknown extends V\n                ? keyof V extends never\n                  ? IfAny<V, V, D>\n                  : V\n                : V\n              : T\n\n/**\n * Extract prop types from a runtime props options object.\n * The extracted types are **internal** - i.e. the resolved props received by\n * the component.\n * - Boolean props are always present\n * - Props with default values are always present\n *\n * To extract accepted props from the parent, use {@link ExtractPublicPropTypes}.\n */\nexport type ExtractPropTypes<O> = {\n  // use `keyof Pick<O, RequiredKeys<O>>` instead of `RequiredKeys<O>` to\n  // support IDE features\n  [K in keyof Pick<O, RequiredKeys<O>>]: O[K] extends { default: any }\n    ? Exclude<InferPropType<O[K]>, undefined>\n    : InferPropType<O[K]>\n} & {\n  // use `keyof Pick<O, OptionalKeys<O>>` instead of `OptionalKeys<O>` to\n  // support IDE features\n  [K in keyof Pick<O, OptionalKeys<O>>]?: InferPropType<O[K]>\n}\n\ntype PublicRequiredKeys<T> = {\n  [K in keyof T]: T[K] extends { required: true } ? K : never\n}[keyof T]\n\ntype PublicOptionalKeys<T> = Exclude<keyof T, PublicRequiredKeys<T>>\n\n/**\n * Extract prop types from a runtime props options object.\n * The extracted types are **public** - i.e. the expected props that can be\n * passed to component.\n */\nexport type ExtractPublicPropTypes<O> = {\n  [K in keyof Pick<O, PublicRequiredKeys<O>>]: InferPropType<O[K]>\n} & {\n  [K in keyof Pick<O, PublicOptionalKeys<O>>]?: InferPropType<O[K]>\n}\n\nenum BooleanFlags {\n  shouldCast,\n  shouldCastTrue,\n}\n\n// extract props which defined with default from prop options\nexport type ExtractDefaultPropTypes<O> = O extends object\n  ? // use `keyof Pick<O, DefaultKeys<O>>` instead of `DefaultKeys<O>` to support IDE features\n    { [K in keyof Pick<O, DefaultKeys<O>>]: InferPropType<O[K]> }\n  : {}\n\ntype NormalizedProp = PropOptions & {\n  [BooleanFlags.shouldCast]?: boolean\n  [BooleanFlags.shouldCastTrue]?: boolean\n}\n\n// normalized value is a tuple of the actual normalized options\n// and an array of prop keys that need value casting (booleans and defaults)\nexport type NormalizedProps = Record<string, NormalizedProp>\nexport type NormalizedPropsOptions = [NormalizedProps, string[]] | []\n\nexport function initProps(\n  instance: ComponentInternalInstance,\n  rawProps: Data | null,\n  isStateful: number, // result of bitwise flag comparison\n  isSSR = false,\n): void {\n  const props: Data = {}\n  const attrs: Data = createInternalObject()\n\n  instance.propsDefaults = Object.create(null)\n\n  setFullProps(instance, rawProps, props, attrs)\n\n  // ensure all declared prop keys are present\n  for (const key in instance.propsOptions[0]) {\n    if (!(key in props)) {\n      props[key] = undefined\n    }\n  }\n\n  // validation\n  if (__DEV__) {\n    validateProps(rawProps || {}, props, instance)\n  }\n\n  if (isStateful) {\n    // stateful\n    instance.props = isSSR ? props : shallowReactive(props)\n  } else {\n    if (!instance.type.props) {\n      // functional w/ optional props, props === attrs\n      instance.props = attrs\n    } else {\n      // functional w/ declared props\n      instance.props = props\n    }\n  }\n  instance.attrs = attrs\n}\n\nfunction isInHmrContext(instance: ComponentInternalInstance | null) {\n  while (instance) {\n    if (instance.type.__hmrId) return true\n    instance = instance.parent\n  }\n}\n\nexport function updateProps(\n  instance: ComponentInternalInstance,\n  rawProps: Data | null,\n  rawPrevProps: Data | null,\n  optimized: boolean,\n): void {\n  const {\n    props,\n    attrs,\n    vnode: { patchFlag },\n  } = instance\n  const rawCurrentProps = toRaw(props)\n  const [options] = instance.propsOptions\n  let hasAttrsChanged = false\n\n  if (\n    // always force full diff in dev\n    // - #1942 if hmr is enabled with sfc component\n    // - vite#872 non-sfc component used by sfc component\n    !(__DEV__ && isInHmrContext(instance)) &&\n    (optimized || patchFlag > 0) &&\n    !(patchFlag & PatchFlags.FULL_PROPS)\n  ) {\n    if (patchFlag & PatchFlags.PROPS) {\n      // Compiler-generated props & no keys change, just set the updated\n      // the props.\n      const propsToUpdate = instance.vnode.dynamicProps!\n      for (let i = 0; i < propsToUpdate.length; i++) {\n        let key = propsToUpdate[i]\n        // skip if the prop key is a declared emit event listener\n        if (isEmitListener(instance.emitsOptions, key)) {\n          continue\n        }\n        // PROPS flag guarantees rawProps to be non-null\n        const value = rawProps![key]\n        if (options) {\n          // attr / props separation was done on init and will be consistent\n          // in this code path, so just check if attrs have it.\n          if (hasOwn(attrs, key)) {\n            if (value !== attrs[key]) {\n              attrs[key] = value\n              hasAttrsChanged = true\n            }\n          } else {\n            const camelizedKey = camelize(key)\n            props[camelizedKey] = resolvePropValue(\n              options,\n              rawCurrentProps,\n              camelizedKey,\n              value,\n              instance,\n              false /* isAbsent */,\n            )\n          }\n        } else {\n          if (__COMPAT__) {\n            if (isOn(key) && key.endsWith('Native')) {\n              key = key.slice(0, -6) // remove Native postfix\n            } else if (shouldSkipAttr(key, instance)) {\n              continue\n            }\n          }\n          if (value !== attrs[key]) {\n            attrs[key] = value\n            hasAttrsChanged = true\n          }\n        }\n      }\n    }\n  } else {\n    // full props update.\n    if (setFullProps(instance, rawProps, props, attrs)) {\n      hasAttrsChanged = true\n    }\n    // in case of dynamic props, check if we need to delete keys from\n    // the props object\n    let kebabKey: string\n    for (const key in rawCurrentProps) {\n      if (\n        !rawProps ||\n        // for camelCase\n        (!hasOwn(rawProps, key) &&\n          // it's possible the original props was passed in as kebab-case\n          // and converted to camelCase (#955)\n          ((kebabKey = hyphenate(key)) === key || !hasOwn(rawProps, kebabKey)))\n      ) {\n        if (options) {\n          if (\n            rawPrevProps &&\n            // for camelCase\n            (rawPrevProps[key] !== undefined ||\n              // for kebab-case\n              rawPrevProps[kebabKey!] !== undefined)\n          ) {\n            props[key] = resolvePropValue(\n              options,\n              rawCurrentProps,\n              key,\n              undefined,\n              instance,\n              true /* isAbsent */,\n            )\n          }\n        } else {\n          delete props[key]\n        }\n      }\n    }\n    // in the case of functional component w/o props declaration, props and\n    // attrs point to the same object so it should already have been updated.\n    if (attrs !== rawCurrentProps) {\n      for (const key in attrs) {\n        if (\n          !rawProps ||\n          (!hasOwn(rawProps, key) &&\n            (!__COMPAT__ || !hasOwn(rawProps, key + 'Native')))\n        ) {\n          delete attrs[key]\n          hasAttrsChanged = true\n        }\n      }\n    }\n  }\n\n  // trigger updates for $attrs in case it's used in component slots\n  if (hasAttrsChanged) {\n    trigger(instance.attrs, TriggerOpTypes.SET, '')\n  }\n\n  if (__DEV__) {\n    validateProps(rawProps || {}, props, instance)\n  }\n}\n\nfunction setFullProps(\n  instance: ComponentInternalInstance,\n  rawProps: Data | null,\n  props: Data,\n  attrs: Data,\n) {\n  const [options, needCastKeys] = instance.propsOptions\n  let hasAttrsChanged = false\n  let rawCastValues: Data | undefined\n  if (rawProps) {\n    for (let key in rawProps) {\n      // key, ref are reserved and never passed down\n      if (isReservedProp(key)) {\n        continue\n      }\n\n      if (__COMPAT__) {\n        if (key.startsWith('onHook:')) {\n          softAssertCompatEnabled(\n            DeprecationTypes.INSTANCE_EVENT_HOOKS,\n            instance,\n            key.slice(2).toLowerCase(),\n          )\n        }\n        if (key === 'inline-template') {\n          continue\n        }\n      }\n\n      const value = rawProps[key]\n      // prop option names are camelized during normalization, so to support\n      // kebab -> camel conversion here we need to camelize the key.\n      let camelKey\n      if (options && hasOwn(options, (camelKey = camelize(key)))) {\n        if (!needCastKeys || !needCastKeys.includes(camelKey)) {\n          props[camelKey] = value\n        } else {\n          ;(rawCastValues || (rawCastValues = {}))[camelKey] = value\n        }\n      } else if (!isEmitListener(instance.emitsOptions, key)) {\n        // Any non-declared (either as a prop or an emitted event) props are put\n        // into a separate `attrs` object for spreading. Make sure to preserve\n        // original key casing\n        if (__COMPAT__) {\n          if (isOn(key) && key.endsWith('Native')) {\n            key = key.slice(0, -6) // remove Native postfix\n          } else if (shouldSkipAttr(key, instance)) {\n            continue\n          }\n        }\n        if (!(key in attrs) || value !== attrs[key]) {\n          attrs[key] = value\n          hasAttrsChanged = true\n        }\n      }\n    }\n  }\n\n  if (needCastKeys) {\n    const rawCurrentProps = toRaw(props)\n    const castValues = rawCastValues || EMPTY_OBJ\n    for (let i = 0; i < needCastKeys.length; i++) {\n      const key = needCastKeys[i]\n      props[key] = resolvePropValue(\n        options!,\n        rawCurrentProps,\n        key,\n        castValues[key],\n        instance,\n        !hasOwn(castValues, key),\n      )\n    }\n  }\n\n  return hasAttrsChanged\n}\n\nfunction resolvePropValue(\n  options: NormalizedProps,\n  props: Data,\n  key: string,\n  value: unknown,\n  instance: ComponentInternalInstance,\n  isAbsent: boolean,\n) {\n  const opt = options[key]\n  if (opt != null) {\n    const hasDefault = hasOwn(opt, 'default')\n    // default values\n    if (hasDefault && value === undefined) {\n      const defaultValue = opt.default\n      if (\n        opt.type !== Function &&\n        !opt.skipFactory &&\n        isFunction(defaultValue)\n      ) {\n        const { propsDefaults } = instance\n        if (key in propsDefaults) {\n          value = propsDefaults[key]\n        } else {\n          const reset = setCurrentInstance(instance)\n          value = propsDefaults[key] = defaultValue.call(\n            __COMPAT__ &&\n              isCompatEnabled(DeprecationTypes.PROPS_DEFAULT_THIS, instance)\n              ? createPropsDefaultThis(instance, props, key)\n              : null,\n            props,\n          )\n          reset()\n        }\n      } else {\n        value = defaultValue\n      }\n      // #9006 reflect default value on custom element\n      if (instance.ce) {\n        instance.ce._setProp(key, value)\n      }\n    }\n    // boolean casting\n    if (opt[BooleanFlags.shouldCast]) {\n      if (isAbsent && !hasDefault) {\n        value = false\n      } else if (\n        opt[BooleanFlags.shouldCastTrue] &&\n        (value === '' || value === hyphenate(key))\n      ) {\n        value = true\n      }\n    }\n  }\n  return value\n}\n\nconst mixinPropsCache = new WeakMap<ConcreteComponent, NormalizedPropsOptions>()\n\nexport function normalizePropsOptions(\n  comp: ConcreteComponent,\n  appContext: AppContext,\n  asMixin = false,\n): NormalizedPropsOptions {\n  const cache =\n    __FEATURE_OPTIONS_API__ && asMixin ? mixinPropsCache : appContext.propsCache\n  const cached = cache.get(comp)\n  if (cached) {\n    return cached\n  }\n\n  const raw = comp.props\n  const normalized: NormalizedPropsOptions[0] = {}\n  const needCastKeys: NormalizedPropsOptions[1] = []\n\n  // apply mixin/extends props\n  let hasExtends = false\n  if (__FEATURE_OPTIONS_API__ && !isFunction(comp)) {\n    const extendProps = (raw: ComponentOptions) => {\n      if (__COMPAT__ && isFunction(raw)) {\n        raw = raw.options\n      }\n      hasExtends = true\n      const [props, keys] = normalizePropsOptions(raw, appContext, true)\n      extend(normalized, props)\n      if (keys) needCastKeys.push(...keys)\n    }\n    if (!asMixin && appContext.mixins.length) {\n      appContext.mixins.forEach(extendProps)\n    }\n    if (comp.extends) {\n      extendProps(comp.extends)\n    }\n    if (comp.mixins) {\n      comp.mixins.forEach(extendProps)\n    }\n  }\n\n  if (!raw && !hasExtends) {\n    if (isObject(comp)) {\n      cache.set(comp, EMPTY_ARR as any)\n    }\n    return EMPTY_ARR as any\n  }\n\n  if (isArray(raw)) {\n    for (let i = 0; i < raw.length; i++) {\n      if (__DEV__ && !isString(raw[i])) {\n        warn(`props must be strings when using array syntax.`, raw[i])\n      }\n      const normalizedKey = camelize(raw[i])\n      if (validatePropName(normalizedKey)) {\n        normalized[normalizedKey] = EMPTY_OBJ\n      }\n    }\n  } else if (raw) {\n    if (__DEV__ && !isObject(raw)) {\n      warn(`invalid props options`, raw)\n    }\n    for (const key in raw) {\n      const normalizedKey = camelize(key)\n      if (validatePropName(normalizedKey)) {\n        const opt = raw[key]\n        const prop: NormalizedProp = (normalized[normalizedKey] =\n          isArray(opt) || isFunction(opt) ? { type: opt } : extend({}, opt))\n        const propType = prop.type\n        let shouldCast = false\n        let shouldCastTrue = true\n\n        if (isArray(propType)) {\n          for (let index = 0; index < propType.length; ++index) {\n            const type = propType[index]\n            const typeName = isFunction(type) && type.name\n\n            if (typeName === 'Boolean') {\n              shouldCast = true\n              break\n            } else if (typeName === 'String') {\n              // If we find `String` before `Boolean`, e.g. `[String, Boolean]`,\n              // we need to handle the casting slightly differently. Props\n              // passed as `<Comp checked=\"\">` or `<Comp checked=\"checked\">`\n              // will either be treated as strings or converted to a boolean\n              // `true`, depending on the order of the types.\n              shouldCastTrue = false\n            }\n          }\n        } else {\n          shouldCast = isFunction(propType) && propType.name === 'Boolean'\n        }\n\n        prop[BooleanFlags.shouldCast] = shouldCast\n        prop[BooleanFlags.shouldCastTrue] = shouldCastTrue\n        // if the prop needs boolean casting or default value\n        if (shouldCast || hasOwn(prop, 'default')) {\n          needCastKeys.push(normalizedKey)\n        }\n      }\n    }\n  }\n\n  const res: NormalizedPropsOptions = [normalized, needCastKeys]\n  if (isObject(comp)) {\n    cache.set(comp, res)\n  }\n  return res\n}\n\nfunction validatePropName(key: string) {\n  if (key[0] !== '$' && !isReservedProp(key)) {\n    return true\n  } else if (__DEV__) {\n    warn(`Invalid prop name: \"${key}\" is a reserved property.`)\n  }\n  return false\n}\n\n// dev only\n// use function string name to check type constructors\n// so that it works across vms / iframes.\nfunction getType(ctor: Prop<any> | null): string {\n  // Early return for null to avoid unnecessary computations\n  if (ctor === null) {\n    return 'null'\n  }\n\n  // Avoid using regex for common cases by checking the type directly\n  if (typeof ctor === 'function') {\n    // Using name property to avoid converting function to string\n    return ctor.name || ''\n  } else if (typeof ctor === 'object') {\n    // Attempting to directly access constructor name if possible\n    const name = ctor.constructor && ctor.constructor.name\n    return name || ''\n  }\n\n  // Fallback for other types (though they're less likely to have meaningful names here)\n  return ''\n}\n\n/**\n * dev only\n */\nfunction validateProps(\n  rawProps: Data,\n  props: Data,\n  instance: ComponentInternalInstance,\n) {\n  const resolvedValues = toRaw(props)\n  const options = instance.propsOptions[0]\n  const camelizePropsKey = Object.keys(rawProps).map(key => camelize(key))\n  for (const key in options) {\n    let opt = options[key]\n    if (opt == null) continue\n    validateProp(\n      key,\n      resolvedValues[key],\n      opt,\n      __DEV__ ? shallowReadonly(resolvedValues) : resolvedValues,\n      !camelizePropsKey.includes(key),\n    )\n  }\n}\n\n/**\n * dev only\n */\nfunction validateProp(\n  name: string,\n  value: unknown,\n  prop: PropOptions,\n  props: Data,\n  isAbsent: boolean,\n) {\n  const { type, required, validator, skipCheck } = prop\n  // required!\n  if (required && isAbsent) {\n    warn('Missing required prop: \"' + name + '\"')\n    return\n  }\n  // missing but optional\n  if (value == null && !required) {\n    return\n  }\n  // type check\n  if (type != null && type !== true && !skipCheck) {\n    let isValid = false\n    const types = isArray(type) ? type : [type]\n    const expectedTypes = []\n    // value is valid as long as one of the specified types match\n    for (let i = 0; i < types.length && !isValid; i++) {\n      const { valid, expectedType } = assertType(value, types[i])\n      expectedTypes.push(expectedType || '')\n      isValid = valid\n    }\n    if (!isValid) {\n      warn(getInvalidTypeMessage(name, value, expectedTypes))\n      return\n    }\n  }\n  // custom validator\n  if (validator && !validator(value, props)) {\n    warn('Invalid prop: custom validator check failed for prop \"' + name + '\".')\n  }\n}\n\nconst isSimpleType = /*@__PURE__*/ makeMap(\n  'String,Number,Boolean,Function,Symbol,BigInt',\n)\n\ntype AssertionResult = {\n  valid: boolean\n  expectedType: string\n}\n\n/**\n * dev only\n */\nfunction assertType(\n  value: unknown,\n  type: PropConstructor | null,\n): AssertionResult {\n  let valid\n  const expectedType = getType(type)\n  if (expectedType === 'null') {\n    valid = value === null\n  } else if (isSimpleType(expectedType)) {\n    const t = typeof value\n    valid = t === expectedType.toLowerCase()\n    // for primitive wrapper objects\n    if (!valid && t === 'object') {\n      valid = value instanceof (type as PropConstructor)\n    }\n  } else if (expectedType === 'Object') {\n    valid = isObject(value)\n  } else if (expectedType === 'Array') {\n    valid = isArray(value)\n  } else {\n    valid = value instanceof (type as PropConstructor)\n  }\n  return {\n    valid,\n    expectedType,\n  }\n}\n\n/**\n * dev only\n */\nfunction getInvalidTypeMessage(\n  name: string,\n  value: unknown,\n  expectedTypes: string[],\n): string {\n  if (expectedTypes.length === 0) {\n    return (\n      `Prop type [] for prop \"${name}\" won't match anything.` +\n      ` Did you mean to use type Array instead?`\n    )\n  }\n  let message =\n    `Invalid prop: type check failed for prop \"${name}\".` +\n    ` Expected ${expectedTypes.map(capitalize).join(' | ')}`\n  const expectedType = expectedTypes[0]\n  const receivedType = toRawType(value)\n  const expectedValue = styleValue(value, expectedType)\n  const receivedValue = styleValue(value, receivedType)\n  // check if we need to specify expected value\n  if (\n    expectedTypes.length === 1 &&\n    isExplicable(expectedType) &&\n    !isBoolean(expectedType, receivedType)\n  ) {\n    message += ` with value ${expectedValue}`\n  }\n  message += `, got ${receivedType} `\n  // check if we need to specify received value\n  if (isExplicable(receivedType)) {\n    message += `with value ${receivedValue}.`\n  }\n  return message\n}\n\n/**\n * dev only\n */\nfunction styleValue(value: unknown, type: string): string {\n  if (type === 'String') {\n    return `\"${value}\"`\n  } else if (type === 'Number') {\n    return `${Number(value)}`\n  } else {\n    return `${value}`\n  }\n}\n\n/**\n * dev only\n */\nfunction isExplicable(type: string): boolean {\n  const explicitTypes = ['string', 'number', 'boolean']\n  return explicitTypes.some(elem => type.toLowerCase() === elem)\n}\n\n/**\n * dev only\n */\nfunction isBoolean(...args: string[]): boolean {\n  return args.some(elem => elem.toLowerCase() === 'boolean')\n}\n"
  },
  {
    "path": "packages/runtime-core/src/componentPublicInstance.ts",
    "content": "import {\n  type Attrs,\n  type Component,\n  type ComponentInternalInstance,\n  type Data,\n  getComponentPublicInstance,\n  isStatefulComponent,\n} from './component'\nimport { nextTick, queueJob } from './scheduler'\nimport {\n  type OnCleanup,\n  type WatchOptions,\n  type WatchStopHandle,\n  instanceWatch,\n} from './apiWatch'\nimport {\n  EMPTY_OBJ,\n  type IfAny,\n  NOOP,\n  type Prettify,\n  type UnionToIntersection,\n  extend,\n  hasOwn,\n  isFunction,\n  isGloballyAllowed,\n  isString,\n} from '@vue/shared'\nimport {\n  ReactiveFlags,\n  type ShallowUnwrapRef,\n  TrackOpTypes,\n  type UnwrapNestedRefs,\n  shallowReadonly,\n  toRaw,\n  track,\n} from '@vue/reactivity'\nimport {\n  type ComponentInjectOptions,\n  type ComponentOptionsBase,\n  type ComponentOptionsMixin,\n  type ComponentProvideOptions,\n  type ComputedOptions,\n  type ExtractComputedReturns,\n  type InjectToObject,\n  type MergedComponentOptionsOverride,\n  type MethodOptions,\n  type OptionTypesKeys,\n  type OptionTypesType,\n  resolveMergedOptions,\n  shouldCacheAccess,\n} from './componentOptions'\nimport type { EmitFn, EmitsOptions } from './componentEmits'\nimport type { SlotsType, UnwrapSlotsType } from './componentSlots'\nimport { markAttrsAccessed } from './componentRenderUtils'\nimport { currentRenderingInstance } from './componentRenderContext'\nimport { warn } from './warning'\nimport { installCompatInstanceProperties } from './compat/instance'\nimport type { Directive } from './directives'\n\n/**\n * Custom properties added to component instances in any way and can be accessed through `this`\n *\n * @example\n * Here is an example of adding a property `$router` to every component instance:\n * ```ts\n * import { createApp } from 'vue'\n * import { Router, createRouter } from 'vue-router'\n *\n * declare module 'vue' {\n *   interface ComponentCustomProperties {\n *     $router: Router\n *   }\n * }\n *\n * // effectively adding the router to every component instance\n * const app = createApp({})\n * const router = createRouter()\n * app.config.globalProperties.$router = router\n *\n * const vm = app.mount('#app')\n * // we can access the router from the instance\n * vm.$router.push('/')\n * ```\n */\nexport interface ComponentCustomProperties {}\n\ntype IsDefaultMixinComponent<T> = T extends ComponentOptionsMixin\n  ? ComponentOptionsMixin extends T\n    ? true\n    : false\n  : false\n\ntype MixinToOptionTypes<T> =\n  T extends ComponentOptionsBase<\n    infer P,\n    infer B,\n    infer D,\n    infer C,\n    infer M,\n    infer Mixin,\n    infer Extends,\n    any,\n    any,\n    infer Defaults,\n    any,\n    any,\n    any,\n    any,\n    any,\n    any,\n    any\n  >\n    ? OptionTypesType<P & {}, B & {}, D & {}, C & {}, M & {}, Defaults & {}> &\n        IntersectionMixin<Mixin> &\n        IntersectionMixin<Extends>\n    : never\n\n// ExtractMixin(map type) is used to resolve circularly references\ntype ExtractMixin<T> = {\n  Mixin: MixinToOptionTypes<T>\n}[T extends ComponentOptionsMixin ? 'Mixin' : never]\n\nexport type IntersectionMixin<T> =\n  IsDefaultMixinComponent<T> extends true\n    ? OptionTypesType\n    : UnionToIntersection<ExtractMixin<T>>\n\nexport type UnwrapMixinsType<\n  T,\n  Type extends OptionTypesKeys,\n> = T extends OptionTypesType ? T[Type] : never\n\ntype EnsureNonVoid<T> = T extends void ? {} : T\n\nexport type ComponentPublicInstanceConstructor<\n  T extends ComponentPublicInstance<Props, RawBindings, D, C, M> =\n    ComponentPublicInstance<any>,\n  Props = any,\n  RawBindings = any,\n  D = any,\n  C extends ComputedOptions = ComputedOptions,\n  M extends MethodOptions = MethodOptions,\n> = {\n  __isFragment?: never\n  __isTeleport?: never\n  __isSuspense?: never\n  new (...args: any[]): T\n}\n\n/**\n * @deprecated This is no longer used internally, but exported and relied on by\n * existing library types generated by vue-tsc.\n */\nexport type CreateComponentPublicInstance<\n  P = {},\n  B = {},\n  D = {},\n  C extends ComputedOptions = {},\n  M extends MethodOptions = {},\n  Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,\n  Extends extends ComponentOptionsMixin = ComponentOptionsMixin,\n  E extends EmitsOptions = {},\n  PublicProps = P,\n  Defaults = {},\n  MakeDefaultsOptional extends boolean = false,\n  I extends ComponentInjectOptions = {},\n  S extends SlotsType = {},\n  PublicMixin = IntersectionMixin<Mixin> & IntersectionMixin<Extends>,\n  PublicP = UnwrapMixinsType<PublicMixin, 'P'> & EnsureNonVoid<P>,\n  PublicB = UnwrapMixinsType<PublicMixin, 'B'> & EnsureNonVoid<B>,\n  PublicD = UnwrapMixinsType<PublicMixin, 'D'> & EnsureNonVoid<D>,\n  PublicC extends ComputedOptions = UnwrapMixinsType<PublicMixin, 'C'> &\n    EnsureNonVoid<C>,\n  PublicM extends MethodOptions = UnwrapMixinsType<PublicMixin, 'M'> &\n    EnsureNonVoid<M>,\n  PublicDefaults = UnwrapMixinsType<PublicMixin, 'Defaults'> &\n    EnsureNonVoid<Defaults>,\n> = ComponentPublicInstance<\n  PublicP,\n  PublicB,\n  PublicD,\n  PublicC,\n  PublicM,\n  E,\n  PublicProps,\n  PublicDefaults,\n  MakeDefaultsOptional,\n  ComponentOptionsBase<\n    P,\n    B,\n    D,\n    C,\n    M,\n    Mixin,\n    Extends,\n    E,\n    string,\n    Defaults,\n    {},\n    string,\n    S\n  >,\n  I,\n  S\n>\n\n/**\n * This is the same as `CreateComponentPublicInstance` but adds local components,\n * global directives, exposed, and provide inference.\n * It changes the arguments order so that we don't need to repeat mixin\n * inference everywhere internally, but it has to be a new type to avoid\n * breaking types that relies on previous arguments order (#10842)\n */\nexport type CreateComponentPublicInstanceWithMixins<\n  P = {},\n  B = {},\n  D = {},\n  C extends ComputedOptions = {},\n  M extends MethodOptions = {},\n  Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,\n  Extends extends ComponentOptionsMixin = ComponentOptionsMixin,\n  E extends EmitsOptions = {},\n  PublicProps = P,\n  Defaults = {},\n  MakeDefaultsOptional extends boolean = false,\n  I extends ComponentInjectOptions = {},\n  S extends SlotsType = {},\n  LC extends Record<string, Component> = {},\n  Directives extends Record<string, Directive> = {},\n  Exposed extends string = string,\n  TypeRefs extends Data = {},\n  TypeEl extends Element = any,\n  Provide extends ComponentProvideOptions = ComponentProvideOptions,\n  // mixin inference\n  PublicMixin = IntersectionMixin<Mixin> & IntersectionMixin<Extends>,\n  PublicP = UnwrapMixinsType<PublicMixin, 'P'> & EnsureNonVoid<P>,\n  PublicB = UnwrapMixinsType<PublicMixin, 'B'> & EnsureNonVoid<B>,\n  PublicD = UnwrapMixinsType<PublicMixin, 'D'> & EnsureNonVoid<D>,\n  PublicC extends ComputedOptions = UnwrapMixinsType<PublicMixin, 'C'> &\n    EnsureNonVoid<C>,\n  PublicM extends MethodOptions = UnwrapMixinsType<PublicMixin, 'M'> &\n    EnsureNonVoid<M>,\n  PublicDefaults = UnwrapMixinsType<PublicMixin, 'Defaults'> &\n    EnsureNonVoid<Defaults>,\n> = ComponentPublicInstance<\n  PublicP,\n  PublicB,\n  PublicD,\n  PublicC,\n  PublicM,\n  E,\n  PublicProps,\n  PublicDefaults,\n  MakeDefaultsOptional,\n  ComponentOptionsBase<\n    P,\n    B,\n    D,\n    C,\n    M,\n    Mixin,\n    Extends,\n    E,\n    string,\n    Defaults,\n    {},\n    string,\n    S,\n    LC,\n    Directives,\n    Exposed,\n    Provide\n  >,\n  I,\n  S,\n  Exposed,\n  TypeRefs,\n  TypeEl\n>\n\nexport type ExposedKeys<\n  T,\n  Exposed extends string & keyof T,\n> = '' extends Exposed ? T : Pick<T, Exposed>\n\n// public properties exposed on the proxy, which is used as the render context\n// in templates (as `this` in the render option)\nexport type ComponentPublicInstance<\n  P = {}, // props type extracted from props option\n  B = {}, // raw bindings returned from setup()\n  D = {}, // return from data()\n  C extends ComputedOptions = {},\n  M extends MethodOptions = {},\n  E extends EmitsOptions = {},\n  PublicProps = {},\n  Defaults = {},\n  MakeDefaultsOptional extends boolean = false,\n  Options = ComponentOptionsBase<any, any, any, any, any, any, any, any, any>,\n  I extends ComponentInjectOptions = {},\n  S extends SlotsType = {},\n  Exposed extends string = '',\n  TypeRefs extends Data = {},\n  TypeEl extends Element = any,\n> = {\n  $: ComponentInternalInstance\n  $data: D\n  $props: MakeDefaultsOptional extends true\n    ? Partial<Defaults> & Omit<Prettify<P> & PublicProps, keyof Defaults>\n    : Prettify<P> & PublicProps\n  $attrs: Attrs\n  $refs: Data & TypeRefs\n  $slots: UnwrapSlotsType<S>\n  $root: ComponentPublicInstance | null\n  $parent: ComponentPublicInstance | null\n  $host: Element | null\n  $emit: EmitFn<E>\n  $el: TypeEl\n  $options: Options & MergedComponentOptionsOverride\n  $forceUpdate: () => void\n  $nextTick: typeof nextTick\n  $watch<T extends string | ((...args: any) => any)>(\n    source: T,\n    cb: T extends (...args: any) => infer R\n      ? (...args: [R, R, OnCleanup]) => any\n      : (...args: [any, any, OnCleanup]) => any,\n    options?: WatchOptions,\n  ): WatchStopHandle\n} & ExposedKeys<\n  IfAny<\n    P,\n    P,\n    Readonly<Defaults> & Omit<P, keyof ShallowUnwrapRef<B> | keyof Defaults>\n  > &\n    ShallowUnwrapRef<B> &\n    UnwrapNestedRefs<D> &\n    ExtractComputedReturns<C> &\n    M &\n    ComponentCustomProperties &\n    InjectToObject<I>,\n  Exposed\n>\n\nexport type PublicPropertiesMap = Record<\n  string,\n  (i: ComponentInternalInstance) => any\n>\n\n/**\n * #2437 In Vue 3, functional components do not have a public instance proxy but\n * they exist in the internal parent chain. For code that relies on traversing\n * public $parent chains, skip functional ones and go to the parent instead.\n */\nconst getPublicInstance = (\n  i: ComponentInternalInstance | null,\n): ComponentPublicInstance | ComponentInternalInstance['exposed'] | null => {\n  if (!i) return null\n  if (isStatefulComponent(i)) return getComponentPublicInstance(i)\n  return getPublicInstance(i.parent)\n}\n\nexport const publicPropertiesMap: PublicPropertiesMap =\n  // Move PURE marker to new line to workaround compiler discarding it\n  // due to type annotation\n  /*@__PURE__*/ extend(Object.create(null), {\n    $: i => i,\n    $el: i => i.vnode.el,\n    $data: i => i.data,\n    $props: i => (__DEV__ ? shallowReadonly(i.props) : i.props),\n    $attrs: i => (__DEV__ ? shallowReadonly(i.attrs) : i.attrs),\n    $slots: i => (__DEV__ ? shallowReadonly(i.slots) : i.slots),\n    $refs: i => (__DEV__ ? shallowReadonly(i.refs) : i.refs),\n    $parent: i => getPublicInstance(i.parent),\n    $root: i => getPublicInstance(i.root),\n    $host: i => i.ce,\n    $emit: i => i.emit,\n    $options: i => (__FEATURE_OPTIONS_API__ ? resolveMergedOptions(i) : i.type),\n    $forceUpdate: i =>\n      i.f ||\n      (i.f = () => {\n        queueJob(i.update)\n      }),\n    $nextTick: i => i.n || (i.n = nextTick.bind(i.proxy!)),\n    $watch: i => (__FEATURE_OPTIONS_API__ ? instanceWatch.bind(i) : NOOP),\n  } as PublicPropertiesMap)\n\nif (__COMPAT__) {\n  installCompatInstanceProperties(publicPropertiesMap)\n}\n\nenum AccessTypes {\n  OTHER,\n  SETUP,\n  DATA,\n  PROPS,\n  CONTEXT,\n}\n\nexport interface ComponentRenderContext {\n  [key: string]: any\n  _: ComponentInternalInstance\n}\n\nexport const isReservedPrefix = (key: string): key is '_' | '$' =>\n  key === '_' || key === '$'\n\nconst hasSetupBinding = (state: Data, key: string) =>\n  state !== EMPTY_OBJ && !state.__isScriptSetup && hasOwn(state, key)\n\nexport const PublicInstanceProxyHandlers: ProxyHandler<any> = {\n  get({ _: instance }: ComponentRenderContext, key: string) {\n    if (key === ReactiveFlags.SKIP) {\n      return true\n    }\n\n    const { ctx, setupState, data, props, accessCache, type, appContext } =\n      instance\n\n    // for internal formatters to know that this is a Vue instance\n    if (__DEV__ && key === '__isVue') {\n      return true\n    }\n\n    // data / props / ctx\n    // This getter gets called for every property access on the render context\n    // during render and is a major hotspot. The most expensive part of this\n    // is the multiple hasOwn() calls. It's much faster to do a simple property\n    // access on a plain object, so we use an accessCache object (with null\n    // prototype) to memoize what access type a key corresponds to.\n    if (key[0] !== '$') {\n      const n = accessCache![key]\n      if (n !== undefined) {\n        switch (n) {\n          case AccessTypes.SETUP:\n            return setupState[key]\n          case AccessTypes.DATA:\n            return data[key]\n          case AccessTypes.CONTEXT:\n            return ctx[key]\n          case AccessTypes.PROPS:\n            return props![key]\n          // default: just fallthrough\n        }\n      } else if (hasSetupBinding(setupState, key)) {\n        accessCache![key] = AccessTypes.SETUP\n        return setupState[key]\n      } else if (\n        __FEATURE_OPTIONS_API__ &&\n        data !== EMPTY_OBJ &&\n        hasOwn(data, key)\n      ) {\n        accessCache![key] = AccessTypes.DATA\n        return data[key]\n      } else if (hasOwn(props, key)) {\n        accessCache![key] = AccessTypes.PROPS\n        return props![key]\n      } else if (ctx !== EMPTY_OBJ && hasOwn(ctx, key)) {\n        accessCache![key] = AccessTypes.CONTEXT\n        return ctx[key]\n      } else if (!__FEATURE_OPTIONS_API__ || shouldCacheAccess) {\n        accessCache![key] = AccessTypes.OTHER\n      }\n    }\n\n    const publicGetter = publicPropertiesMap[key]\n    let cssModule, globalProperties\n    // public $xxx properties\n    if (publicGetter) {\n      if (key === '$attrs') {\n        track(instance.attrs, TrackOpTypes.GET, '')\n        __DEV__ && markAttrsAccessed()\n      } else if (__DEV__ && key === '$slots') {\n        // for HMR only\n        track(instance, TrackOpTypes.GET, key)\n      }\n      return publicGetter(instance)\n    } else if (\n      // css module (injected by vue-loader)\n      (cssModule = type.__cssModules) &&\n      (cssModule = cssModule[key])\n    ) {\n      return cssModule\n    } else if (ctx !== EMPTY_OBJ && hasOwn(ctx, key)) {\n      // user may set custom properties to `this` that start with `$`\n      accessCache![key] = AccessTypes.CONTEXT\n      return ctx[key]\n    } else if (\n      // global properties\n      ((globalProperties = appContext.config.globalProperties),\n      hasOwn(globalProperties, key))\n    ) {\n      if (__COMPAT__) {\n        const desc = Object.getOwnPropertyDescriptor(globalProperties, key)!\n        if (desc.get) {\n          return desc.get.call(instance.proxy)\n        } else {\n          const val = globalProperties[key]\n          return isFunction(val) ? extend(val.bind(instance.proxy), val) : val\n        }\n      } else {\n        return globalProperties[key]\n      }\n    } else if (\n      __DEV__ &&\n      currentRenderingInstance &&\n      (!isString(key) ||\n        // #1091 avoid internal isRef/isVNode checks on component instance leading\n        // to infinite warning loop\n        key.indexOf('__v') !== 0)\n    ) {\n      if (data !== EMPTY_OBJ && isReservedPrefix(key[0]) && hasOwn(data, key)) {\n        warn(\n          `Property ${JSON.stringify(\n            key,\n          )} must be accessed via $data because it starts with a reserved ` +\n            `character (\"$\" or \"_\") and is not proxied on the render context.`,\n        )\n      } else if (instance === currentRenderingInstance) {\n        warn(\n          `Property ${JSON.stringify(key)} was accessed during render ` +\n            `but is not defined on instance.`,\n        )\n      }\n    }\n  },\n\n  set(\n    { _: instance }: ComponentRenderContext,\n    key: string,\n    value: any,\n  ): boolean {\n    const { data, setupState, ctx } = instance\n    if (hasSetupBinding(setupState, key)) {\n      setupState[key] = value\n      return true\n    } else if (\n      __DEV__ &&\n      setupState.__isScriptSetup &&\n      hasOwn(setupState, key)\n    ) {\n      warn(`Cannot mutate <script setup> binding \"${key}\" from Options API.`)\n      return false\n    } else if (\n      __FEATURE_OPTIONS_API__ &&\n      data !== EMPTY_OBJ &&\n      hasOwn(data, key)\n    ) {\n      data[key] = value\n      return true\n    } else if (hasOwn(instance.props, key)) {\n      __DEV__ && warn(`Attempting to mutate prop \"${key}\". Props are readonly.`)\n      return false\n    }\n    if (key[0] === '$' && key.slice(1) in instance) {\n      __DEV__ &&\n        warn(\n          `Attempting to mutate public property \"${key}\". ` +\n            `Properties starting with $ are reserved and readonly.`,\n        )\n      return false\n    } else {\n      if (__DEV__ && key in instance.appContext.config.globalProperties) {\n        Object.defineProperty(ctx, key, {\n          enumerable: true,\n          configurable: true,\n          value,\n        })\n      } else {\n        ctx[key] = value\n      }\n    }\n    return true\n  },\n\n  has(\n    {\n      _: { data, setupState, accessCache, ctx, appContext, props, type },\n    }: ComponentRenderContext,\n    key: string,\n  ) {\n    let cssModules\n    return !!(\n      accessCache![key] ||\n      (__FEATURE_OPTIONS_API__ &&\n        data !== EMPTY_OBJ &&\n        key[0] !== '$' &&\n        hasOwn(data, key)) ||\n      hasSetupBinding(setupState, key) ||\n      hasOwn(props, key) ||\n      hasOwn(ctx, key) ||\n      hasOwn(publicPropertiesMap, key) ||\n      hasOwn(appContext.config.globalProperties, key) ||\n      ((cssModules = type.__cssModules) && cssModules[key])\n    )\n  },\n\n  defineProperty(\n    target: ComponentRenderContext,\n    key: string,\n    descriptor: PropertyDescriptor,\n  ) {\n    if (descriptor.get != null) {\n      // invalidate key cache of a getter based property #5417\n      target._.accessCache![key] = 0\n    } else if (hasOwn(descriptor, 'value')) {\n      this.set!(target, key, descriptor.value, null)\n    }\n    return Reflect.defineProperty(target, key, descriptor)\n  },\n}\n\nif (__DEV__ && !__TEST__) {\n  PublicInstanceProxyHandlers.ownKeys = (target: ComponentRenderContext) => {\n    warn(\n      `Avoid app logic that relies on enumerating keys on a component instance. ` +\n        `The keys will be empty in production mode to avoid performance overhead.`,\n    )\n    return Reflect.ownKeys(target)\n  }\n}\n\nexport const RuntimeCompiledPublicInstanceProxyHandlers: ProxyHandler<any> =\n  /*@__PURE__*/ extend({}, PublicInstanceProxyHandlers, {\n    get(target: ComponentRenderContext, key: string) {\n      // fast path for unscopables when using `with` block\n      if ((key as any) === Symbol.unscopables) {\n        return\n      }\n      return PublicInstanceProxyHandlers.get!(target, key, target)\n    },\n    has(_: ComponentRenderContext, key: string) {\n      const has = key[0] !== '_' && !isGloballyAllowed(key)\n      if (__DEV__ && !has && PublicInstanceProxyHandlers.has!(_, key)) {\n        warn(\n          `Property ${JSON.stringify(\n            key,\n          )} should not start with _ which is a reserved prefix for Vue internals.`,\n        )\n      }\n      return has\n    },\n  })\n\n// dev only\n// In dev mode, the proxy target exposes the same properties as seen on `this`\n// for easier console inspection. In prod mode it will be an empty object so\n// these properties definitions can be skipped.\nexport function createDevRenderContext(instance: ComponentInternalInstance) {\n  const target: Record<string, any> = {}\n\n  // expose internal instance for proxy handlers\n  Object.defineProperty(target, `_`, {\n    configurable: true,\n    enumerable: false,\n    get: () => instance,\n  })\n\n  // expose public properties\n  Object.keys(publicPropertiesMap).forEach(key => {\n    Object.defineProperty(target, key, {\n      configurable: true,\n      enumerable: false,\n      get: () => publicPropertiesMap[key](instance),\n      // intercepted by the proxy so no need for implementation,\n      // but needed to prevent set errors\n      set: NOOP,\n    })\n  })\n\n  return target as ComponentRenderContext\n}\n\n// dev only\nexport function exposePropsOnRenderContext(\n  instance: ComponentInternalInstance,\n): void {\n  const {\n    ctx,\n    propsOptions: [propsOptions],\n  } = instance\n  if (propsOptions) {\n    Object.keys(propsOptions).forEach(key => {\n      Object.defineProperty(ctx, key, {\n        enumerable: true,\n        configurable: true,\n        get: () => instance.props[key],\n        set: NOOP,\n      })\n    })\n  }\n}\n\n// dev only\nexport function exposeSetupStateOnRenderContext(\n  instance: ComponentInternalInstance,\n): void {\n  const { ctx, setupState } = instance\n  Object.keys(toRaw(setupState)).forEach(key => {\n    if (!setupState.__isScriptSetup) {\n      if (isReservedPrefix(key[0])) {\n        warn(\n          `setup() return property ${JSON.stringify(\n            key,\n          )} should not start with \"$\" or \"_\" ` +\n            `which are reserved prefixes for Vue internals.`,\n        )\n        return\n      }\n      Object.defineProperty(ctx, key, {\n        enumerable: true,\n        configurable: true,\n        get: () => setupState[key],\n        set: NOOP,\n      })\n    }\n  })\n}\n"
  },
  {
    "path": "packages/runtime-core/src/componentRenderContext.ts",
    "content": "import type { ComponentInternalInstance } from './component'\nimport { devtoolsComponentUpdated } from './devtools'\nimport { setBlockTracking } from './vnode'\n\n/**\n * mark the current rendering instance for asset resolution (e.g.\n * resolveComponent, resolveDirective) during render\n */\nexport let currentRenderingInstance: ComponentInternalInstance | null = null\nexport let currentScopeId: string | null = null\n\n/**\n * Note: rendering calls maybe nested. The function returns the parent rendering\n * instance if present, which should be restored after the render is done:\n *\n * ```js\n * const prev = setCurrentRenderingInstance(i)\n * // ...render\n * setCurrentRenderingInstance(prev)\n * ```\n */\nexport function setCurrentRenderingInstance(\n  instance: ComponentInternalInstance | null,\n): ComponentInternalInstance | null {\n  const prev = currentRenderingInstance\n  currentRenderingInstance = instance\n  currentScopeId = (instance && instance.type.__scopeId) || null\n  // v2 pre-compiled components uses _scopeId instead of __scopeId\n  if (__COMPAT__ && !currentScopeId) {\n    currentScopeId = (instance && (instance.type as any)._scopeId) || null\n  }\n  return prev\n}\n\n/**\n * Set scope id when creating hoisted vnodes.\n * @private compiler helper\n */\nexport function pushScopeId(id: string | null): void {\n  currentScopeId = id\n}\n\n/**\n * Technically we no longer need this after 3.0.8 but we need to keep the same\n * API for backwards compat w/ code generated by compilers.\n * @private\n */\nexport function popScopeId(): void {\n  currentScopeId = null\n}\n\n/**\n * Only for backwards compat\n * @private\n */\nexport const withScopeId = (_id: string): typeof withCtx => withCtx\n\nexport type ContextualRenderFn = {\n  (...args: any[]): any\n  _n: boolean /* already normalized */\n  _c: boolean /* compiled */\n  _d: boolean /* disableTracking */\n  _ns: boolean /* nonScoped */\n}\n\n/**\n * Wrap a slot function to memoize current rendering instance\n * @private compiler helper\n */\nexport function withCtx(\n  fn: Function,\n  ctx: ComponentInternalInstance | null = currentRenderingInstance,\n  isNonScopedSlot?: boolean, // __COMPAT__ only\n): Function {\n  if (!ctx) return fn\n\n  // already normalized\n  if ((fn as ContextualRenderFn)._n) {\n    return fn\n  }\n\n  const renderFnWithContext: ContextualRenderFn = (...args: any[]) => {\n    // If a user calls a compiled slot inside a template expression (#1745), it\n    // can mess up block tracking, so by default we disable block tracking and\n    // force bail out when invoking a compiled slot (indicated by the ._d flag).\n    // This isn't necessary if rendering a compiled `<slot>`, so we flip the\n    // ._d flag off when invoking the wrapped fn inside `renderSlot`.\n    if (renderFnWithContext._d) {\n      setBlockTracking(-1)\n    }\n    const prevInstance = setCurrentRenderingInstance(ctx)\n    let res\n    try {\n      res = fn(...args)\n    } finally {\n      setCurrentRenderingInstance(prevInstance)\n      if (renderFnWithContext._d) {\n        setBlockTracking(1)\n      }\n    }\n\n    if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {\n      devtoolsComponentUpdated(ctx)\n    }\n\n    return res\n  }\n\n  // mark normalized to avoid duplicated wrapping\n  renderFnWithContext._n = true\n  // mark this as compiled by default\n  // this is used in vnode.ts -> normalizeChildren() to set the slot\n  // rendering flag.\n  renderFnWithContext._c = true\n  // disable block tracking by default\n  renderFnWithContext._d = true\n  // compat build only flag to distinguish scoped slots from non-scoped ones\n  if (__COMPAT__ && isNonScopedSlot) {\n    renderFnWithContext._ns = true\n  }\n  return renderFnWithContext\n}\n"
  },
  {
    "path": "packages/runtime-core/src/componentRenderUtils.ts",
    "content": "import {\n  type ComponentInternalInstance,\n  type Data,\n  type FunctionalComponent,\n  getComponentName,\n} from './component'\nimport {\n  Comment,\n  type VNode,\n  type VNodeArrayChildren,\n  blockStack,\n  cloneVNode,\n  createVNode,\n  isVNode,\n  normalizeVNode,\n} from './vnode'\nimport { ErrorCodes, handleError } from './errorHandling'\nimport {\n  PatchFlags,\n  ShapeFlags,\n  isModelListener,\n  isObject,\n  isOn,\n  looseEqual,\n} from '@vue/shared'\nimport { warn } from './warning'\nimport { isHmrUpdating } from './hmr'\nimport type { NormalizedProps } from './componentProps'\nimport { isEmitListener } from './componentEmits'\nimport { setCurrentRenderingInstance } from './componentRenderContext'\nimport {\n  DeprecationTypes,\n  isCompatEnabled,\n  warnDeprecation,\n} from './compat/compatConfig'\nimport { shallowReadonly } from '@vue/reactivity'\nimport { setTransitionHooks } from './components/BaseTransition'\n\n/**\n * dev only flag to track whether $attrs was used during render.\n * If $attrs was used during render then the warning for failed attrs\n * fallthrough can be suppressed.\n */\nlet accessedAttrs: boolean = false\n\nexport function markAttrsAccessed(): void {\n  accessedAttrs = true\n}\n\ntype SetRootFn = ((root: VNode) => void) | undefined\n\nexport function renderComponentRoot(\n  instance: ComponentInternalInstance,\n): VNode {\n  const {\n    type: Component,\n    vnode,\n    proxy,\n    withProxy,\n    propsOptions: [propsOptions],\n    slots,\n    attrs,\n    emit,\n    render,\n    renderCache,\n    props,\n    data,\n    setupState,\n    ctx,\n    inheritAttrs,\n  } = instance\n  const prev = setCurrentRenderingInstance(instance)\n\n  let result\n  let fallthroughAttrs\n  if (__DEV__) {\n    accessedAttrs = false\n  }\n\n  try {\n    if (vnode.shapeFlag & ShapeFlags.STATEFUL_COMPONENT) {\n      // withProxy is a proxy with a different `has` trap only for\n      // runtime-compiled render functions using `with` block.\n      const proxyToUse = withProxy || proxy\n      // 'this' isn't available in production builds with `<script setup>`,\n      // so warn if it's used in dev.\n      const thisProxy =\n        __DEV__ && setupState.__isScriptSetup\n          ? new Proxy(proxyToUse!, {\n              get(target, key, receiver) {\n                warn(\n                  `Property '${String(\n                    key,\n                  )}' was accessed via 'this'. Avoid using 'this' in templates.`,\n                )\n                return Reflect.get(target, key, receiver)\n              },\n            })\n          : proxyToUse\n      result = normalizeVNode(\n        render!.call(\n          thisProxy,\n          proxyToUse!,\n          renderCache,\n          __DEV__ ? shallowReadonly(props) : props,\n          setupState,\n          data,\n          ctx,\n        ),\n      )\n      fallthroughAttrs = attrs\n    } else {\n      // functional\n      const render = Component as FunctionalComponent\n      // in dev, mark attrs accessed if optional props (attrs === props)\n      if (__DEV__ && attrs === props) {\n        markAttrsAccessed()\n      }\n      result = normalizeVNode(\n        render.length > 1\n          ? render(\n              __DEV__ ? shallowReadonly(props) : props,\n              __DEV__\n                ? {\n                    get attrs() {\n                      markAttrsAccessed()\n                      return shallowReadonly(attrs)\n                    },\n                    slots,\n                    emit,\n                  }\n                : { attrs, slots, emit },\n            )\n          : render(\n              __DEV__ ? shallowReadonly(props) : props,\n              null as any /* we know it doesn't need it */,\n            ),\n      )\n      fallthroughAttrs = Component.props\n        ? attrs\n        : getFunctionalFallthrough(attrs)\n    }\n  } catch (err) {\n    blockStack.length = 0\n    handleError(err, instance, ErrorCodes.RENDER_FUNCTION)\n    result = createVNode(Comment)\n  }\n\n  // attr merging\n  // in dev mode, comments are preserved, and it's possible for a template\n  // to have comments along side the root element which makes it a fragment\n  let root = result\n  let setRoot: SetRootFn = undefined\n  if (\n    __DEV__ &&\n    result.patchFlag > 0 &&\n    result.patchFlag & PatchFlags.DEV_ROOT_FRAGMENT\n  ) {\n    ;[root, setRoot] = getChildRoot(result)\n  }\n\n  if (fallthroughAttrs && inheritAttrs !== false) {\n    const keys = Object.keys(fallthroughAttrs)\n    const { shapeFlag } = root\n    if (keys.length) {\n      if (shapeFlag & (ShapeFlags.ELEMENT | ShapeFlags.COMPONENT)) {\n        if (propsOptions && keys.some(isModelListener)) {\n          // If a v-model listener (onUpdate:xxx) has a corresponding declared\n          // prop, it indicates this component expects to handle v-model and\n          // it should not fallthrough.\n          // related: #1543, #1643, #1989\n          fallthroughAttrs = filterModelListeners(\n            fallthroughAttrs,\n            propsOptions,\n          )\n        }\n        root = cloneVNode(root, fallthroughAttrs, false, true)\n      } else if (__DEV__ && !accessedAttrs && root.type !== Comment) {\n        const allAttrs = Object.keys(attrs)\n        const eventAttrs: string[] = []\n        const extraAttrs: string[] = []\n        for (let i = 0, l = allAttrs.length; i < l; i++) {\n          const key = allAttrs[i]\n          if (isOn(key)) {\n            // ignore v-model handlers when they fail to fallthrough\n            if (!isModelListener(key)) {\n              // remove `on`, lowercase first letter to reflect event casing\n              // accurately\n              eventAttrs.push(key[2].toLowerCase() + key.slice(3))\n            }\n          } else {\n            extraAttrs.push(key)\n          }\n        }\n        if (extraAttrs.length) {\n          warn(\n            `Extraneous non-props attributes (` +\n              `${extraAttrs.join(', ')}) ` +\n              `were passed to component but could not be automatically inherited ` +\n              `because component renders fragment or text or teleport root nodes.`,\n          )\n        }\n        if (eventAttrs.length) {\n          warn(\n            `Extraneous non-emits event listeners (` +\n              `${eventAttrs.join(', ')}) ` +\n              `were passed to component but could not be automatically inherited ` +\n              `because component renders fragment or text root nodes. ` +\n              `If the listener is intended to be a component custom event listener only, ` +\n              `declare it using the \"emits\" option.`,\n          )\n        }\n      }\n    }\n  }\n\n  if (\n    __COMPAT__ &&\n    isCompatEnabled(DeprecationTypes.INSTANCE_ATTRS_CLASS_STYLE, instance) &&\n    vnode.shapeFlag & ShapeFlags.STATEFUL_COMPONENT &&\n    root.shapeFlag & (ShapeFlags.ELEMENT | ShapeFlags.COMPONENT)\n  ) {\n    const { class: cls, style } = vnode.props || {}\n    if (cls || style) {\n      if (__DEV__ && inheritAttrs === false) {\n        warnDeprecation(\n          DeprecationTypes.INSTANCE_ATTRS_CLASS_STYLE,\n          instance,\n          getComponentName(instance.type),\n        )\n      }\n      root = cloneVNode(\n        root,\n        {\n          class: cls,\n          style: style,\n        },\n        false,\n        true,\n      )\n    }\n  }\n\n  // inherit directives\n  if (vnode.dirs) {\n    if (__DEV__ && !isElementRoot(root)) {\n      warn(\n        `Runtime directive used on component with non-element root node. ` +\n          `The directives will not function as intended.`,\n      )\n    }\n    // clone before mutating since the root may be a hoisted vnode\n    root = cloneVNode(root, null, false, true)\n    root.dirs = root.dirs ? root.dirs.concat(vnode.dirs) : vnode.dirs\n  }\n  // inherit transition data\n  if (vnode.transition) {\n    if (__DEV__ && !isElementRoot(root)) {\n      warn(\n        `Component inside <Transition> renders non-element root node ` +\n          `that cannot be animated.`,\n      )\n    }\n    setTransitionHooks(root, vnode.transition)\n  }\n\n  if (__DEV__ && setRoot) {\n    setRoot(root)\n  } else {\n    result = root\n  }\n\n  setCurrentRenderingInstance(prev)\n  return result\n}\n\n/**\n * dev only\n * In dev mode, template root level comments are rendered, which turns the\n * template into a fragment root, but we need to locate the single element\n * root for attrs and scope id processing.\n */\nconst getChildRoot = (vnode: VNode): [VNode, SetRootFn] => {\n  const rawChildren = vnode.children as VNodeArrayChildren\n  const dynamicChildren = vnode.dynamicChildren\n  const childRoot = filterSingleRoot(rawChildren, false)\n  if (!childRoot) {\n    return [vnode, undefined]\n  } else if (\n    __DEV__ &&\n    childRoot.patchFlag > 0 &&\n    childRoot.patchFlag & PatchFlags.DEV_ROOT_FRAGMENT\n  ) {\n    return getChildRoot(childRoot)\n  }\n\n  const index = rawChildren.indexOf(childRoot)\n  const dynamicIndex = dynamicChildren ? dynamicChildren.indexOf(childRoot) : -1\n  const setRoot: SetRootFn = (updatedRoot: VNode) => {\n    rawChildren[index] = updatedRoot\n    if (dynamicChildren) {\n      if (dynamicIndex > -1) {\n        dynamicChildren[dynamicIndex] = updatedRoot\n      } else if (updatedRoot.patchFlag > 0) {\n        vnode.dynamicChildren = [...dynamicChildren, updatedRoot]\n      }\n    }\n  }\n  return [normalizeVNode(childRoot), setRoot]\n}\n\nexport function filterSingleRoot(\n  children: VNodeArrayChildren,\n  recurse = true,\n): VNode | undefined {\n  let singleRoot\n  for (let i = 0; i < children.length; i++) {\n    const child = children[i]\n    if (isVNode(child)) {\n      // ignore user comment\n      if (child.type !== Comment || child.children === 'v-if') {\n        if (singleRoot) {\n          // has more than 1 non-comment child, return now\n          return\n        } else {\n          singleRoot = child\n          if (\n            __DEV__ &&\n            recurse &&\n            singleRoot.patchFlag > 0 &&\n            singleRoot.patchFlag & PatchFlags.DEV_ROOT_FRAGMENT\n          ) {\n            return filterSingleRoot(singleRoot.children as VNodeArrayChildren)\n          }\n        }\n      }\n    } else {\n      return\n    }\n  }\n  return singleRoot\n}\n\nconst getFunctionalFallthrough = (attrs: Data): Data | undefined => {\n  let res: Data | undefined\n  for (const key in attrs) {\n    if (key === 'class' || key === 'style' || isOn(key)) {\n      ;(res || (res = {}))[key] = attrs[key]\n    }\n  }\n  return res\n}\n\nconst filterModelListeners = (attrs: Data, props: NormalizedProps): Data => {\n  const res: Data = {}\n  for (const key in attrs) {\n    if (!isModelListener(key) || !(key.slice(9) in props)) {\n      res[key] = attrs[key]\n    }\n  }\n  return res\n}\n\nconst isElementRoot = (vnode: VNode) => {\n  return (\n    vnode.shapeFlag & (ShapeFlags.COMPONENT | ShapeFlags.ELEMENT) ||\n    vnode.type === Comment // potential v-if branch switch\n  )\n}\n\nexport function shouldUpdateComponent(\n  prevVNode: VNode,\n  nextVNode: VNode,\n  optimized?: boolean,\n): boolean {\n  const { props: prevProps, children: prevChildren, component } = prevVNode\n  const { props: nextProps, children: nextChildren, patchFlag } = nextVNode\n  const emits = component!.emitsOptions\n\n  // Parent component's render function was hot-updated. Since this may have\n  // caused the child component's slots content to have changed, we need to\n  // force the child to update as well.\n  if (__DEV__ && (prevChildren || nextChildren) && isHmrUpdating) {\n    return true\n  }\n\n  // force child update for runtime directive or transition on component vnode.\n  if (nextVNode.dirs || nextVNode.transition) {\n    return true\n  }\n\n  if (optimized && patchFlag >= 0) {\n    if (patchFlag & PatchFlags.DYNAMIC_SLOTS) {\n      // slot content that references values that might have changed,\n      // e.g. in a v-for\n      return true\n    }\n    if (patchFlag & PatchFlags.FULL_PROPS) {\n      if (!prevProps) {\n        return !!nextProps\n      }\n      // presence of this flag indicates props are always non-null\n      return hasPropsChanged(prevProps, nextProps!, emits)\n    } else if (patchFlag & PatchFlags.PROPS) {\n      const dynamicProps = nextVNode.dynamicProps!\n      for (let i = 0; i < dynamicProps.length; i++) {\n        const key = dynamicProps[i]\n        if (\n          hasPropValueChanged(nextProps!, prevProps!, key) &&\n          !isEmitListener(emits, key)\n        ) {\n          return true\n        }\n      }\n    }\n  } else {\n    // this path is only taken by manually written render functions\n    // so presence of any children leads to a forced update\n    if (prevChildren || nextChildren) {\n      if (!nextChildren || !(nextChildren as any).$stable) {\n        return true\n      }\n    }\n    if (prevProps === nextProps) {\n      return false\n    }\n    if (!prevProps) {\n      return !!nextProps\n    }\n    if (!nextProps) {\n      return true\n    }\n    return hasPropsChanged(prevProps, nextProps, emits)\n  }\n\n  return false\n}\n\nfunction hasPropsChanged(\n  prevProps: Data,\n  nextProps: Data,\n  emitsOptions: ComponentInternalInstance['emitsOptions'],\n): boolean {\n  const nextKeys = Object.keys(nextProps)\n  if (nextKeys.length !== Object.keys(prevProps).length) {\n    return true\n  }\n  for (let i = 0; i < nextKeys.length; i++) {\n    const key = nextKeys[i]\n    if (\n      hasPropValueChanged(nextProps, prevProps, key) &&\n      !isEmitListener(emitsOptions, key)\n    ) {\n      return true\n    }\n  }\n  return false\n}\n\nfunction hasPropValueChanged(\n  nextProps: Data,\n  prevProps: Data,\n  key: string,\n): boolean {\n  const nextProp = nextProps[key]\n  const prevProp = prevProps[key]\n  if (key === 'style' && isObject(nextProp) && isObject(prevProp)) {\n    return !looseEqual(nextProp, prevProp)\n  }\n  return nextProp !== prevProp\n}\n\nexport function updateHOCHostEl(\n  { vnode, parent }: ComponentInternalInstance,\n  el: typeof vnode.el, // HostNode\n): void {\n  while (parent) {\n    const root = parent.subTree\n    if (root.suspense && root.suspense.activeBranch === vnode) {\n      root.el = vnode.el\n    }\n    if (root === vnode) {\n      ;(vnode = parent.vnode).el = el\n      parent = parent.parent\n    } else {\n      break\n    }\n  }\n}\n"
  },
  {
    "path": "packages/runtime-core/src/componentSlots.ts",
    "content": "import { type ComponentInternalInstance, currentInstance } from './component'\nimport {\n  type VNode,\n  type VNodeChild,\n  type VNodeNormalizedChildren,\n  normalizeVNode,\n} from './vnode'\nimport {\n  EMPTY_OBJ,\n  type IfAny,\n  type Prettify,\n  ShapeFlags,\n  SlotFlags,\n  def,\n  isArray,\n  isFunction,\n} from '@vue/shared'\nimport { warn } from './warning'\nimport { isKeepAlive } from './components/KeepAlive'\nimport {\n  type ContextualRenderFn,\n  currentRenderingInstance,\n  withCtx,\n} from './componentRenderContext'\nimport { isHmrUpdating } from './hmr'\nimport { DeprecationTypes, isCompatEnabled } from './compat/compatConfig'\nimport { TriggerOpTypes, trigger } from '@vue/reactivity'\nimport { createInternalObject } from './internalObject'\n\nexport type Slot<T extends any = any> = (\n  ...args: IfAny<T, any[], [T] | (T extends undefined ? [] : never)>\n) => VNode[]\n\nexport type InternalSlots = {\n  [name: string]: Slot | undefined\n}\n\nexport type Slots = Readonly<InternalSlots>\n\ndeclare const SlotSymbol: unique symbol\nexport type SlotsType<T extends Record<string, any> = Record<string, any>> = {\n  [SlotSymbol]?: T\n}\n\nexport type StrictUnwrapSlotsType<\n  S extends SlotsType,\n  T = NonNullable<S[typeof SlotSymbol]>,\n> = [keyof S] extends [never] ? Slots : Readonly<T> & T\n\nexport type UnwrapSlotsType<\n  S extends SlotsType,\n  T = NonNullable<S[typeof SlotSymbol]>,\n> = [keyof S] extends [never]\n  ? Slots\n  : Readonly<\n      Prettify<{\n        [K in keyof T]: NonNullable<T[K]> extends (...args: any[]) => any\n          ? T[K]\n          : Slot<T[K]>\n      }>\n    >\n\nexport type RawSlots = {\n  [name: string]: unknown\n  // manual render fn hint to skip forced children updates\n  $stable?: boolean\n  /**\n   * for tracking slot owner instance. This is attached during\n   * normalizeChildren when the component vnode is created.\n   * @internal\n   */\n  _ctx?: ComponentInternalInstance | null\n  /**\n   * indicates compiler generated slots\n   * we use a reserved property instead of a vnode patchFlag because the slots\n   * object may be directly passed down to a child component in a manual\n   * render function, and the optimization hint need to be on the slot object\n   * itself to be preserved.\n   * @internal\n   */\n  _?: SlotFlags\n}\n\nconst isInternalKey = (key: string) =>\n  key === '_' || key === '_ctx' || key === '$stable'\n\nconst normalizeSlotValue = (value: unknown): VNode[] =>\n  isArray(value)\n    ? value.map(normalizeVNode)\n    : [normalizeVNode(value as VNodeChild)]\n\nconst normalizeSlot = (\n  key: string,\n  rawSlot: Function,\n  ctx: ComponentInternalInstance | null | undefined,\n): Slot => {\n  if ((rawSlot as any)._n) {\n    // already normalized - #5353\n    return rawSlot as Slot\n  }\n  const normalized = withCtx((...args: any[]) => {\n    if (\n      __DEV__ &&\n      currentInstance &&\n      !(ctx === null && currentRenderingInstance) &&\n      !(ctx && ctx.root !== currentInstance.root)\n    ) {\n      warn(\n        `Slot \"${key}\" invoked outside of the render function: ` +\n          `this will not track dependencies used in the slot. ` +\n          `Invoke the slot function inside the render function instead.`,\n      )\n    }\n    return normalizeSlotValue(rawSlot(...args))\n  }, ctx) as Slot\n  // NOT a compiled slot\n  ;(normalized as ContextualRenderFn)._c = false\n  return normalized\n}\n\nconst normalizeObjectSlots = (\n  rawSlots: RawSlots,\n  slots: InternalSlots,\n  instance: ComponentInternalInstance,\n) => {\n  const ctx = rawSlots._ctx\n  for (const key in rawSlots) {\n    if (isInternalKey(key)) continue\n    const value = rawSlots[key]\n    if (isFunction(value)) {\n      slots[key] = normalizeSlot(key, value, ctx)\n    } else if (value != null) {\n      if (\n        __DEV__ &&\n        !(\n          __COMPAT__ &&\n          isCompatEnabled(DeprecationTypes.RENDER_FUNCTION, instance)\n        )\n      ) {\n        warn(\n          `Non-function value encountered for slot \"${key}\". ` +\n            `Prefer function slots for better performance.`,\n        )\n      }\n      const normalized = normalizeSlotValue(value)\n      slots[key] = () => normalized\n    }\n  }\n}\n\nconst normalizeVNodeSlots = (\n  instance: ComponentInternalInstance,\n  children: VNodeNormalizedChildren,\n) => {\n  if (\n    __DEV__ &&\n    !isKeepAlive(instance.vnode) &&\n    !(__COMPAT__ && isCompatEnabled(DeprecationTypes.RENDER_FUNCTION, instance))\n  ) {\n    warn(\n      `Non-function value encountered for default slot. ` +\n        `Prefer function slots for better performance.`,\n    )\n  }\n  const normalized = normalizeSlotValue(children)\n  instance.slots.default = () => normalized\n}\n\nconst assignSlots = (\n  slots: InternalSlots,\n  children: Slots,\n  optimized: boolean,\n) => {\n  for (const key in children) {\n    // #2893\n    // when rendering the optimized slots by manually written render function,\n    // do not copy the `slots._` compiler flag so that `renderSlot` creates\n    // slot Fragment with BAIL patchFlag to force full updates\n    if (optimized || !isInternalKey(key)) {\n      slots[key] = children[key]\n    }\n  }\n}\n\nexport const initSlots = (\n  instance: ComponentInternalInstance,\n  children: VNodeNormalizedChildren,\n  optimized: boolean,\n): void => {\n  const slots = (instance.slots = createInternalObject())\n  if (instance.vnode.shapeFlag & ShapeFlags.SLOTS_CHILDREN) {\n    const type = (children as RawSlots)._\n    if (type) {\n      assignSlots(slots, children as Slots, optimized)\n      // make compiler marker non-enumerable\n      if (optimized) {\n        def(slots, '_', type, true)\n      }\n    } else {\n      normalizeObjectSlots(children as RawSlots, slots, instance)\n    }\n  } else if (children) {\n    normalizeVNodeSlots(instance, children)\n  }\n}\n\nexport const updateSlots = (\n  instance: ComponentInternalInstance,\n  children: VNodeNormalizedChildren,\n  optimized: boolean,\n): void => {\n  const { vnode, slots } = instance\n  let needDeletionCheck = true\n  let deletionComparisonTarget = EMPTY_OBJ\n  if (vnode.shapeFlag & ShapeFlags.SLOTS_CHILDREN) {\n    const type = (children as RawSlots)._\n    if (type) {\n      // compiled slots.\n      if (__DEV__ && isHmrUpdating) {\n        // Parent was HMR updated so slot content may have changed.\n        // force update slots and mark instance for hmr as well\n        assignSlots(slots, children as Slots, optimized)\n        trigger(instance, TriggerOpTypes.SET, '$slots')\n      } else if (optimized && type === SlotFlags.STABLE) {\n        // compiled AND stable.\n        // no need to update, and skip stale slots removal.\n        needDeletionCheck = false\n      } else {\n        // compiled but dynamic (v-if/v-for on slots) - update slots, but skip\n        // normalization.\n        assignSlots(slots, children as Slots, optimized)\n      }\n    } else {\n      needDeletionCheck = !(children as RawSlots).$stable\n      normalizeObjectSlots(children as RawSlots, slots, instance)\n    }\n    deletionComparisonTarget = children as RawSlots\n  } else if (children) {\n    // non slot object children (direct value) passed to a component\n    normalizeVNodeSlots(instance, children)\n    deletionComparisonTarget = { default: 1 }\n  }\n\n  // delete stale slots\n  if (needDeletionCheck) {\n    for (const key in slots) {\n      if (!isInternalKey(key) && deletionComparisonTarget[key] == null) {\n        delete slots[key]\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "packages/runtime-core/src/components/BaseTransition.ts",
    "content": "import {\n  type ComponentInternalInstance,\n  type ComponentOptions,\n  type SetupContext,\n  getCurrentInstance,\n} from '../component'\nimport {\n  Comment,\n  Fragment,\n  type VNode,\n  type VNodeArrayChildren,\n  cloneVNode,\n  isSameVNodeType,\n} from '../vnode'\nimport { warn } from '../warning'\nimport { isKeepAlive } from './KeepAlive'\nimport { toRaw } from '@vue/reactivity'\nimport { ErrorCodes, callWithAsyncErrorHandling } from '../errorHandling'\nimport { PatchFlags, ShapeFlags, isArray, isFunction } from '@vue/shared'\nimport { onBeforeUnmount, onMounted } from '../apiLifecycle'\nimport { isTeleport } from './Teleport'\nimport type { RendererElement } from '../renderer'\nimport { SchedulerJobFlags } from '../scheduler'\n\ntype Hook<T = () => void> = T | T[]\n\nexport const leaveCbKey: unique symbol = Symbol('_leaveCb')\nconst enterCbKey: unique symbol = Symbol('_enterCb')\n\nexport interface BaseTransitionProps<HostElement = RendererElement> {\n  mode?: 'in-out' | 'out-in' | 'default'\n  appear?: boolean\n\n  // If true, indicates this is a transition that doesn't actually insert/remove\n  // the element, but toggles the show / hidden status instead.\n  // The transition hooks are injected, but will be skipped by the renderer.\n  // Instead, a custom directive can control the transition by calling the\n  // injected hooks (e.g. v-show).\n  persisted?: boolean\n\n  // Hooks. Using camel case for easier usage in render functions & JSX.\n  // In templates these can be written as @before-enter=\"xxx\" as prop names\n  // are camelized.\n  onBeforeEnter?: Hook<(el: HostElement) => void>\n  onEnter?: Hook<(el: HostElement, done: () => void) => void>\n  onAfterEnter?: Hook<(el: HostElement) => void>\n  onEnterCancelled?: Hook<(el: HostElement) => void>\n  // leave\n  onBeforeLeave?: Hook<(el: HostElement) => void>\n  onLeave?: Hook<(el: HostElement, done: () => void) => void>\n  onAfterLeave?: Hook<(el: HostElement) => void>\n  onLeaveCancelled?: Hook<(el: HostElement) => void> // only fired in persisted mode\n  // appear\n  onBeforeAppear?: Hook<(el: HostElement) => void>\n  onAppear?: Hook<(el: HostElement, done: () => void) => void>\n  onAfterAppear?: Hook<(el: HostElement) => void>\n  onAppearCancelled?: Hook<(el: HostElement) => void>\n}\n\nexport interface TransitionHooks<HostElement = RendererElement> {\n  mode: BaseTransitionProps['mode']\n  persisted: boolean\n  beforeEnter(el: HostElement): void\n  enter(el: HostElement): void\n  leave(el: HostElement, remove: () => void): void\n  clone(vnode: VNode): TransitionHooks<HostElement>\n  // optional\n  afterLeave?(): void\n  delayLeave?(\n    el: HostElement,\n    earlyRemove: () => void,\n    delayedLeave: () => void,\n  ): void\n  delayedLeave?(): void\n}\n\nexport type TransitionHookCaller = <T extends any[] = [el: any]>(\n  hook: Hook<(...args: T) => void> | undefined,\n  args?: T,\n) => void\n\nexport type PendingCallback = (cancelled?: boolean) => void\n\nexport interface TransitionState {\n  isMounted: boolean\n  isLeaving: boolean\n  isUnmounting: boolean\n  // Track pending leave callbacks for children of the same key.\n  // This is used to force remove leaving a child when a new copy is entering.\n  leavingVNodes: Map<any, Record<string, VNode>>\n}\n\nexport interface TransitionElement {\n  // in persisted mode (e.g. v-show), the same element is toggled, so the\n  // pending enter/leave callbacks may need to be cancelled if the state is toggled\n  // before it finishes.\n  [enterCbKey]?: PendingCallback\n  [leaveCbKey]?: PendingCallback\n}\n\nexport function useTransitionState(): TransitionState {\n  const state: TransitionState = {\n    isMounted: false,\n    isLeaving: false,\n    isUnmounting: false,\n    leavingVNodes: new Map(),\n  }\n  onMounted(() => {\n    state.isMounted = true\n  })\n  onBeforeUnmount(() => {\n    state.isUnmounting = true\n  })\n  return state\n}\n\nconst TransitionHookValidator = [Function, Array]\n\nexport const BaseTransitionPropsValidators: Record<string, any> = {\n  mode: String,\n  appear: Boolean,\n  persisted: Boolean,\n  // enter\n  onBeforeEnter: TransitionHookValidator,\n  onEnter: TransitionHookValidator,\n  onAfterEnter: TransitionHookValidator,\n  onEnterCancelled: TransitionHookValidator,\n  // leave\n  onBeforeLeave: TransitionHookValidator,\n  onLeave: TransitionHookValidator,\n  onAfterLeave: TransitionHookValidator,\n  onLeaveCancelled: TransitionHookValidator,\n  // appear\n  onBeforeAppear: TransitionHookValidator,\n  onAppear: TransitionHookValidator,\n  onAfterAppear: TransitionHookValidator,\n  onAppearCancelled: TransitionHookValidator,\n}\n\nconst recursiveGetSubtree = (instance: ComponentInternalInstance): VNode => {\n  const subTree = instance.subTree\n  return subTree.component ? recursiveGetSubtree(subTree.component) : subTree\n}\n\nconst BaseTransitionImpl: ComponentOptions = {\n  name: `BaseTransition`,\n\n  props: BaseTransitionPropsValidators,\n\n  setup(props: BaseTransitionProps, { slots }: SetupContext) {\n    const instance = getCurrentInstance()!\n    const state = useTransitionState()\n\n    return () => {\n      const children =\n        slots.default && getTransitionRawChildren(slots.default(), true)\n      if (!children || !children.length) {\n        return\n      }\n\n      const child: VNode = findNonCommentChild(children)\n      // there's no need to track reactivity for these props so use the raw\n      // props for a bit better perf\n      const rawProps = toRaw(props)\n      const { mode } = rawProps\n      // check mode\n      if (\n        __DEV__ &&\n        mode &&\n        mode !== 'in-out' &&\n        mode !== 'out-in' &&\n        mode !== 'default'\n      ) {\n        warn(`invalid <transition> mode: ${mode}`)\n      }\n\n      if (state.isLeaving) {\n        return emptyPlaceholder(child)\n      }\n\n      // in the case of <transition><keep-alive/></transition>, we need to\n      // compare the type of the kept-alive children.\n      const innerChild = getInnerChild(child)\n      if (!innerChild) {\n        return emptyPlaceholder(child)\n      }\n\n      let enterHooks = resolveTransitionHooks(\n        innerChild,\n        rawProps,\n        state,\n        instance,\n        // #11061, ensure enterHooks is fresh after clone\n        hooks => (enterHooks = hooks),\n      )\n\n      if (innerChild.type !== Comment) {\n        setTransitionHooks(innerChild, enterHooks)\n      }\n\n      let oldInnerChild = instance.subTree && getInnerChild(instance.subTree)\n\n      // handle mode\n      if (\n        oldInnerChild &&\n        oldInnerChild.type !== Comment &&\n        !isSameVNodeType(oldInnerChild, innerChild) &&\n        recursiveGetSubtree(instance).type !== Comment\n      ) {\n        let leavingHooks = resolveTransitionHooks(\n          oldInnerChild,\n          rawProps,\n          state,\n          instance,\n        )\n        // update old tree's hooks in case of dynamic transition\n        setTransitionHooks(oldInnerChild, leavingHooks)\n        // switching between different views\n        if (mode === 'out-in' && innerChild.type !== Comment) {\n          state.isLeaving = true\n          // return placeholder node and queue update when leave finishes\n          leavingHooks.afterLeave = () => {\n            state.isLeaving = false\n            // #6835\n            // it also needs to be updated when active is undefined\n            if (!(instance.job.flags! & SchedulerJobFlags.DISPOSED)) {\n              instance.update()\n            }\n            delete leavingHooks.afterLeave\n            oldInnerChild = undefined\n          }\n          return emptyPlaceholder(child)\n        } else if (mode === 'in-out' && innerChild.type !== Comment) {\n          leavingHooks.delayLeave = (\n            el: TransitionElement,\n            earlyRemove,\n            delayedLeave,\n          ) => {\n            const leavingVNodesCache = getLeavingNodesForType(\n              state,\n              oldInnerChild!,\n            )\n            leavingVNodesCache[String(oldInnerChild!.key)] = oldInnerChild!\n            // early removal callback\n            el[leaveCbKey] = () => {\n              earlyRemove()\n              el[leaveCbKey] = undefined\n              delete enterHooks.delayedLeave\n              oldInnerChild = undefined\n            }\n            enterHooks.delayedLeave = () => {\n              delayedLeave()\n              delete enterHooks.delayedLeave\n              oldInnerChild = undefined\n            }\n          }\n        } else {\n          oldInnerChild = undefined\n        }\n      } else if (oldInnerChild) {\n        oldInnerChild = undefined\n      }\n\n      return child\n    }\n  },\n}\n\nif (__COMPAT__) {\n  BaseTransitionImpl.__isBuiltIn = true\n}\n\nfunction findNonCommentChild(children: VNode[]): VNode {\n  let child: VNode = children[0]\n  if (children.length > 1) {\n    let hasFound = false\n    // locate first non-comment child\n    for (const c of children) {\n      if (c.type !== Comment) {\n        if (__DEV__ && hasFound) {\n          // warn more than one non-comment child\n          warn(\n            '<transition> can only be used on a single element or component. ' +\n              'Use <transition-group> for lists.',\n          )\n          break\n        }\n        child = c\n        hasFound = true\n        if (!__DEV__) break\n      }\n    }\n  }\n  return child\n}\n\n// export the public type for h/tsx inference\n// also to avoid inline import() in generated d.ts files\nexport const BaseTransition = BaseTransitionImpl as unknown as {\n  new (): {\n    $props: BaseTransitionProps<any>\n    $slots: {\n      default(): VNode[]\n    }\n  }\n}\n\nfunction getLeavingNodesForType(\n  state: TransitionState,\n  vnode: VNode,\n): Record<string, VNode> {\n  const { leavingVNodes } = state\n  let leavingVNodesCache = leavingVNodes.get(vnode.type)!\n  if (!leavingVNodesCache) {\n    leavingVNodesCache = Object.create(null)\n    leavingVNodes.set(vnode.type, leavingVNodesCache)\n  }\n  return leavingVNodesCache\n}\n\n// The transition hooks are attached to the vnode as vnode.transition\n// and will be called at appropriate timing in the renderer.\nexport function resolveTransitionHooks(\n  vnode: VNode,\n  props: BaseTransitionProps<any>,\n  state: TransitionState,\n  instance: ComponentInternalInstance,\n  postClone?: (hooks: TransitionHooks) => void,\n): TransitionHooks {\n  const {\n    appear,\n    mode,\n    persisted = false,\n    onBeforeEnter,\n    onEnter,\n    onAfterEnter,\n    onEnterCancelled,\n    onBeforeLeave,\n    onLeave,\n    onAfterLeave,\n    onLeaveCancelled,\n    onBeforeAppear,\n    onAppear,\n    onAfterAppear,\n    onAppearCancelled,\n  } = props\n  const key = String(vnode.key)\n  const leavingVNodesCache = getLeavingNodesForType(state, vnode)\n\n  const callHook: TransitionHookCaller = (hook, args) => {\n    hook &&\n      callWithAsyncErrorHandling(\n        hook,\n        instance,\n        ErrorCodes.TRANSITION_HOOK,\n        args,\n      )\n  }\n\n  const callAsyncHook = (\n    hook: Hook<(el: any, done: () => void) => void>,\n    args: [TransitionElement, () => void],\n  ) => {\n    const done = args[1]\n    callHook(hook, args)\n    if (isArray(hook)) {\n      if (hook.every(hook => hook.length <= 1)) done()\n    } else if (hook.length <= 1) {\n      done()\n    }\n  }\n\n  const hooks: TransitionHooks<TransitionElement> = {\n    mode,\n    persisted,\n    beforeEnter(el) {\n      let hook = onBeforeEnter\n      if (!state.isMounted) {\n        if (appear) {\n          hook = onBeforeAppear || onBeforeEnter\n        } else {\n          return\n        }\n      }\n      // for same element (v-show)\n      if (el[leaveCbKey]) {\n        el[leaveCbKey](true /* cancelled */)\n      }\n      // for toggled element with same key (v-if)\n      const leavingVNode = leavingVNodesCache[key]\n      if (\n        leavingVNode &&\n        isSameVNodeType(vnode, leavingVNode) &&\n        (leavingVNode.el as TransitionElement)[leaveCbKey]\n      ) {\n        // force early removal (not cancelled)\n        ;(leavingVNode.el as TransitionElement)[leaveCbKey]!()\n      }\n      callHook(hook, [el])\n    },\n\n    enter(el) {\n      // prevent enter if leave is in progress\n      if (leavingVNodesCache[key] === vnode) return\n      let hook = onEnter\n      let afterHook = onAfterEnter\n      let cancelHook = onEnterCancelled\n      if (!state.isMounted) {\n        if (appear) {\n          hook = onAppear || onEnter\n          afterHook = onAfterAppear || onAfterEnter\n          cancelHook = onAppearCancelled || onEnterCancelled\n        } else {\n          return\n        }\n      }\n      let called = false\n      el[enterCbKey] = (cancelled?) => {\n        if (called) return\n        called = true\n        if (cancelled) {\n          callHook(cancelHook, [el])\n        } else {\n          callHook(afterHook, [el])\n        }\n        if (hooks.delayedLeave) {\n          hooks.delayedLeave()\n        }\n        el[enterCbKey] = undefined\n      }\n      const done = el[enterCbKey]!.bind(null, false)\n      if (hook) {\n        callAsyncHook(hook, [el, done])\n      } else {\n        done()\n      }\n    },\n\n    leave(el, remove) {\n      const key = String(vnode.key)\n      if (el[enterCbKey]) {\n        el[enterCbKey](true /* cancelled */)\n      }\n      if (state.isUnmounting) {\n        return remove()\n      }\n      callHook(onBeforeLeave, [el])\n      let called = false\n      el[leaveCbKey] = (cancelled?) => {\n        if (called) return\n        called = true\n        remove()\n        if (cancelled) {\n          callHook(onLeaveCancelled, [el])\n        } else {\n          callHook(onAfterLeave, [el])\n        }\n        el[leaveCbKey] = undefined\n        if (leavingVNodesCache[key] === vnode) {\n          delete leavingVNodesCache[key]\n        }\n      }\n      const done = el[leaveCbKey]!.bind(null, false)\n      leavingVNodesCache[key] = vnode\n      if (onLeave) {\n        callAsyncHook(onLeave, [el, done])\n      } else {\n        done()\n      }\n    },\n\n    clone(vnode) {\n      const hooks = resolveTransitionHooks(\n        vnode,\n        props,\n        state,\n        instance,\n        postClone,\n      )\n      if (postClone) postClone(hooks)\n      return hooks\n    },\n  }\n\n  return hooks\n}\n\n// the placeholder really only handles one special case: KeepAlive\n// in the case of a KeepAlive in a leave phase we need to return a KeepAlive\n// placeholder with empty content to avoid the KeepAlive instance from being\n// unmounted.\nfunction emptyPlaceholder(vnode: VNode): VNode | undefined {\n  if (isKeepAlive(vnode)) {\n    vnode = cloneVNode(vnode)\n    vnode.children = null\n    return vnode\n  }\n}\n\nfunction getInnerChild(vnode: VNode): VNode | undefined {\n  if (!isKeepAlive(vnode)) {\n    if (isTeleport(vnode.type) && vnode.children) {\n      return findNonCommentChild(vnode.children as VNode[])\n    }\n\n    return vnode\n  }\n  // #7121,#12465 get the component subtree if it's been mounted\n  if (vnode.component) {\n    return vnode.component.subTree\n  }\n\n  const { shapeFlag, children } = vnode\n\n  if (children) {\n    if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) {\n      return (children as VNodeArrayChildren)[0] as VNode\n    }\n\n    if (\n      shapeFlag & ShapeFlags.SLOTS_CHILDREN &&\n      isFunction((children as any).default)\n    ) {\n      return (children as any).default()\n    }\n  }\n}\n\nexport function setTransitionHooks(vnode: VNode, hooks: TransitionHooks): void {\n  if (vnode.shapeFlag & ShapeFlags.COMPONENT && vnode.component) {\n    vnode.transition = hooks\n    setTransitionHooks(vnode.component.subTree, hooks)\n  } else if (__FEATURE_SUSPENSE__ && vnode.shapeFlag & ShapeFlags.SUSPENSE) {\n    vnode.ssContent!.transition = hooks.clone(vnode.ssContent!)\n    vnode.ssFallback!.transition = hooks.clone(vnode.ssFallback!)\n  } else {\n    vnode.transition = hooks\n  }\n}\n\nexport function getTransitionRawChildren(\n  children: VNode[],\n  keepComment: boolean = false,\n  parentKey?: VNode['key'],\n): VNode[] {\n  let ret: VNode[] = []\n  let keyedFragmentCount = 0\n  for (let i = 0; i < children.length; i++) {\n    let child = children[i]\n    // #5360 inherit parent key in case of <template v-for>\n    const key =\n      parentKey == null\n        ? child.key\n        : String(parentKey) + String(child.key != null ? child.key : i)\n    // handle fragment children case, e.g. v-for\n    if (child.type === Fragment) {\n      if (child.patchFlag & PatchFlags.KEYED_FRAGMENT) keyedFragmentCount++\n      ret = ret.concat(\n        getTransitionRawChildren(child.children as VNode[], keepComment, key),\n      )\n    }\n    // comment placeholders should be skipped, e.g. v-if\n    else if (keepComment || child.type !== Comment) {\n      ret.push(key != null ? cloneVNode(child, { key }) : child)\n    }\n  }\n  // #1126 if a transition children list contains multiple sub fragments, these\n  // fragments will be merged into a flat children array. Since each v-for\n  // fragment may contain different static bindings inside, we need to de-op\n  // these children to force full diffs to ensure correct behavior.\n  if (keyedFragmentCount > 1) {\n    for (let i = 0; i < ret.length; i++) {\n      ret[i].patchFlag = PatchFlags.BAIL\n    }\n  }\n  return ret\n}\n"
  },
  {
    "path": "packages/runtime-core/src/components/KeepAlive.ts",
    "content": "import {\n  type ComponentInternalInstance,\n  type ComponentOptions,\n  type ConcreteComponent,\n  type SetupContext,\n  currentInstance,\n  getComponentName,\n  getCurrentInstance,\n} from '../component'\nimport {\n  Comment,\n  type VNode,\n  type VNodeProps,\n  cloneVNode,\n  invokeVNodeHook,\n  isSameVNodeType,\n  isVNode,\n} from '../vnode'\nimport { warn } from '../warning'\nimport {\n  injectHook,\n  onBeforeUnmount,\n  onMounted,\n  onUnmounted,\n  onUpdated,\n} from '../apiLifecycle'\nimport {\n  ShapeFlags,\n  invokeArrayFns,\n  isArray,\n  isRegExp,\n  isString,\n  remove,\n} from '@vue/shared'\nimport { watch } from '../apiWatch'\nimport {\n  type ElementNamespace,\n  MoveType,\n  type RendererElement,\n  type RendererInternals,\n  type RendererNode,\n  invalidateMount,\n  queuePostRenderEffect,\n} from '../renderer'\nimport { setTransitionHooks } from './BaseTransition'\nimport type { ComponentRenderContext } from '../componentPublicInstance'\nimport { devtoolsComponentAdded } from '../devtools'\nimport { isAsyncWrapper } from '../apiAsyncComponent'\nimport { isSuspense } from './Suspense'\nimport { LifecycleHooks } from '../enums'\n\ntype MatchPattern = string | RegExp | (string | RegExp)[]\n\nexport interface KeepAliveProps {\n  include?: MatchPattern\n  exclude?: MatchPattern\n  max?: number | string\n}\n\ntype CacheKey = PropertyKey | ConcreteComponent\ntype Cache = Map<CacheKey, VNode>\ntype Keys = Set<CacheKey>\n\nexport interface KeepAliveContext extends ComponentRenderContext {\n  renderer: RendererInternals\n  activate: (\n    vnode: VNode,\n    container: RendererElement,\n    anchor: RendererNode | null,\n    namespace: ElementNamespace,\n    optimized: boolean,\n  ) => void\n  deactivate: (vnode: VNode) => void\n}\n\nexport const isKeepAlive = (vnode: VNode): boolean =>\n  (vnode.type as any).__isKeepAlive\n\nconst KeepAliveImpl: ComponentOptions = {\n  name: `KeepAlive`,\n\n  // Marker for special handling inside the renderer. We are not using a ===\n  // check directly on KeepAlive in the renderer, because importing it directly\n  // would prevent it from being tree-shaken.\n  __isKeepAlive: true,\n\n  props: {\n    include: [String, RegExp, Array],\n    exclude: [String, RegExp, Array],\n    max: [String, Number],\n  },\n\n  setup(props: KeepAliveProps, { slots }: SetupContext) {\n    const instance = getCurrentInstance()!\n    // KeepAlive communicates with the instantiated renderer via the\n    // ctx where the renderer passes in its internals,\n    // and the KeepAlive instance exposes activate/deactivate implementations.\n    // The whole point of this is to avoid importing KeepAlive directly in the\n    // renderer to facilitate tree-shaking.\n    const sharedContext = instance.ctx as KeepAliveContext\n\n    // if the internal renderer is not registered, it indicates that this is server-side rendering,\n    // for KeepAlive, we just need to render its children\n    if (__SSR__ && !sharedContext.renderer) {\n      return () => {\n        const children = slots.default && slots.default()\n        return children && children.length === 1 ? children[0] : children\n      }\n    }\n\n    const cache: Cache = new Map()\n    const keys: Keys = new Set()\n    let current: VNode | null = null\n\n    if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {\n      ;(instance as any).__v_cache = cache\n    }\n\n    const parentSuspense = instance.suspense\n\n    const {\n      renderer: {\n        p: patch,\n        m: move,\n        um: _unmount,\n        o: { createElement },\n      },\n    } = sharedContext\n    const storageContainer = createElement('div')\n\n    sharedContext.activate = (\n      vnode,\n      container,\n      anchor,\n      namespace,\n      optimized,\n    ) => {\n      const instance = vnode.component!\n      move(vnode, container, anchor, MoveType.ENTER, parentSuspense)\n      // in case props have changed\n      patch(\n        instance.vnode,\n        vnode,\n        container,\n        anchor,\n        instance,\n        parentSuspense,\n        namespace,\n        vnode.slotScopeIds,\n        optimized,\n      )\n      queuePostRenderEffect(() => {\n        instance.isDeactivated = false\n        if (instance.a) {\n          invokeArrayFns(instance.a)\n        }\n        const vnodeHook = vnode.props && vnode.props.onVnodeMounted\n        if (vnodeHook) {\n          invokeVNodeHook(vnodeHook, instance.parent, vnode)\n        }\n      }, parentSuspense)\n\n      if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {\n        // Update components tree\n        devtoolsComponentAdded(instance)\n      }\n    }\n\n    sharedContext.deactivate = (vnode: VNode) => {\n      const instance = vnode.component!\n      invalidateMount(instance.m)\n      invalidateMount(instance.a)\n\n      move(vnode, storageContainer, null, MoveType.LEAVE, parentSuspense)\n      queuePostRenderEffect(() => {\n        if (instance.da) {\n          invokeArrayFns(instance.da)\n        }\n        const vnodeHook = vnode.props && vnode.props.onVnodeUnmounted\n        if (vnodeHook) {\n          invokeVNodeHook(vnodeHook, instance.parent, vnode)\n        }\n        instance.isDeactivated = true\n      }, parentSuspense)\n\n      if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {\n        // Update components tree\n        devtoolsComponentAdded(instance)\n      }\n\n      // for e2e test\n      if (__DEV__ && __BROWSER__) {\n        ;(instance as any).__keepAliveStorageContainer = storageContainer\n      }\n    }\n\n    function unmount(vnode: VNode) {\n      // reset the shapeFlag so it can be properly unmounted\n      resetShapeFlag(vnode)\n      _unmount(vnode, instance, parentSuspense, true)\n    }\n\n    function pruneCache(filter: (name: string) => boolean) {\n      cache.forEach((vnode, key) => {\n        // for async components, name check should be based in its loaded\n        // inner component if available\n        const name = getComponentName(\n          isAsyncWrapper(vnode)\n            ? (vnode.type as ComponentOptions).__asyncResolved || {}\n            : (vnode.type as ConcreteComponent),\n        )\n        if (name && !filter(name)) {\n          pruneCacheEntry(key)\n        }\n      })\n    }\n\n    function pruneCacheEntry(key: CacheKey) {\n      const cached = cache.get(key) as VNode\n      if (cached && (!current || !isSameVNodeType(cached, current))) {\n        unmount(cached)\n      } else if (current) {\n        // current active instance should no longer be kept-alive.\n        // we can't unmount it now but it might be later, so reset its flag now.\n        resetShapeFlag(current)\n      }\n      cache.delete(key)\n      keys.delete(key)\n    }\n\n    // prune cache on include/exclude prop change\n    watch(\n      () => [props.include, props.exclude],\n      ([include, exclude]) => {\n        include && pruneCache(name => matches(include, name))\n        exclude && pruneCache(name => !matches(exclude, name))\n      },\n      // prune post-render after `current` has been updated\n      { flush: 'post', deep: true },\n    )\n\n    // cache sub tree after render\n    let pendingCacheKey: CacheKey | null = null\n    const cacheSubtree = () => {\n      // fix #1621, the pendingCacheKey could be 0\n      if (pendingCacheKey != null) {\n        // if KeepAlive child is a Suspense, it needs to be cached after Suspense resolves\n        // avoid caching vnode that not been mounted\n        if (isSuspense(instance.subTree.type)) {\n          queuePostRenderEffect(() => {\n            cache.set(pendingCacheKey!, getInnerChild(instance.subTree))\n          }, instance.subTree.suspense)\n        } else {\n          cache.set(pendingCacheKey, getInnerChild(instance.subTree))\n        }\n      }\n    }\n    onMounted(cacheSubtree)\n    onUpdated(cacheSubtree)\n\n    onBeforeUnmount(() => {\n      cache.forEach(cached => {\n        const { subTree, suspense } = instance\n        const vnode = getInnerChild(subTree)\n        if (cached.type === vnode.type && cached.key === vnode.key) {\n          // current instance will be unmounted as part of keep-alive's unmount\n          resetShapeFlag(vnode)\n          // but invoke its deactivated hook here\n          const da = vnode.component!.da\n          da && queuePostRenderEffect(da, suspense)\n          return\n        }\n        unmount(cached)\n      })\n    })\n\n    return () => {\n      pendingCacheKey = null\n\n      if (!slots.default) {\n        return (current = null)\n      }\n\n      const children = slots.default()\n      const rawVNode = children[0]\n      if (children.length > 1) {\n        if (__DEV__) {\n          warn(`KeepAlive should contain exactly one component child.`)\n        }\n        current = null\n        return children\n      } else if (\n        !isVNode(rawVNode) ||\n        (!(rawVNode.shapeFlag & ShapeFlags.STATEFUL_COMPONENT) &&\n          !(rawVNode.shapeFlag & ShapeFlags.SUSPENSE))\n      ) {\n        current = null\n        return rawVNode\n      }\n\n      let vnode = getInnerChild(rawVNode)\n      // #6028 Suspense ssContent maybe a comment VNode, should avoid caching it\n      if (vnode.type === Comment) {\n        current = null\n        return vnode\n      }\n\n      const comp = vnode.type as ConcreteComponent\n\n      // for async components, name check should be based in its loaded\n      // inner component if available\n      const name = getComponentName(\n        isAsyncWrapper(vnode)\n          ? (vnode.type as ComponentOptions).__asyncResolved || {}\n          : comp,\n      )\n\n      const { include, exclude, max } = props\n\n      if (\n        (include && (!name || !matches(include, name))) ||\n        (exclude && name && matches(exclude, name))\n      ) {\n        // #11717\n        vnode.shapeFlag &= ~ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE\n        current = vnode\n        return rawVNode\n      }\n\n      const key = vnode.key == null ? comp : vnode.key\n      const cachedVNode = cache.get(key)\n\n      // clone vnode if it's reused because we are going to mutate it\n      if (vnode.el) {\n        vnode = cloneVNode(vnode)\n        if (rawVNode.shapeFlag & ShapeFlags.SUSPENSE) {\n          rawVNode.ssContent = vnode\n        }\n      }\n      // #1511 it's possible for the returned vnode to be cloned due to attr\n      // fallthrough or scopeId, so the vnode here may not be the final vnode\n      // that is mounted. Instead of caching it directly, we store the pending\n      // key and cache `instance.subTree` (the normalized vnode) in\n      // mounted/updated hooks.\n      pendingCacheKey = key\n\n      if (cachedVNode) {\n        // copy over mounted state\n        vnode.el = cachedVNode.el\n        vnode.component = cachedVNode.component\n        if (vnode.transition) {\n          // recursively update transition hooks on subTree\n          setTransitionHooks(vnode, vnode.transition!)\n        }\n        // avoid vnode being mounted as fresh\n        vnode.shapeFlag |= ShapeFlags.COMPONENT_KEPT_ALIVE\n        // make this key the freshest\n        keys.delete(key)\n        keys.add(key)\n      } else {\n        keys.add(key)\n        // prune oldest entry\n        if (max && keys.size > parseInt(max as string, 10)) {\n          pruneCacheEntry(keys.values().next().value!)\n        }\n      }\n      // avoid vnode being unmounted\n      vnode.shapeFlag |= ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE\n\n      current = vnode\n      return isSuspense(rawVNode.type) ? rawVNode : vnode\n    }\n  },\n}\n\nconst decorate = (t: typeof KeepAliveImpl) => {\n  t.__isBuiltIn = true\n  return t\n}\n\n// export the public type for h/tsx inference\n// also to avoid inline import() in generated d.ts files\nexport const KeepAlive = (__COMPAT__\n  ? /*@__PURE__*/ decorate(KeepAliveImpl)\n  : KeepAliveImpl) as any as {\n  __isKeepAlive: true\n  new (): {\n    $props: VNodeProps & KeepAliveProps\n    $slots: {\n      default(): VNode[]\n    }\n  }\n}\n\nfunction matches(pattern: MatchPattern, name: string): boolean {\n  if (isArray(pattern)) {\n    return pattern.some((p: string | RegExp) => matches(p, name))\n  } else if (isString(pattern)) {\n    return pattern.split(',').includes(name)\n  } else if (isRegExp(pattern)) {\n    pattern.lastIndex = 0\n    return pattern.test(name)\n  }\n  /* v8 ignore next */\n  return false\n}\n\nexport function onActivated(\n  hook: Function,\n  target?: ComponentInternalInstance | null,\n): void {\n  registerKeepAliveHook(hook, LifecycleHooks.ACTIVATED, target)\n}\n\nexport function onDeactivated(\n  hook: Function,\n  target?: ComponentInternalInstance | null,\n): void {\n  registerKeepAliveHook(hook, LifecycleHooks.DEACTIVATED, target)\n}\n\nfunction registerKeepAliveHook(\n  hook: Function & { __wdc?: Function },\n  type: LifecycleHooks,\n  target: ComponentInternalInstance | null = currentInstance,\n) {\n  // cache the deactivate branch check wrapper for injected hooks so the same\n  // hook can be properly deduped by the scheduler. \"__wdc\" stands for \"with\n  // deactivation check\".\n  const wrappedHook =\n    hook.__wdc ||\n    (hook.__wdc = () => {\n      // only fire the hook if the target instance is NOT in a deactivated branch.\n      let current: ComponentInternalInstance | null = target\n      while (current) {\n        if (current.isDeactivated) {\n          return\n        }\n        current = current.parent\n      }\n      return hook()\n    })\n  injectHook(type, wrappedHook, target)\n  // In addition to registering it on the target instance, we walk up the parent\n  // chain and register it on all ancestor instances that are keep-alive roots.\n  // This avoids the need to walk the entire component tree when invoking these\n  // hooks, and more importantly, avoids the need to track child components in\n  // arrays.\n  if (target) {\n    let current = target.parent\n    while (current && current.parent) {\n      if (isKeepAlive(current.parent.vnode)) {\n        injectToKeepAliveRoot(wrappedHook, type, target, current)\n      }\n      current = current.parent\n    }\n  }\n}\n\nfunction injectToKeepAliveRoot(\n  hook: Function & { __weh?: Function },\n  type: LifecycleHooks,\n  target: ComponentInternalInstance,\n  keepAliveRoot: ComponentInternalInstance,\n) {\n  // injectHook wraps the original for error handling, so make sure to remove\n  // the wrapped version.\n  const injected = injectHook(type, hook, keepAliveRoot, true /* prepend */)\n  onUnmounted(() => {\n    remove(keepAliveRoot[type]!, injected)\n  }, target)\n}\n\nfunction resetShapeFlag(vnode: VNode) {\n  // bitwise operations to remove keep alive flags\n  vnode.shapeFlag &= ~ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE\n  vnode.shapeFlag &= ~ShapeFlags.COMPONENT_KEPT_ALIVE\n}\n\nfunction getInnerChild(vnode: VNode) {\n  return vnode.shapeFlag & ShapeFlags.SUSPENSE ? vnode.ssContent! : vnode\n}\n"
  },
  {
    "path": "packages/runtime-core/src/components/Suspense.ts",
    "content": "import {\n  Comment,\n  type VNode,\n  type VNodeProps,\n  closeBlock,\n  createVNode,\n  currentBlock,\n  isBlockTreeEnabled,\n  isSameVNodeType,\n  normalizeVNode,\n  openBlock,\n} from '../vnode'\nimport { ShapeFlags, isArray, isFunction, toNumber } from '@vue/shared'\nimport { type ComponentInternalInstance, handleSetupResult } from '../component'\nimport type { Slots } from '../componentSlots'\nimport {\n  type ElementNamespace,\n  MoveType,\n  type RendererElement,\n  type RendererInternals,\n  type RendererNode,\n  type SetupRenderEffectFn,\n  queuePostRenderEffect,\n} from '../renderer'\nimport { queuePostFlushCb } from '../scheduler'\nimport { filterSingleRoot, updateHOCHostEl } from '../componentRenderUtils'\nimport {\n  assertNumber,\n  popWarningContext,\n  pushWarningContext,\n  warn,\n} from '../warning'\nimport { ErrorCodes, handleError } from '../errorHandling'\nimport { NULL_DYNAMIC_COMPONENT } from '../helpers/resolveAssets'\n\nexport interface SuspenseProps {\n  onResolve?: () => void\n  onPending?: () => void\n  onFallback?: () => void\n  timeout?: string | number\n  /**\n   * Allow suspense to be captured by parent suspense\n   *\n   * @default false\n   */\n  suspensible?: boolean\n}\n\nexport const isSuspense = (type: any): boolean => type.__isSuspense\n\n// incrementing unique id for every pending branch\nlet suspenseId = 0\n\n/**\n * For testing only\n */\nexport const resetSuspenseId = (): number => (suspenseId = 0)\n\n// Suspense exposes a component-like API, and is treated like a component\n// in the compiler, but internally it's a special built-in type that hooks\n// directly into the renderer.\nexport const SuspenseImpl = {\n  name: 'Suspense',\n  // In order to make Suspense tree-shakable, we need to avoid importing it\n  // directly in the renderer. The renderer checks for the __isSuspense flag\n  // on a vnode's type and calls the `process` method, passing in renderer\n  // internals.\n  __isSuspense: true,\n  process(\n    n1: VNode | null,\n    n2: VNode,\n    container: RendererElement,\n    anchor: RendererNode | null,\n    parentComponent: ComponentInternalInstance | null,\n    parentSuspense: SuspenseBoundary | null,\n    namespace: ElementNamespace,\n    slotScopeIds: string[] | null,\n    optimized: boolean,\n    // platform-specific impl passed from renderer\n    rendererInternals: RendererInternals,\n  ): void {\n    if (n1 == null) {\n      mountSuspense(\n        n2,\n        container,\n        anchor,\n        parentComponent,\n        parentSuspense,\n        namespace,\n        slotScopeIds,\n        optimized,\n        rendererInternals,\n      )\n    } else {\n      // #8678 if the current suspense needs to be patched and parentSuspense has\n      // not been resolved. this means that both the current suspense and parentSuspense\n      // need to be patched. because parentSuspense's pendingBranch includes the\n      // current suspense, it will be processed twice:\n      //  1. current patch\n      //  2. mounting along with the pendingBranch of parentSuspense\n      // it is necessary to skip the current patch to avoid multiple mounts\n      // of inner components.\n      if (\n        parentSuspense &&\n        parentSuspense.deps > 0 &&\n        !n1.suspense!.isInFallback\n      ) {\n        n2.suspense = n1.suspense!\n        n2.suspense.vnode = n2\n        n2.el = n1.el\n        return\n      }\n      patchSuspense(\n        n1,\n        n2,\n        container,\n        anchor,\n        parentComponent,\n        namespace,\n        slotScopeIds,\n        optimized,\n        rendererInternals,\n      )\n    }\n  },\n  hydrate: hydrateSuspense as typeof hydrateSuspense,\n  normalize: normalizeSuspenseChildren as typeof normalizeSuspenseChildren,\n}\n\n// Force-casted public typing for h and TSX props inference\nexport const Suspense = (__FEATURE_SUSPENSE__\n  ? SuspenseImpl\n  : null) as unknown as {\n  __isSuspense: true\n  new (): {\n    $props: VNodeProps & SuspenseProps\n    $slots: {\n      default(): VNode[]\n      fallback(): VNode[]\n    }\n  }\n}\n\nfunction triggerEvent(\n  vnode: VNode,\n  name: 'onResolve' | 'onPending' | 'onFallback',\n) {\n  const eventListener = vnode.props && vnode.props[name]\n  if (isFunction(eventListener)) {\n    eventListener()\n  }\n}\n\nfunction mountSuspense(\n  vnode: VNode,\n  container: RendererElement,\n  anchor: RendererNode | null,\n  parentComponent: ComponentInternalInstance | null,\n  parentSuspense: SuspenseBoundary | null,\n  namespace: ElementNamespace,\n  slotScopeIds: string[] | null,\n  optimized: boolean,\n  rendererInternals: RendererInternals,\n) {\n  const {\n    p: patch,\n    o: { createElement },\n  } = rendererInternals\n  const hiddenContainer = createElement('div')\n  const suspense = (vnode.suspense = createSuspenseBoundary(\n    vnode,\n    parentSuspense,\n    parentComponent,\n    container,\n    hiddenContainer,\n    anchor,\n    namespace,\n    slotScopeIds,\n    optimized,\n    rendererInternals,\n  ))\n\n  // start mounting the content subtree in an off-dom container\n  patch(\n    null,\n    (suspense.pendingBranch = vnode.ssContent!),\n    hiddenContainer,\n    null,\n    parentComponent,\n    suspense,\n    namespace,\n    slotScopeIds,\n  )\n  // now check if we have encountered any async deps\n  if (suspense.deps > 0) {\n    // has async\n    // invoke @fallback event\n    triggerEvent(vnode, 'onPending')\n    triggerEvent(vnode, 'onFallback')\n\n    // mount the fallback tree\n    patch(\n      null,\n      vnode.ssFallback!,\n      container,\n      anchor,\n      parentComponent,\n      null, // fallback tree will not have suspense context\n      namespace,\n      slotScopeIds,\n    )\n    setActiveBranch(suspense, vnode.ssFallback!)\n  } else {\n    // Suspense has no async deps. Just resolve.\n    suspense.resolve(false, true)\n  }\n}\n\nfunction patchSuspense(\n  n1: VNode,\n  n2: VNode,\n  container: RendererElement,\n  anchor: RendererNode | null,\n  parentComponent: ComponentInternalInstance | null,\n  namespace: ElementNamespace,\n  slotScopeIds: string[] | null,\n  optimized: boolean,\n  { p: patch, um: unmount, o: { createElement } }: RendererInternals,\n) {\n  const suspense = (n2.suspense = n1.suspense)!\n  suspense.vnode = n2\n  n2.el = n1.el\n  const newBranch = n2.ssContent!\n  const newFallback = n2.ssFallback!\n\n  const { activeBranch, pendingBranch, isInFallback, isHydrating } = suspense\n  if (pendingBranch) {\n    suspense.pendingBranch = newBranch\n    if (isSameVNodeType(pendingBranch, newBranch)) {\n      // same root type but content may have changed.\n      patch(\n        pendingBranch,\n        newBranch,\n        suspense.hiddenContainer,\n        null,\n        parentComponent,\n        suspense,\n        namespace,\n        slotScopeIds,\n        optimized,\n      )\n      if (suspense.deps <= 0) {\n        suspense.resolve()\n      } else if (isInFallback) {\n        // It's possible that the app is in hydrating state when patching the\n        // suspense instance. If someone updates the dependency during component\n        // setup in children of suspense boundary, that would be problemtic\n        // because we aren't actually showing a fallback content when\n        // patchSuspense is called. In such case, patch of fallback content\n        // should be no op\n        if (!isHydrating) {\n          patch(\n            activeBranch,\n            newFallback,\n            container,\n            anchor,\n            parentComponent,\n            null, // fallback tree will not have suspense context\n            namespace,\n            slotScopeIds,\n            optimized,\n          )\n          setActiveBranch(suspense, newFallback)\n        }\n      }\n    } else {\n      // toggled before pending tree is resolved\n      // increment pending ID. this is used to invalidate async callbacks\n      suspense.pendingId = suspenseId++\n      if (isHydrating) {\n        // if toggled before hydration is finished, the current DOM tree is\n        // no longer valid. set it as the active branch so it will be unmounted\n        // when resolved\n        suspense.isHydrating = false\n        suspense.activeBranch = pendingBranch\n      } else {\n        unmount(pendingBranch, parentComponent, suspense)\n      }\n      // reset suspense state\n      suspense.deps = 0\n      // discard effects from pending branch\n      suspense.effects.length = 0\n      // discard previous container\n      suspense.hiddenContainer = createElement('div')\n\n      if (isInFallback) {\n        // already in fallback state\n        patch(\n          null,\n          newBranch,\n          suspense.hiddenContainer,\n          null,\n          parentComponent,\n          suspense,\n          namespace,\n          slotScopeIds,\n          optimized,\n        )\n        if (suspense.deps <= 0) {\n          suspense.resolve()\n        } else {\n          patch(\n            activeBranch,\n            newFallback,\n            container,\n            anchor,\n            parentComponent,\n            null, // fallback tree will not have suspense context\n            namespace,\n            slotScopeIds,\n            optimized,\n          )\n          setActiveBranch(suspense, newFallback)\n        }\n      } else if (activeBranch && isSameVNodeType(activeBranch, newBranch)) {\n        // toggled \"back\" to current active branch\n        patch(\n          activeBranch,\n          newBranch,\n          container,\n          anchor,\n          parentComponent,\n          suspense,\n          namespace,\n          slotScopeIds,\n          optimized,\n        )\n        // force resolve\n        suspense.resolve(true)\n      } else {\n        // switched to a 3rd branch\n        patch(\n          null,\n          newBranch,\n          suspense.hiddenContainer,\n          null,\n          parentComponent,\n          suspense,\n          namespace,\n          slotScopeIds,\n          optimized,\n        )\n        if (suspense.deps <= 0) {\n          suspense.resolve()\n        }\n      }\n    }\n  } else {\n    if (activeBranch && isSameVNodeType(activeBranch, newBranch)) {\n      // root did not change, just normal patch\n      patch(\n        activeBranch,\n        newBranch,\n        container,\n        anchor,\n        parentComponent,\n        suspense,\n        namespace,\n        slotScopeIds,\n        optimized,\n      )\n      setActiveBranch(suspense, newBranch)\n    } else {\n      // root node toggled\n      // invoke @pending event\n      triggerEvent(n2, 'onPending')\n      // mount pending branch in off-dom container\n      suspense.pendingBranch = newBranch\n      if (newBranch.shapeFlag & ShapeFlags.COMPONENT_KEPT_ALIVE) {\n        suspense.pendingId = newBranch.component!.suspenseId!\n      } else {\n        suspense.pendingId = suspenseId++\n      }\n      patch(\n        null,\n        newBranch,\n        suspense.hiddenContainer,\n        null,\n        parentComponent,\n        suspense,\n        namespace,\n        slotScopeIds,\n        optimized,\n      )\n      if (suspense.deps <= 0) {\n        // incoming branch has no async deps, resolve now.\n        suspense.resolve()\n      } else {\n        const { timeout, pendingId } = suspense\n        if (timeout > 0) {\n          setTimeout(() => {\n            if (suspense.pendingId === pendingId) {\n              suspense.fallback(newFallback)\n            }\n          }, timeout)\n        } else if (timeout === 0) {\n          suspense.fallback(newFallback)\n        }\n      }\n    }\n  }\n}\n\nexport interface SuspenseBoundary {\n  vnode: VNode<RendererNode, RendererElement, SuspenseProps>\n  parent: SuspenseBoundary | null\n  parentComponent: ComponentInternalInstance | null\n  namespace: ElementNamespace\n  container: RendererElement\n  hiddenContainer: RendererElement\n  activeBranch: VNode | null\n  pendingBranch: VNode | null\n  deps: number\n  pendingId: number\n  timeout: number\n  isInFallback: boolean\n  isHydrating: boolean\n  isUnmounted: boolean\n  effects: Function[]\n  resolve(force?: boolean, sync?: boolean): void\n  fallback(fallbackVNode: VNode): void\n  move(\n    container: RendererElement,\n    anchor: RendererNode | null,\n    type: MoveType,\n  ): void\n  next(): RendererNode | null\n  registerDep(\n    instance: ComponentInternalInstance,\n    setupRenderEffect: SetupRenderEffectFn,\n    optimized: boolean,\n  ): void\n  unmount(parentSuspense: SuspenseBoundary | null, doRemove?: boolean): void\n}\n\nlet hasWarned = false\n\nfunction createSuspenseBoundary(\n  vnode: VNode,\n  parentSuspense: SuspenseBoundary | null,\n  parentComponent: ComponentInternalInstance | null,\n  container: RendererElement,\n  hiddenContainer: RendererElement,\n  anchor: RendererNode | null,\n  namespace: ElementNamespace,\n  slotScopeIds: string[] | null,\n  optimized: boolean,\n  rendererInternals: RendererInternals,\n  isHydrating = false,\n): SuspenseBoundary {\n  /* v8 ignore start */\n  if (__DEV__ && !__TEST__ && !hasWarned) {\n    hasWarned = true\n    // @ts-expect-error `console.info` cannot be null error\n    // eslint-disable-next-line no-console\n    console[console.info ? 'info' : 'log'](\n      `<Suspense> is an experimental feature and its API will likely change.`,\n    )\n  }\n  /* v8 ignore stop */\n\n  const {\n    p: patch,\n    m: move,\n    um: unmount,\n    n: next,\n    o: { parentNode, remove },\n  } = rendererInternals\n\n  // if set `suspensible: true`, set the current suspense as a dep of parent suspense\n  let parentSuspenseId: number | undefined\n  const isSuspensible = isVNodeSuspensible(vnode)\n  if (isSuspensible) {\n    if (parentSuspense && parentSuspense.pendingBranch) {\n      parentSuspenseId = parentSuspense.pendingId\n      parentSuspense.deps++\n    }\n  }\n\n  const timeout = vnode.props ? toNumber(vnode.props.timeout) : undefined\n  if (__DEV__) {\n    assertNumber(timeout, `Suspense timeout`)\n  }\n\n  const initialAnchor = anchor\n  const suspense: SuspenseBoundary = {\n    vnode,\n    parent: parentSuspense,\n    parentComponent,\n    namespace,\n    container,\n    hiddenContainer,\n    deps: 0,\n    pendingId: suspenseId++,\n    timeout: typeof timeout === 'number' ? timeout : -1,\n    activeBranch: null,\n    pendingBranch: null,\n    isInFallback: !isHydrating,\n    isHydrating,\n    isUnmounted: false,\n    effects: [],\n\n    resolve(resume = false, sync = false) {\n      if (__DEV__) {\n        if (!resume && !suspense.pendingBranch) {\n          throw new Error(\n            `suspense.resolve() is called without a pending branch.`,\n          )\n        }\n        if (suspense.isUnmounted) {\n          throw new Error(\n            `suspense.resolve() is called on an already unmounted suspense boundary.`,\n          )\n        }\n      }\n      const {\n        vnode,\n        activeBranch,\n        pendingBranch,\n        pendingId,\n        effects,\n        parentComponent,\n        container,\n        isInFallback,\n      } = suspense\n\n      // if there's a transition happening we need to wait it to finish.\n      let delayEnter: boolean | null = false\n      if (suspense.isHydrating) {\n        suspense.isHydrating = false\n      } else if (!resume) {\n        delayEnter =\n          activeBranch &&\n          pendingBranch!.transition &&\n          pendingBranch!.transition.mode === 'out-in'\n        if (delayEnter) {\n          activeBranch!.transition!.afterLeave = () => {\n            if (pendingId === suspense.pendingId) {\n              move(\n                pendingBranch!,\n                container,\n                anchor === initialAnchor ? next(activeBranch!) : anchor,\n                MoveType.ENTER,\n              )\n              queuePostFlushCb(effects)\n              // clear el reference from fallback vnode to allow GC after transition\n              if (isInFallback && vnode.ssFallback) {\n                vnode.ssFallback.el = null\n              }\n            }\n          }\n        }\n        // unmount current active tree\n        if (activeBranch) {\n          // if the fallback tree was mounted, it may have been moved\n          // as part of a parent suspense. get the latest anchor for insertion\n          // #8105 if `delayEnter` is true, it means that the mounting of\n          // `activeBranch` will be delayed. if the branch switches before\n          // transition completes, both `activeBranch` and `pendingBranch` may\n          // coexist in the `hiddenContainer`. This could result in\n          // `next(activeBranch!)` obtaining an incorrect anchor\n          // (got `pendingBranch.el`).\n          // Therefore, after the mounting of activeBranch is completed,\n          // it is necessary to get the latest anchor.\n          if (parentNode(activeBranch.el!) === container) {\n            anchor = next(activeBranch)\n          }\n          unmount(activeBranch, parentComponent, suspense, true)\n          // clear el reference from fallback vnode to allow GC\n          if (!delayEnter && isInFallback && vnode.ssFallback) {\n            queuePostRenderEffect(() => (vnode.ssFallback!.el = null), suspense)\n          }\n        }\n        if (!delayEnter) {\n          // move content from off-dom container to actual container\n          move(pendingBranch!, container, anchor, MoveType.ENTER)\n        }\n      }\n\n      setActiveBranch(suspense, pendingBranch!)\n      suspense.pendingBranch = null\n      suspense.isInFallback = false\n\n      // flush buffered effects\n      // check if there is a pending parent suspense\n      let parent = suspense.parent\n      let hasUnresolvedAncestor = false\n      while (parent) {\n        if (parent.pendingBranch) {\n          // found a pending parent suspense, merge buffered post jobs\n          // into that parent\n          parent.effects.push(...effects)\n          hasUnresolvedAncestor = true\n          break\n        }\n        parent = parent.parent\n      }\n      // no pending parent suspense nor transition, flush all jobs\n      if (!hasUnresolvedAncestor && !delayEnter) {\n        queuePostFlushCb(effects)\n      }\n      suspense.effects = []\n\n      // resolve parent suspense if all async deps are resolved\n      if (isSuspensible) {\n        if (\n          parentSuspense &&\n          parentSuspense.pendingBranch &&\n          parentSuspenseId === parentSuspense.pendingId\n        ) {\n          parentSuspense.deps--\n          if (parentSuspense.deps === 0 && !sync) {\n            parentSuspense.resolve()\n          }\n        }\n      }\n\n      // invoke @resolve event\n      triggerEvent(vnode, 'onResolve')\n    },\n\n    fallback(fallbackVNode) {\n      if (!suspense.pendingBranch) {\n        return\n      }\n\n      const { vnode, activeBranch, parentComponent, container, namespace } =\n        suspense\n\n      // invoke @fallback event\n      triggerEvent(vnode, 'onFallback')\n\n      const anchor = next(activeBranch!)\n      const mountFallback = () => {\n        if (!suspense.isInFallback) {\n          return\n        }\n        // mount the fallback tree\n        patch(\n          null,\n          fallbackVNode,\n          container,\n          anchor,\n          parentComponent,\n          null, // fallback tree will not have suspense context\n          namespace,\n          slotScopeIds,\n          optimized,\n        )\n        setActiveBranch(suspense, fallbackVNode)\n      }\n\n      const delayEnter =\n        fallbackVNode.transition && fallbackVNode.transition.mode === 'out-in'\n      if (delayEnter) {\n        activeBranch!.transition!.afterLeave = mountFallback\n      }\n      suspense.isInFallback = true\n\n      // unmount current active branch\n      unmount(\n        activeBranch!,\n        parentComponent,\n        null, // no suspense so unmount hooks fire now\n        true, // shouldRemove\n      )\n\n      if (!delayEnter) {\n        mountFallback()\n      }\n    },\n\n    move(container, anchor, type) {\n      suspense.activeBranch &&\n        move(suspense.activeBranch, container, anchor, type)\n      suspense.container = container\n    },\n\n    next() {\n      return suspense.activeBranch && next(suspense.activeBranch)\n    },\n\n    registerDep(instance, setupRenderEffect, optimized) {\n      const isInPendingSuspense = !!suspense.pendingBranch\n      if (isInPendingSuspense) {\n        suspense.deps++\n      }\n      const hydratedEl = instance.vnode.el\n      instance\n        .asyncDep!.catch(err => {\n          handleError(err, instance, ErrorCodes.SETUP_FUNCTION)\n        })\n        .then(asyncSetupResult => {\n          // retry when the setup() promise resolves.\n          // component may have been unmounted before resolve.\n          if (\n            instance.isUnmounted ||\n            suspense.isUnmounted ||\n            suspense.pendingId !== instance.suspenseId\n          ) {\n            return\n          }\n          // retry from this component\n          instance.asyncResolved = true\n          const { vnode } = instance\n          if (__DEV__) {\n            pushWarningContext(vnode)\n          }\n          handleSetupResult(instance, asyncSetupResult, false)\n          if (hydratedEl) {\n            // vnode may have been replaced if an update happened before the\n            // async dep is resolved.\n            vnode.el = hydratedEl\n          }\n          const placeholder = !hydratedEl && instance.subTree.el\n          setupRenderEffect(\n            instance,\n            vnode,\n            // component may have been moved before resolve.\n            // if this is not a hydration, instance.subTree will be the comment\n            // placeholder.\n            parentNode(hydratedEl || instance.subTree.el!)!,\n            // anchor will not be used if this is hydration, so only need to\n            // consider the comment placeholder case.\n            hydratedEl ? null : next(instance.subTree),\n            suspense,\n            namespace,\n            optimized,\n          )\n          if (placeholder) {\n            // clean up placeholder reference\n            vnode.placeholder = null\n            remove(placeholder)\n          }\n          updateHOCHostEl(instance, vnode.el)\n          if (__DEV__) {\n            popWarningContext()\n          }\n          // only decrease deps count if suspense is not already resolved\n          if (isInPendingSuspense && --suspense.deps === 0) {\n            suspense.resolve()\n          }\n        })\n    },\n\n    unmount(parentSuspense, doRemove) {\n      suspense.isUnmounted = true\n      if (suspense.activeBranch) {\n        unmount(\n          suspense.activeBranch,\n          parentComponent,\n          parentSuspense,\n          doRemove,\n        )\n      }\n      if (suspense.pendingBranch) {\n        unmount(\n          suspense.pendingBranch,\n          parentComponent,\n          parentSuspense,\n          doRemove,\n        )\n      }\n    },\n  }\n\n  return suspense\n}\n\nfunction hydrateSuspense(\n  node: Node,\n  vnode: VNode,\n  parentComponent: ComponentInternalInstance | null,\n  parentSuspense: SuspenseBoundary | null,\n  namespace: ElementNamespace,\n  slotScopeIds: string[] | null,\n  optimized: boolean,\n  rendererInternals: RendererInternals,\n  hydrateNode: (\n    node: Node,\n    vnode: VNode,\n    parentComponent: ComponentInternalInstance | null,\n    parentSuspense: SuspenseBoundary | null,\n    slotScopeIds: string[] | null,\n    optimized: boolean,\n  ) => Node | null,\n): Node | null {\n  const suspense = (vnode.suspense = createSuspenseBoundary(\n    vnode,\n    parentSuspense,\n    parentComponent,\n    node.parentNode!,\n    // eslint-disable-next-line no-restricted-globals\n    document.createElement('div'),\n    null,\n    namespace,\n    slotScopeIds,\n    optimized,\n    rendererInternals,\n    true /* hydrating */,\n  ))\n  // there are two possible scenarios for server-rendered suspense:\n  // - success: ssr content should be fully resolved\n  // - failure: ssr content should be the fallback branch.\n  // however, on the client we don't really know if it has failed or not\n  // attempt to hydrate the DOM assuming it has succeeded, but we still\n  // need to construct a suspense boundary first\n  const result = hydrateNode(\n    node,\n    (suspense.pendingBranch = vnode.ssContent!),\n    parentComponent,\n    suspense,\n    slotScopeIds,\n    optimized,\n  )\n  if (suspense.deps === 0) {\n    suspense.resolve(false, true)\n  }\n  return result\n}\n\nfunction normalizeSuspenseChildren(vnode: VNode): void {\n  const { shapeFlag, children } = vnode\n  const isSlotChildren = shapeFlag & ShapeFlags.SLOTS_CHILDREN\n  vnode.ssContent = normalizeSuspenseSlot(\n    isSlotChildren ? (children as Slots).default : children,\n  )\n  vnode.ssFallback = isSlotChildren\n    ? normalizeSuspenseSlot((children as Slots).fallback)\n    : createVNode(Comment)\n}\n\nfunction normalizeSuspenseSlot(s: any) {\n  let block: VNode[] | null | undefined\n  if (isFunction(s)) {\n    const trackBlock = isBlockTreeEnabled && s._c\n    if (trackBlock) {\n      // disableTracking: false\n      // allow block tracking for compiled slots\n      // (see ./componentRenderContext.ts)\n      s._d = false\n      openBlock()\n    }\n    s = s()\n    if (trackBlock) {\n      s._d = true\n      block = currentBlock\n      closeBlock()\n    }\n  }\n  if (isArray(s)) {\n    const singleChild = filterSingleRoot(s)\n    if (\n      __DEV__ &&\n      !singleChild &&\n      s.filter(child => child !== NULL_DYNAMIC_COMPONENT).length > 0\n    ) {\n      warn(`<Suspense> slots expect a single root node.`)\n    }\n    s = singleChild\n  }\n  s = normalizeVNode(s)\n  if (block && !s.dynamicChildren) {\n    s.dynamicChildren = block.filter(c => c !== s)\n  }\n  return s\n}\n\nexport function queueEffectWithSuspense(\n  fn: Function | Function[],\n  suspense: SuspenseBoundary | null,\n): void {\n  if (suspense && suspense.pendingBranch) {\n    if (isArray(fn)) {\n      suspense.effects.push(...fn)\n    } else {\n      suspense.effects.push(fn)\n    }\n  } else {\n    queuePostFlushCb(fn)\n  }\n}\n\nfunction setActiveBranch(suspense: SuspenseBoundary, branch: VNode) {\n  suspense.activeBranch = branch\n  const { vnode, parentComponent } = suspense\n  let el = branch.el\n  // if branch has no el after patch, it's a HOC wrapping async components\n  // drill and locate the placeholder comment node\n  while (!el && branch.component) {\n    branch = branch.component.subTree\n    el = branch.el\n  }\n  vnode.el = el\n  // in case suspense is the root node of a component,\n  // recursively update the HOC el\n  if (parentComponent && parentComponent.subTree === vnode) {\n    parentComponent.vnode.el = el\n    updateHOCHostEl(parentComponent, el)\n  }\n}\n\nfunction isVNodeSuspensible(vnode: VNode) {\n  const suspensible = vnode.props && vnode.props.suspensible\n  return suspensible != null && suspensible !== false\n}\n"
  },
  {
    "path": "packages/runtime-core/src/components/Teleport.ts",
    "content": "import type { ComponentInternalInstance } from '../component'\nimport type { SuspenseBoundary } from './Suspense'\nimport {\n  type ElementNamespace,\n  MoveType,\n  type RendererElement,\n  type RendererInternals,\n  type RendererNode,\n  type RendererOptions,\n  queuePostRenderEffect,\n  traverseStaticChildren,\n} from '../renderer'\nimport type { VNode, VNodeArrayChildren, VNodeProps } from '../vnode'\nimport { ShapeFlags, isString } from '@vue/shared'\nimport { warn } from '../warning'\nimport { isHmrUpdating } from '../hmr'\n\nexport type TeleportVNode = VNode<RendererNode, RendererElement, TeleportProps>\n\nexport interface TeleportProps {\n  to: string | RendererElement | null | undefined\n  disabled?: boolean\n  defer?: boolean\n}\n\nexport const TeleportEndKey: unique symbol = Symbol('_vte')\n\nexport const isTeleport = (type: any): boolean => type.__isTeleport\n\nconst isTeleportDisabled = (props: VNode['props']): boolean =>\n  props && (props.disabled || props.disabled === '')\n\nconst isTeleportDeferred = (props: VNode['props']): boolean =>\n  props && (props.defer || props.defer === '')\n\nconst isTargetSVG = (target: RendererElement): boolean =>\n  typeof SVGElement !== 'undefined' && target instanceof SVGElement\n\nconst isTargetMathML = (target: RendererElement): boolean =>\n  typeof MathMLElement === 'function' && target instanceof MathMLElement\n\nconst resolveTarget = <T = RendererElement>(\n  props: TeleportProps | null,\n  select: RendererOptions['querySelector'],\n): T | null => {\n  const targetSelector = props && props.to\n  if (isString(targetSelector)) {\n    if (!select) {\n      __DEV__ &&\n        warn(\n          `Current renderer does not support string target for Teleports. ` +\n            `(missing querySelector renderer option)`,\n        )\n      return null\n    } else {\n      const target = select(targetSelector)\n      if (__DEV__ && !target && !isTeleportDisabled(props)) {\n        warn(\n          `Failed to locate Teleport target with selector \"${targetSelector}\". ` +\n            `Note the target element must exist before the component is mounted - ` +\n            `i.e. the target cannot be rendered by the component itself, and ` +\n            `ideally should be outside of the entire Vue component tree.`,\n        )\n      }\n      return target as T\n    }\n  } else {\n    if (__DEV__ && !targetSelector && !isTeleportDisabled(props)) {\n      warn(`Invalid Teleport target: ${targetSelector}`)\n    }\n    return targetSelector as T\n  }\n}\n\nexport const TeleportImpl = {\n  name: 'Teleport',\n  __isTeleport: true,\n  process(\n    n1: TeleportVNode | null,\n    n2: TeleportVNode,\n    container: RendererElement,\n    anchor: RendererNode | null,\n    parentComponent: ComponentInternalInstance | null,\n    parentSuspense: SuspenseBoundary | null,\n    namespace: ElementNamespace,\n    slotScopeIds: string[] | null,\n    optimized: boolean,\n    internals: RendererInternals,\n  ): void {\n    const {\n      mc: mountChildren,\n      pc: patchChildren,\n      pbc: patchBlockChildren,\n      o: { insert, querySelector, createText, createComment },\n    } = internals\n\n    const disabled = isTeleportDisabled(n2.props)\n    let { shapeFlag, children, dynamicChildren } = n2\n\n    // #3302\n    // HMR updated, force full diff\n    if (__DEV__ && isHmrUpdating) {\n      optimized = false\n      dynamicChildren = null\n    }\n\n    if (n1 == null) {\n      // insert anchors in the main view\n      const placeholder = (n2.el = __DEV__\n        ? createComment('teleport start')\n        : createText(''))\n      const mainAnchor = (n2.anchor = __DEV__\n        ? createComment('teleport end')\n        : createText(''))\n      insert(placeholder, container, anchor)\n      insert(mainAnchor, container, anchor)\n\n      const mount = (container: RendererElement, anchor: RendererNode) => {\n        // Teleport *always* has Array children. This is enforced in both the\n        // compiler and vnode children normalization.\n        if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) {\n          mountChildren(\n            children as VNodeArrayChildren,\n            container,\n            anchor,\n            parentComponent,\n            parentSuspense,\n            namespace,\n            slotScopeIds,\n            optimized,\n          )\n        }\n      }\n\n      const mountToTarget = () => {\n        const target = (n2.target = resolveTarget(n2.props, querySelector))\n        const targetAnchor = prepareAnchor(target, n2, createText, insert)\n        if (target) {\n          // #2652 we could be teleporting from a non-SVG tree into an SVG tree\n          if (namespace !== 'svg' && isTargetSVG(target)) {\n            namespace = 'svg'\n          } else if (namespace !== 'mathml' && isTargetMathML(target)) {\n            namespace = 'mathml'\n          }\n\n          // track CE teleport targets\n          if (parentComponent && parentComponent.isCE) {\n            ;(\n              parentComponent.ce!._teleportTargets ||\n              (parentComponent.ce!._teleportTargets = new Set())\n            ).add(target)\n          }\n\n          if (!disabled) {\n            mount(target, targetAnchor)\n            updateCssVars(n2, false)\n          }\n        } else if (__DEV__ && !disabled) {\n          warn(\n            'Invalid Teleport target on mount:',\n            target,\n            `(${typeof target})`,\n          )\n        }\n      }\n\n      if (disabled) {\n        mount(container, mainAnchor)\n        updateCssVars(n2, true)\n      }\n\n      if (isTeleportDeferred(n2.props)) {\n        n2.el!.__isMounted = false\n        queuePostRenderEffect(() => {\n          mountToTarget()\n          delete n2.el!.__isMounted\n        }, parentSuspense)\n      } else {\n        mountToTarget()\n      }\n    } else {\n      if (isTeleportDeferred(n2.props) && n1.el!.__isMounted === false) {\n        queuePostRenderEffect(() => {\n          TeleportImpl.process(\n            n1,\n            n2,\n            container,\n            anchor,\n            parentComponent,\n            parentSuspense,\n            namespace,\n            slotScopeIds,\n            optimized,\n            internals,\n          )\n        }, parentSuspense)\n        return\n      }\n      // update content\n      n2.el = n1.el\n      n2.targetStart = n1.targetStart\n      const mainAnchor = (n2.anchor = n1.anchor)!\n      const target = (n2.target = n1.target)!\n      const targetAnchor = (n2.targetAnchor = n1.targetAnchor)!\n      const wasDisabled = isTeleportDisabled(n1.props)\n      const currentContainer = wasDisabled ? container : target\n      const currentAnchor = wasDisabled ? mainAnchor : targetAnchor\n\n      if (namespace === 'svg' || isTargetSVG(target)) {\n        namespace = 'svg'\n      } else if (namespace === 'mathml' || isTargetMathML(target)) {\n        namespace = 'mathml'\n      }\n\n      if (dynamicChildren) {\n        // fast path when the teleport happens to be a block root\n        patchBlockChildren(\n          n1.dynamicChildren!,\n          dynamicChildren,\n          currentContainer,\n          parentComponent,\n          parentSuspense,\n          namespace,\n          slotScopeIds,\n        )\n        // even in block tree mode we need to make sure all root-level nodes\n        // in the teleport inherit previous DOM references so that they can\n        // be moved in future patches.\n        // in dev mode, deep traversal is necessary for HMR\n        traverseStaticChildren(n1, n2, !__DEV__)\n      } else if (!optimized) {\n        patchChildren(\n          n1,\n          n2,\n          currentContainer,\n          currentAnchor,\n          parentComponent,\n          parentSuspense,\n          namespace,\n          slotScopeIds,\n          false,\n        )\n      }\n\n      if (disabled) {\n        if (!wasDisabled) {\n          // enabled -> disabled\n          // move into main container\n          moveTeleport(\n            n2,\n            container,\n            mainAnchor,\n            internals,\n            TeleportMoveTypes.TOGGLE,\n          )\n        } else {\n          // #7835\n          // When `teleport` is disabled, `to` may change, making it always old,\n          // to ensure the correct `to` when enabled\n          if (n2.props && n1.props && n2.props.to !== n1.props.to) {\n            n2.props.to = n1.props.to\n          }\n        }\n      } else {\n        // target changed\n        if ((n2.props && n2.props.to) !== (n1.props && n1.props.to)) {\n          const nextTarget = (n2.target = resolveTarget(\n            n2.props,\n            querySelector,\n          ))\n          if (nextTarget) {\n            moveTeleport(\n              n2,\n              nextTarget,\n              null,\n              internals,\n              TeleportMoveTypes.TARGET_CHANGE,\n            )\n          } else if (__DEV__) {\n            warn(\n              'Invalid Teleport target on update:',\n              target,\n              `(${typeof target})`,\n            )\n          }\n        } else if (wasDisabled) {\n          // disabled -> enabled\n          // move into teleport target\n          moveTeleport(\n            n2,\n            target,\n            targetAnchor,\n            internals,\n            TeleportMoveTypes.TOGGLE,\n          )\n        }\n      }\n      updateCssVars(n2, disabled)\n    }\n  },\n\n  remove(\n    vnode: VNode,\n    parentComponent: ComponentInternalInstance | null,\n    parentSuspense: SuspenseBoundary | null,\n    { um: unmount, o: { remove: hostRemove } }: RendererInternals,\n    doRemove: boolean,\n  ): void {\n    const {\n      shapeFlag,\n      children,\n      anchor,\n      targetStart,\n      targetAnchor,\n      target,\n      props,\n    } = vnode\n\n    if (target) {\n      hostRemove(targetStart!)\n      hostRemove(targetAnchor!)\n    }\n\n    // an unmounted teleport should always unmount its children whether it's disabled or not\n    doRemove && hostRemove(anchor!)\n    if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) {\n      const shouldRemove = doRemove || !isTeleportDisabled(props)\n      for (let i = 0; i < (children as VNode[]).length; i++) {\n        const child = (children as VNode[])[i]\n        unmount(\n          child,\n          parentComponent,\n          parentSuspense,\n          shouldRemove,\n          !!child.dynamicChildren,\n        )\n      }\n    }\n  },\n\n  move: moveTeleport as typeof moveTeleport,\n  hydrate: hydrateTeleport as typeof hydrateTeleport,\n}\n\nexport enum TeleportMoveTypes {\n  TARGET_CHANGE,\n  TOGGLE, // enable / disable\n  REORDER, // moved in the main view\n}\n\nfunction moveTeleport(\n  vnode: VNode,\n  container: RendererElement,\n  parentAnchor: RendererNode | null,\n  { o: { insert }, m: move }: RendererInternals,\n  moveType: TeleportMoveTypes = TeleportMoveTypes.REORDER,\n): void {\n  // move target anchor if this is a target change.\n  if (moveType === TeleportMoveTypes.TARGET_CHANGE) {\n    insert(vnode.targetAnchor!, container, parentAnchor)\n  }\n  const { el, anchor, shapeFlag, children, props } = vnode\n  const isReorder = moveType === TeleportMoveTypes.REORDER\n  // move main view anchor if this is a re-order.\n  if (isReorder) {\n    insert(el!, container, parentAnchor)\n  }\n  // if this is a re-order and teleport is enabled (content is in target)\n  // do not move children. So the opposite is: only move children if this\n  // is not a reorder, or the teleport is disabled\n  if (!isReorder || isTeleportDisabled(props)) {\n    // Teleport has either Array children or no children.\n    if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) {\n      for (let i = 0; i < (children as VNode[]).length; i++) {\n        move(\n          (children as VNode[])[i],\n          container,\n          parentAnchor,\n          MoveType.REORDER,\n        )\n      }\n    }\n  }\n  // move main view anchor if this is a re-order.\n  if (isReorder) {\n    insert(anchor!, container, parentAnchor)\n  }\n}\n\ninterface TeleportTargetElement extends Element {\n  // last teleport target\n  _lpa?: Node | null\n}\n\nfunction hydrateTeleport(\n  node: Node,\n  vnode: TeleportVNode,\n  parentComponent: ComponentInternalInstance | null,\n  parentSuspense: SuspenseBoundary | null,\n  slotScopeIds: string[] | null,\n  optimized: boolean,\n  {\n    o: { nextSibling, parentNode, querySelector, insert, createText },\n  }: RendererInternals<Node, Element>,\n  hydrateChildren: (\n    node: Node | null,\n    vnode: VNode,\n    container: Element,\n    parentComponent: ComponentInternalInstance | null,\n    parentSuspense: SuspenseBoundary | null,\n    slotScopeIds: string[] | null,\n    optimized: boolean,\n  ) => Node | null,\n): Node | null {\n  // lookahead until we find the target anchor\n  // we cannot rely on return value of hydrateChildren() because there\n  // could be nested teleports\n  function hydrateAnchor(\n    target: TeleportTargetElement,\n    targetNode: Node | null,\n  ) {\n    let targetAnchor = targetNode\n    while (targetAnchor) {\n      if (targetAnchor && targetAnchor.nodeType === 8) {\n        if ((targetAnchor as Comment).data === 'teleport start anchor') {\n          vnode.targetStart = targetAnchor\n        } else if ((targetAnchor as Comment).data === 'teleport anchor') {\n          vnode.targetAnchor = targetAnchor\n          target._lpa =\n            vnode.targetAnchor && nextSibling(vnode.targetAnchor as Node)\n          break\n        }\n      }\n      targetAnchor = nextSibling(targetAnchor)\n    }\n  }\n\n  function hydrateDisabledTeleport(node: Node, vnode: VNode) {\n    vnode.anchor = hydrateChildren(\n      nextSibling(node),\n      vnode,\n      parentNode(node)!,\n      parentComponent,\n      parentSuspense,\n      slotScopeIds,\n      optimized,\n    )\n  }\n\n  const target = (vnode.target = resolveTarget<Element>(\n    vnode.props,\n    querySelector,\n  ))\n  const disabled = isTeleportDisabled(vnode.props)\n  if (target) {\n    // if multiple teleports rendered to the same target element, we need to\n    // pick up from where the last teleport finished instead of the first node\n    const targetNode =\n      (target as TeleportTargetElement)._lpa || target.firstChild\n    if (vnode.shapeFlag & ShapeFlags.ARRAY_CHILDREN) {\n      if (disabled) {\n        hydrateDisabledTeleport(node, vnode)\n        hydrateAnchor(target as TeleportTargetElement, targetNode)\n        if (!vnode.targetAnchor) {\n          prepareAnchor(\n            target,\n            vnode,\n            createText,\n            insert,\n            // if target is the same as the main view, insert anchors before current node\n            // to avoid hydrating mismatch\n            parentNode(node)! === target ? node : null,\n          )\n        }\n      } else {\n        vnode.anchor = nextSibling(node)\n        hydrateAnchor(target as TeleportTargetElement, targetNode)\n        // #11400 if the HTML corresponding to Teleport is not embedded in the\n        // correct position on the final page during SSR. the targetAnchor will\n        // always be null, we need to manually add targetAnchor to ensure\n        // Teleport it can properly unmount or move\n        if (!vnode.targetAnchor) {\n          prepareAnchor(target, vnode, createText, insert)\n        }\n\n        hydrateChildren(\n          targetNode && nextSibling(targetNode),\n          vnode,\n          target,\n          parentComponent,\n          parentSuspense,\n          slotScopeIds,\n          optimized,\n        )\n      }\n    }\n    updateCssVars(vnode, disabled)\n  } else if (disabled) {\n    if (vnode.shapeFlag & ShapeFlags.ARRAY_CHILDREN) {\n      hydrateDisabledTeleport(node, vnode)\n      vnode.targetStart = node\n      vnode.targetAnchor = nextSibling(node)\n    }\n  }\n  return vnode.anchor && nextSibling(vnode.anchor as Node)\n}\n\n// Force-casted public typing for h and TSX props inference\nexport const Teleport = TeleportImpl as unknown as {\n  __isTeleport: true\n  new (): {\n    $props: VNodeProps & TeleportProps\n    $slots: {\n      default(): VNode[]\n    }\n  }\n}\n\nfunction updateCssVars(vnode: VNode, isDisabled: boolean) {\n  // presence of .ut method indicates owner component uses css vars.\n  // code path here can assume browser environment.\n  const ctx = vnode.ctx\n  if (ctx && ctx.ut) {\n    let node, anchor\n    if (isDisabled) {\n      node = vnode.el\n      anchor = vnode.anchor\n    } else {\n      node = vnode.targetStart\n      anchor = vnode.targetAnchor\n    }\n    while (node && node !== anchor) {\n      if (node.nodeType === 1) node.setAttribute('data-v-owner', ctx.uid)\n      node = node.nextSibling\n    }\n    ctx.ut()\n  }\n}\n\nfunction prepareAnchor(\n  target: RendererElement | null,\n  vnode: TeleportVNode,\n  createText: RendererOptions['createText'],\n  insert: RendererOptions['insert'],\n  anchor: RendererNode | null = null,\n) {\n  const targetStart = (vnode.targetStart = createText(''))\n  const targetAnchor = (vnode.targetAnchor = createText(''))\n\n  // attach a special property, so we can skip teleported content in\n  // renderer's nextSibling search\n  targetStart[TeleportEndKey] = targetAnchor\n\n  if (target) {\n    insert(targetStart, target, anchor)\n    insert(targetAnchor, target, anchor)\n  }\n\n  return targetAnchor\n}\n"
  },
  {
    "path": "packages/runtime-core/src/customFormatter.ts",
    "content": "import {\n  type Ref,\n  isReactive,\n  isReadonly,\n  isRef,\n  isShallow,\n  pauseTracking,\n  resetTracking,\n  toRaw,\n} from '@vue/reactivity'\nimport { EMPTY_OBJ, extend, isArray, isFunction, isObject } from '@vue/shared'\nimport type { ComponentInternalInstance, ComponentOptions } from './component'\nimport type { ComponentPublicInstance } from './componentPublicInstance'\n\nexport function initCustomFormatter(): void {\n  /* eslint-disable no-restricted-globals */\n  if (!__DEV__ || typeof window === 'undefined') {\n    return\n  }\n\n  const vueStyle = { style: 'color:#3ba776' }\n  const numberStyle = { style: 'color:#1677ff' }\n  const stringStyle = { style: 'color:#f5222d' }\n  const keywordStyle = { style: 'color:#eb2f96' }\n\n  // custom formatter for Chrome\n  // https://www.mattzeunert.com/2016/02/19/custom-chrome-devtools-object-formatters.html\n  const formatter = {\n    __vue_custom_formatter: true,\n    header(obj: unknown) {\n      // TODO also format ComponentPublicInstance & ctx.slots/attrs in setup\n      if (!isObject(obj)) {\n        return null\n      }\n\n      if (obj.__isVue) {\n        return ['div', vueStyle, `VueInstance`]\n      } else if (isRef(obj)) {\n        // avoid tracking during debugger accessing\n        pauseTracking()\n        const value = obj.value\n        resetTracking()\n        return [\n          'div',\n          {},\n          ['span', vueStyle, genRefFlag(obj)],\n          '<',\n          formatValue(value),\n          `>`,\n        ]\n      } else if (isReactive(obj)) {\n        return [\n          'div',\n          {},\n          ['span', vueStyle, isShallow(obj) ? 'ShallowReactive' : 'Reactive'],\n          '<',\n          formatValue(obj),\n          `>${isReadonly(obj) ? ` (readonly)` : ``}`,\n        ]\n      } else if (isReadonly(obj)) {\n        return [\n          'div',\n          {},\n          ['span', vueStyle, isShallow(obj) ? 'ShallowReadonly' : 'Readonly'],\n          '<',\n          formatValue(obj),\n          '>',\n        ]\n      }\n      return null\n    },\n    hasBody(obj: unknown) {\n      return obj && (obj as any).__isVue\n    },\n    body(obj: unknown) {\n      if (obj && (obj as any).__isVue) {\n        return [\n          'div',\n          {},\n          ...formatInstance((obj as ComponentPublicInstance).$),\n        ]\n      }\n    },\n  }\n\n  function formatInstance(instance: ComponentInternalInstance) {\n    const blocks = []\n    if (instance.type.props && instance.props) {\n      blocks.push(createInstanceBlock('props', toRaw(instance.props)))\n    }\n    if (instance.setupState !== EMPTY_OBJ) {\n      blocks.push(createInstanceBlock('setup', instance.setupState))\n    }\n    if (instance.data !== EMPTY_OBJ) {\n      blocks.push(createInstanceBlock('data', toRaw(instance.data)))\n    }\n    const computed = extractKeys(instance, 'computed')\n    if (computed) {\n      blocks.push(createInstanceBlock('computed', computed))\n    }\n    const injected = extractKeys(instance, 'inject')\n    if (injected) {\n      blocks.push(createInstanceBlock('injected', injected))\n    }\n\n    blocks.push([\n      'div',\n      {},\n      [\n        'span',\n        {\n          style: keywordStyle.style + ';opacity:0.66',\n        },\n        '$ (internal): ',\n      ],\n      ['object', { object: instance }],\n    ])\n    return blocks\n  }\n\n  function createInstanceBlock(type: string, target: any) {\n    target = extend({}, target)\n    if (!Object.keys(target).length) {\n      return ['span', {}]\n    }\n    return [\n      'div',\n      { style: 'line-height:1.25em;margin-bottom:0.6em' },\n      [\n        'div',\n        {\n          style: 'color:#476582',\n        },\n        type,\n      ],\n      [\n        'div',\n        {\n          style: 'padding-left:1.25em',\n        },\n        ...Object.keys(target).map(key => {\n          return [\n            'div',\n            {},\n            ['span', keywordStyle, key + ': '],\n            formatValue(target[key], false),\n          ]\n        }),\n      ],\n    ]\n  }\n\n  function formatValue(v: unknown, asRaw = true) {\n    if (typeof v === 'number') {\n      return ['span', numberStyle, v]\n    } else if (typeof v === 'string') {\n      return ['span', stringStyle, JSON.stringify(v)]\n    } else if (typeof v === 'boolean') {\n      return ['span', keywordStyle, v]\n    } else if (isObject(v)) {\n      return ['object', { object: asRaw ? toRaw(v) : v }]\n    } else {\n      return ['span', stringStyle, String(v)]\n    }\n  }\n\n  function extractKeys(instance: ComponentInternalInstance, type: string) {\n    const Comp = instance.type\n    if (isFunction(Comp)) {\n      return\n    }\n    const extracted: Record<string, any> = {}\n    for (const key in instance.ctx) {\n      if (isKeyOfType(Comp, key, type)) {\n        extracted[key] = instance.ctx[key]\n      }\n    }\n    return extracted\n  }\n\n  function isKeyOfType(Comp: ComponentOptions, key: string, type: string) {\n    const opts = Comp[type]\n    if (\n      (isArray(opts) && opts.includes(key)) ||\n      (isObject(opts) && key in opts)\n    ) {\n      return true\n    }\n    if (Comp.extends && isKeyOfType(Comp.extends, key, type)) {\n      return true\n    }\n    if (Comp.mixins && Comp.mixins.some(m => isKeyOfType(m, key, type))) {\n      return true\n    }\n  }\n\n  function genRefFlag(v: Ref) {\n    if (isShallow(v)) {\n      return `ShallowRef`\n    }\n    if ((v as any).effect) {\n      return `ComputedRef`\n    }\n    return `Ref`\n  }\n\n  if ((window as any).devtoolsFormatters) {\n    ;(window as any).devtoolsFormatters.push(formatter)\n  } else {\n    ;(window as any).devtoolsFormatters = [formatter]\n  }\n}\n"
  },
  {
    "path": "packages/runtime-core/src/devtools.ts",
    "content": "/* eslint-disable no-restricted-globals */\nimport type { App } from './apiCreateApp'\nimport { Comment, Fragment, Static, Text } from './vnode'\nimport type { ComponentInternalInstance } from './component'\n\ninterface AppRecord {\n  id: number\n  app: App\n  version: string\n  types: Record<string, string | Symbol>\n}\n\nenum DevtoolsHooks {\n  APP_INIT = 'app:init',\n  APP_UNMOUNT = 'app:unmount',\n  COMPONENT_UPDATED = 'component:updated',\n  COMPONENT_ADDED = 'component:added',\n  COMPONENT_REMOVED = 'component:removed',\n  COMPONENT_EMIT = 'component:emit',\n  PERFORMANCE_START = 'perf:start',\n  PERFORMANCE_END = 'perf:end',\n}\n\nexport interface DevtoolsHook {\n  enabled?: boolean\n  emit: (event: string, ...payload: any[]) => void\n  on: (event: string, handler: Function) => void\n  once: (event: string, handler: Function) => void\n  off: (event: string, handler: Function) => void\n  appRecords: AppRecord[]\n  /**\n   * Added at https://github.com/vuejs/devtools/commit/f2ad51eea789006ab66942e5a27c0f0986a257f9\n   * Returns whether the arg was buffered or not\n   */\n  cleanupBuffer?: (matchArg: unknown) => boolean\n}\n\nexport let devtools: DevtoolsHook\n\nlet buffer: { event: string; args: any[] }[] = []\n\nlet devtoolsNotInstalled = false\n\nfunction emit(event: string, ...args: any[]) {\n  if (devtools) {\n    devtools.emit(event, ...args)\n  } else if (!devtoolsNotInstalled) {\n    buffer.push({ event, args })\n  }\n}\n\nexport function setDevtoolsHook(hook: DevtoolsHook, target: any): void {\n  devtools = hook\n  if (devtools) {\n    devtools.enabled = true\n    buffer.forEach(({ event, args }) => devtools.emit(event, ...args))\n    buffer = []\n  } else if (\n    // handle late devtools injection - only do this if we are in an actual\n    // browser environment to avoid the timer handle stalling test runner exit\n    // (#4815)\n    typeof window !== 'undefined' &&\n    // some envs mock window but not fully\n    window.HTMLElement &&\n    // also exclude jsdom\n    // eslint-disable-next-line no-restricted-syntax\n    !window.navigator?.userAgent?.includes('jsdom')\n  ) {\n    const replay = (target.__VUE_DEVTOOLS_HOOK_REPLAY__ =\n      target.__VUE_DEVTOOLS_HOOK_REPLAY__ || [])\n    replay.push((newHook: DevtoolsHook) => {\n      setDevtoolsHook(newHook, target)\n    })\n    // clear buffer after 3s - the user probably doesn't have devtools installed\n    // at all, and keeping the buffer will cause memory leaks (#4738)\n    setTimeout(() => {\n      if (!devtools) {\n        target.__VUE_DEVTOOLS_HOOK_REPLAY__ = null\n        devtoolsNotInstalled = true\n        buffer = []\n      }\n    }, 3000)\n  } else {\n    // non-browser env, assume not installed\n    devtoolsNotInstalled = true\n    buffer = []\n  }\n}\n\nexport function devtoolsInitApp(app: App, version: string): void {\n  emit(DevtoolsHooks.APP_INIT, app, version, {\n    Fragment,\n    Text,\n    Comment,\n    Static,\n  })\n}\n\nexport function devtoolsUnmountApp(app: App): void {\n  emit(DevtoolsHooks.APP_UNMOUNT, app)\n}\n\nexport const devtoolsComponentAdded: DevtoolsComponentHook =\n  /*@__PURE__*/ createDevtoolsComponentHook(DevtoolsHooks.COMPONENT_ADDED)\n\nexport const devtoolsComponentUpdated: DevtoolsComponentHook =\n  /*@__PURE__*/ createDevtoolsComponentHook(DevtoolsHooks.COMPONENT_UPDATED)\n\nconst _devtoolsComponentRemoved = /*@__PURE__*/ createDevtoolsComponentHook(\n  DevtoolsHooks.COMPONENT_REMOVED,\n)\n\nexport const devtoolsComponentRemoved = (\n  component: ComponentInternalInstance,\n): void => {\n  if (\n    devtools &&\n    typeof devtools.cleanupBuffer === 'function' &&\n    // remove the component if it wasn't buffered\n    !devtools.cleanupBuffer(component)\n  ) {\n    _devtoolsComponentRemoved(component)\n  }\n}\n\ntype DevtoolsComponentHook = (component: ComponentInternalInstance) => void\n\n/*@__NO_SIDE_EFFECTS__*/\nfunction createDevtoolsComponentHook(\n  hook: DevtoolsHooks,\n): DevtoolsComponentHook {\n  return (component: ComponentInternalInstance) => {\n    emit(\n      hook,\n      component.appContext.app,\n      component.uid,\n      component.parent ? component.parent.uid : undefined,\n      component,\n    )\n  }\n}\n\nexport const devtoolsPerfStart: DevtoolsPerformanceHook =\n  /*@__PURE__*/ createDevtoolsPerformanceHook(DevtoolsHooks.PERFORMANCE_START)\n\nexport const devtoolsPerfEnd: DevtoolsPerformanceHook =\n  /*@__PURE__*/ createDevtoolsPerformanceHook(DevtoolsHooks.PERFORMANCE_END)\n\ntype DevtoolsPerformanceHook = (\n  component: ComponentInternalInstance,\n  type: string,\n  time: number,\n) => void\nfunction createDevtoolsPerformanceHook(\n  hook: DevtoolsHooks,\n): DevtoolsPerformanceHook {\n  return (component: ComponentInternalInstance, type: string, time: number) => {\n    emit(hook, component.appContext.app, component.uid, component, type, time)\n  }\n}\n\nexport function devtoolsComponentEmit(\n  component: ComponentInternalInstance,\n  event: string,\n  params: any[],\n): void {\n  emit(\n    DevtoolsHooks.COMPONENT_EMIT,\n    component.appContext.app,\n    component,\n    event,\n    params,\n  )\n}\n"
  },
  {
    "path": "packages/runtime-core/src/directives.ts",
    "content": "/**\nRuntime helper for applying directives to a vnode. Example usage:\n\nconst comp = resolveComponent('comp')\nconst foo = resolveDirective('foo')\nconst bar = resolveDirective('bar')\n\nreturn withDirectives(h(comp), [\n  [foo, this.x],\n  [bar, this.y]\n])\n*/\n\nimport type { VNode } from './vnode'\nimport { EMPTY_OBJ, isBuiltInDirective, isFunction } from '@vue/shared'\nimport { warn } from './warning'\nimport {\n  type ComponentInternalInstance,\n  type Data,\n  getComponentPublicInstance,\n} from './component'\nimport { currentRenderingInstance } from './componentRenderContext'\nimport { ErrorCodes, callWithAsyncErrorHandling } from './errorHandling'\nimport type { ComponentPublicInstance } from './componentPublicInstance'\nimport { mapCompatDirectiveHook } from './compat/customDirective'\nimport { pauseTracking, resetTracking, traverse } from '@vue/reactivity'\n\nexport interface DirectiveBinding<\n  Value = any,\n  Modifiers extends string = string,\n  Arg = any,\n> {\n  instance: ComponentPublicInstance | Record<string, any> | null\n  value: Value\n  oldValue: Value | null\n  arg?: Arg\n  modifiers: DirectiveModifiers<Modifiers>\n  dir: ObjectDirective<any, Value, Modifiers, Arg>\n}\n\nexport type DirectiveHook<\n  HostElement = any,\n  Prev = VNode<any, HostElement> | null,\n  Value = any,\n  Modifiers extends string = string,\n  Arg = any,\n> = (\n  el: HostElement,\n  binding: DirectiveBinding<Value, Modifiers, Arg>,\n  vnode: VNode<any, HostElement>,\n  prevVNode: Prev,\n) => void\n\nexport type SSRDirectiveHook<\n  Value = any,\n  Modifiers extends string = string,\n  Arg = any,\n> = (\n  binding: DirectiveBinding<Value, Modifiers, Arg>,\n  vnode: VNode,\n) => Data | undefined\n\nexport interface ObjectDirective<\n  HostElement = any,\n  Value = any,\n  Modifiers extends string = string,\n  Arg = any,\n> {\n  /**\n   * @internal without this, ts-expect-error in directives.test-d.ts somehow\n   * fails when running tsc, but passes in IDE and when testing against built\n   * dts. Could be a TS bug.\n   */\n  __mod?: Modifiers\n  created?: DirectiveHook<HostElement, null, Value, Modifiers, Arg>\n  beforeMount?: DirectiveHook<HostElement, null, Value, Modifiers, Arg>\n  mounted?: DirectiveHook<HostElement, null, Value, Modifiers, Arg>\n  beforeUpdate?: DirectiveHook<\n    HostElement,\n    VNode<any, HostElement>,\n    Value,\n    Modifiers,\n    Arg\n  >\n  updated?: DirectiveHook<\n    HostElement,\n    VNode<any, HostElement>,\n    Value,\n    Modifiers,\n    Arg\n  >\n  beforeUnmount?: DirectiveHook<HostElement, null, Value, Modifiers, Arg>\n  unmounted?: DirectiveHook<HostElement, null, Value, Modifiers, Arg>\n  getSSRProps?: SSRDirectiveHook<Value, Modifiers, Arg>\n  deep?: boolean\n}\n\nexport type FunctionDirective<\n  HostElement = any,\n  V = any,\n  Modifiers extends string = string,\n  Arg = any,\n> = DirectiveHook<HostElement, any, V, Modifiers, Arg>\n\nexport type Directive<\n  HostElement = any,\n  Value = any,\n  Modifiers extends string = string,\n  Arg = any,\n> =\n  | ObjectDirective<HostElement, Value, Modifiers, Arg>\n  | FunctionDirective<HostElement, Value, Modifiers, Arg>\n\nexport type DirectiveModifiers<K extends string = string> = Partial<\n  Record<K, boolean>\n>\n\nexport function validateDirectiveName(name: string): void {\n  if (isBuiltInDirective(name)) {\n    warn('Do not use built-in directive ids as custom directive id: ' + name)\n  }\n}\n\n// Directive, value, argument, modifiers\nexport type DirectiveArguments = Array<\n  | [Directive | undefined]\n  | [Directive | undefined, any]\n  | [Directive | undefined, any, any]\n  | [Directive | undefined, any, any, DirectiveModifiers]\n>\n\n/**\n * Adds directives to a VNode.\n */\nexport function withDirectives<T extends VNode>(\n  vnode: T,\n  directives: DirectiveArguments,\n): T {\n  if (currentRenderingInstance === null) {\n    __DEV__ && warn(`withDirectives can only be used inside render functions.`)\n    return vnode\n  }\n  const instance = getComponentPublicInstance(currentRenderingInstance)\n  const bindings: DirectiveBinding[] = vnode.dirs || (vnode.dirs = [])\n  for (let i = 0; i < directives.length; i++) {\n    let [dir, value, arg, modifiers = EMPTY_OBJ] = directives[i]\n    if (dir) {\n      if (isFunction(dir)) {\n        dir = {\n          mounted: dir,\n          updated: dir,\n        } as ObjectDirective\n      }\n      if (dir.deep) {\n        traverse(value)\n      }\n      bindings.push({\n        dir,\n        instance,\n        value,\n        oldValue: void 0,\n        arg,\n        modifiers,\n      })\n    }\n  }\n  return vnode\n}\n\nexport function invokeDirectiveHook(\n  vnode: VNode,\n  prevVNode: VNode | null,\n  instance: ComponentInternalInstance | null,\n  name: keyof ObjectDirective,\n): void {\n  const bindings = vnode.dirs!\n  const oldBindings = prevVNode && prevVNode.dirs!\n  for (let i = 0; i < bindings.length; i++) {\n    const binding = bindings[i]\n    if (oldBindings) {\n      binding.oldValue = oldBindings[i].value\n    }\n    let hook = binding.dir[name] as DirectiveHook | DirectiveHook[] | undefined\n    if (__COMPAT__ && !hook) {\n      hook = mapCompatDirectiveHook(name, binding.dir, instance)\n    }\n    if (hook) {\n      // disable tracking inside all lifecycle hooks\n      // since they can potentially be called inside effects.\n      pauseTracking()\n      callWithAsyncErrorHandling(hook, instance, ErrorCodes.DIRECTIVE_HOOK, [\n        vnode.el,\n        binding,\n        vnode,\n        prevVNode,\n      ])\n      resetTracking()\n    }\n  }\n}\n"
  },
  {
    "path": "packages/runtime-core/src/enums.ts",
    "content": "export enum LifecycleHooks {\n  BEFORE_CREATE = 'bc',\n  CREATED = 'c',\n  BEFORE_MOUNT = 'bm',\n  MOUNTED = 'm',\n  BEFORE_UPDATE = 'bu',\n  UPDATED = 'u',\n  BEFORE_UNMOUNT = 'bum',\n  UNMOUNTED = 'um',\n  DEACTIVATED = 'da',\n  ACTIVATED = 'a',\n  RENDER_TRIGGERED = 'rtg',\n  RENDER_TRACKED = 'rtc',\n  ERROR_CAPTURED = 'ec',\n  SERVER_PREFETCH = 'sp',\n}\n"
  },
  {
    "path": "packages/runtime-core/src/errorHandling.ts",
    "content": "import { pauseTracking, resetTracking } from '@vue/reactivity'\nimport type { VNode } from './vnode'\nimport type { ComponentInternalInstance } from './component'\nimport { popWarningContext, pushWarningContext, warn } from './warning'\nimport { EMPTY_OBJ, isArray, isFunction, isPromise } from '@vue/shared'\nimport { LifecycleHooks } from './enums'\nimport { WatchErrorCodes } from '@vue/reactivity'\n\n// contexts where user provided function may be executed, in addition to\n// lifecycle hooks.\nexport enum ErrorCodes {\n  SETUP_FUNCTION,\n  RENDER_FUNCTION,\n  // The error codes for the watch have been transferred to the reactivity\n  // package along with baseWatch to maintain code compatibility. Hence,\n  // it is essential to keep these values unchanged.\n  // WATCH_GETTER,\n  // WATCH_CALLBACK,\n  // WATCH_CLEANUP,\n  NATIVE_EVENT_HANDLER = 5,\n  COMPONENT_EVENT_HANDLER,\n  VNODE_HOOK,\n  DIRECTIVE_HOOK,\n  TRANSITION_HOOK,\n  APP_ERROR_HANDLER,\n  APP_WARN_HANDLER,\n  FUNCTION_REF,\n  ASYNC_COMPONENT_LOADER,\n  SCHEDULER,\n  COMPONENT_UPDATE,\n  APP_UNMOUNT_CLEANUP,\n}\n\nexport const ErrorTypeStrings: Record<ErrorTypes, string> = {\n  [LifecycleHooks.SERVER_PREFETCH]: 'serverPrefetch hook',\n  [LifecycleHooks.BEFORE_CREATE]: 'beforeCreate hook',\n  [LifecycleHooks.CREATED]: 'created hook',\n  [LifecycleHooks.BEFORE_MOUNT]: 'beforeMount hook',\n  [LifecycleHooks.MOUNTED]: 'mounted hook',\n  [LifecycleHooks.BEFORE_UPDATE]: 'beforeUpdate hook',\n  [LifecycleHooks.UPDATED]: 'updated',\n  [LifecycleHooks.BEFORE_UNMOUNT]: 'beforeUnmount hook',\n  [LifecycleHooks.UNMOUNTED]: 'unmounted hook',\n  [LifecycleHooks.ACTIVATED]: 'activated hook',\n  [LifecycleHooks.DEACTIVATED]: 'deactivated hook',\n  [LifecycleHooks.ERROR_CAPTURED]: 'errorCaptured hook',\n  [LifecycleHooks.RENDER_TRACKED]: 'renderTracked hook',\n  [LifecycleHooks.RENDER_TRIGGERED]: 'renderTriggered hook',\n  [ErrorCodes.SETUP_FUNCTION]: 'setup function',\n  [ErrorCodes.RENDER_FUNCTION]: 'render function',\n  [WatchErrorCodes.WATCH_GETTER]: 'watcher getter',\n  [WatchErrorCodes.WATCH_CALLBACK]: 'watcher callback',\n  [WatchErrorCodes.WATCH_CLEANUP]: 'watcher cleanup function',\n  [ErrorCodes.NATIVE_EVENT_HANDLER]: 'native event handler',\n  [ErrorCodes.COMPONENT_EVENT_HANDLER]: 'component event handler',\n  [ErrorCodes.VNODE_HOOK]: 'vnode hook',\n  [ErrorCodes.DIRECTIVE_HOOK]: 'directive hook',\n  [ErrorCodes.TRANSITION_HOOK]: 'transition hook',\n  [ErrorCodes.APP_ERROR_HANDLER]: 'app errorHandler',\n  [ErrorCodes.APP_WARN_HANDLER]: 'app warnHandler',\n  [ErrorCodes.FUNCTION_REF]: 'ref function',\n  [ErrorCodes.ASYNC_COMPONENT_LOADER]: 'async component loader',\n  [ErrorCodes.SCHEDULER]: 'scheduler flush',\n  [ErrorCodes.COMPONENT_UPDATE]: 'component update',\n  [ErrorCodes.APP_UNMOUNT_CLEANUP]: 'app unmount cleanup function',\n}\n\nexport type ErrorTypes = LifecycleHooks | ErrorCodes | WatchErrorCodes\n\nexport function callWithErrorHandling(\n  fn: Function,\n  instance: ComponentInternalInstance | null | undefined,\n  type: ErrorTypes,\n  args?: unknown[],\n): any {\n  try {\n    return args ? fn(...args) : fn()\n  } catch (err) {\n    handleError(err, instance, type)\n  }\n}\n\nexport function callWithAsyncErrorHandling(\n  fn: Function | Function[],\n  instance: ComponentInternalInstance | null,\n  type: ErrorTypes,\n  args?: unknown[],\n): any {\n  if (isFunction(fn)) {\n    const res = callWithErrorHandling(fn, instance, type, args)\n    if (res && isPromise(res)) {\n      res.catch(err => {\n        handleError(err, instance, type)\n      })\n    }\n    return res\n  }\n\n  if (isArray(fn)) {\n    const values = []\n    for (let i = 0; i < fn.length; i++) {\n      values.push(callWithAsyncErrorHandling(fn[i], instance, type, args))\n    }\n    return values\n  } else if (__DEV__) {\n    warn(\n      `Invalid value type passed to callWithAsyncErrorHandling(): ${typeof fn}`,\n    )\n  }\n}\n\nexport function handleError(\n  err: unknown,\n  instance: ComponentInternalInstance | null | undefined,\n  type: ErrorTypes,\n  throwInDev = true,\n): void {\n  const contextVNode = instance ? instance.vnode : null\n  const { errorHandler, throwUnhandledErrorInProduction } =\n    (instance && instance.appContext.config) || EMPTY_OBJ\n  if (instance) {\n    let cur = instance.parent\n    // the exposed instance is the render proxy to keep it consistent with 2.x\n    const exposedInstance = instance.proxy\n    // in production the hook receives only the error code\n    const errorInfo = __DEV__\n      ? ErrorTypeStrings[type]\n      : `https://vuejs.org/error-reference/#runtime-${type}`\n    while (cur) {\n      const errorCapturedHooks = cur.ec\n      if (errorCapturedHooks) {\n        for (let i = 0; i < errorCapturedHooks.length; i++) {\n          if (\n            errorCapturedHooks[i](err, exposedInstance, errorInfo) === false\n          ) {\n            return\n          }\n        }\n      }\n      cur = cur.parent\n    }\n    // app-level handling\n    if (errorHandler) {\n      pauseTracking()\n      callWithErrorHandling(errorHandler, null, ErrorCodes.APP_ERROR_HANDLER, [\n        err,\n        exposedInstance,\n        errorInfo,\n      ])\n      resetTracking()\n      return\n    }\n  }\n  logError(err, type, contextVNode, throwInDev, throwUnhandledErrorInProduction)\n}\n\nfunction logError(\n  err: unknown,\n  type: ErrorTypes,\n  contextVNode: VNode | null,\n  throwInDev = true,\n  throwInProd = false,\n) {\n  if (__DEV__) {\n    const info = ErrorTypeStrings[type]\n    if (contextVNode) {\n      pushWarningContext(contextVNode)\n    }\n    warn(`Unhandled error${info ? ` during execution of ${info}` : ``}`)\n    if (contextVNode) {\n      popWarningContext()\n    }\n    // crash in dev by default so it's more noticeable\n    if (throwInDev) {\n      throw err\n    } else if (!__TEST__) {\n      console.error(err)\n    }\n  } else if (throwInProd) {\n    throw err\n  } else {\n    // recover in prod to reduce the impact on end-user\n    console.error(err)\n  }\n}\n"
  },
  {
    "path": "packages/runtime-core/src/featureFlags.ts",
    "content": "import { getGlobalThis } from '@vue/shared'\n\n/**\n * This is only called in esm-bundler builds.\n * It is called when a renderer is created, in `baseCreateRenderer` so that\n * importing runtime-core is side-effects free.\n */\nexport function initFeatureFlags(): void {\n  const needWarn = []\n\n  if (typeof __FEATURE_OPTIONS_API__ !== 'boolean') {\n    __DEV__ && needWarn.push(`__VUE_OPTIONS_API__`)\n    getGlobalThis().__VUE_OPTIONS_API__ = true\n  }\n\n  if (typeof __FEATURE_PROD_DEVTOOLS__ !== 'boolean') {\n    __DEV__ && needWarn.push(`__VUE_PROD_DEVTOOLS__`)\n    getGlobalThis().__VUE_PROD_DEVTOOLS__ = false\n  }\n\n  if (typeof __FEATURE_PROD_HYDRATION_MISMATCH_DETAILS__ !== 'boolean') {\n    __DEV__ && needWarn.push(`__VUE_PROD_HYDRATION_MISMATCH_DETAILS__`)\n    getGlobalThis().__VUE_PROD_HYDRATION_MISMATCH_DETAILS__ = false\n  }\n\n  if (__DEV__ && needWarn.length) {\n    const multi = needWarn.length > 1\n    console.warn(\n      `Feature flag${multi ? `s` : ``} ${needWarn.join(', ')} ${\n        multi ? `are` : `is`\n      } not explicitly defined. You are running the esm-bundler build of Vue, ` +\n        `which expects these compile-time feature flags to be globally injected ` +\n        `via the bundler config in order to get better tree-shaking in the ` +\n        `production bundle.\\n\\n` +\n        `For more details, see https://link.vuejs.org/feature-flags.`,\n    )\n  }\n}\n"
  },
  {
    "path": "packages/runtime-core/src/h.ts",
    "content": "import {\n  type Comment,\n  type Fragment,\n  type Text,\n  type VNode,\n  type VNodeArrayChildren,\n  type VNodeProps,\n  createVNode,\n  isVNode,\n  setBlockTracking,\n} from './vnode'\nimport type { Teleport, TeleportProps } from './components/Teleport'\nimport type { Suspense, SuspenseProps } from './components/Suspense'\nimport { type IfAny, isArray, isObject } from '@vue/shared'\nimport type { RawSlots } from './componentSlots'\nimport type {\n  Component,\n  ComponentOptions,\n  ConcreteComponent,\n  FunctionalComponent,\n} from './component'\nimport type { EmitsOptions } from './componentEmits'\nimport type { DefineComponent } from './apiDefineComponent'\n\n// `h` is a more user-friendly version of `createVNode` that allows omitting the\n// props when possible. It is intended for manually written render functions.\n// Compiler-generated code uses `createVNode` because\n// 1. it is monomorphic and avoids the extra call overhead\n// 2. it allows specifying patchFlags for optimization\n\n/*\n// type only\nh('div')\n\n// type + props\nh('div', {})\n\n// type + omit props + children\n// Omit props does NOT support named slots\nh('div', []) // array\nh('div', 'foo') // text\nh('div', h('br')) // vnode\nh(Component, () => {}) // default slot\n\n// type + props + children\nh('div', {}, []) // array\nh('div', {}, 'foo') // text\nh('div', {}, h('br')) // vnode\nh(Component, {}, () => {}) // default slot\nh(Component, {}, {}) // named slots\n\n// named slots without props requires explicit `null` to avoid ambiguity\nh(Component, null, {})\n**/\n\ntype RawProps = VNodeProps & {\n  // used to differ from a single VNode object as children\n  __v_isVNode?: never\n  // used to differ from Array children\n  [Symbol.iterator]?: never\n} & Record<string, any>\n\ntype RawChildren =\n  | string\n  | number\n  | boolean\n  | VNode\n  | VNodeArrayChildren\n  | (() => any)\n\n// fake constructor type returned from `defineComponent`\ninterface Constructor<P = any> {\n  __isFragment?: never\n  __isTeleport?: never\n  __isSuspense?: never\n  new (...args: any[]): { $props: P }\n}\n\ntype HTMLElementEventHandler = {\n  [K in keyof HTMLElementEventMap as `on${Capitalize<K>}`]?: (\n    ev: HTMLElementEventMap[K],\n  ) => any\n}\n\n// The following is a series of overloads for providing props validation of\n// manually written render functions.\n\n// element\nexport function h<K extends keyof HTMLElementTagNameMap>(\n  type: K,\n  children?: RawChildren,\n): VNode\nexport function h<K extends keyof HTMLElementTagNameMap>(\n  type: K,\n  props?: (RawProps & HTMLElementEventHandler) | null,\n  children?: RawChildren | RawSlots,\n): VNode\n\n// custom element\nexport function h(type: string, children?: RawChildren): VNode\nexport function h(\n  type: string,\n  props?: RawProps | null,\n  children?: RawChildren | RawSlots,\n): VNode\n\n// text/comment\nexport function h(\n  type: typeof Text | typeof Comment,\n  children?: string | number | boolean,\n): VNode\nexport function h(\n  type: typeof Text | typeof Comment,\n  props?: null,\n  children?: string | number | boolean,\n): VNode\n// fragment\nexport function h(type: typeof Fragment, children?: VNodeArrayChildren): VNode\nexport function h(\n  type: typeof Fragment,\n  props?: RawProps | null,\n  children?: VNodeArrayChildren,\n): VNode\n\n// teleport (target prop is required)\nexport function h(\n  type: typeof Teleport,\n  props: RawProps & TeleportProps,\n  children: RawChildren | RawSlots,\n): VNode\n\n// suspense\nexport function h(type: typeof Suspense, children?: RawChildren): VNode\nexport function h(\n  type: typeof Suspense,\n  props?: (RawProps & SuspenseProps) | null,\n  children?: RawChildren | RawSlots,\n): VNode\n\n// functional component\nexport function h<\n  P,\n  E extends EmitsOptions = {},\n  S extends Record<string, any> = any,\n>(\n  type: FunctionalComponent<P, any, S, any>,\n  props?: (RawProps & P) | ({} extends P ? null : never),\n  children?: RawChildren | IfAny<S, RawSlots, S>,\n): VNode\n\n// catch-all for generic component types\nexport function h(type: Component, children?: RawChildren): VNode\n\n// concrete component\nexport function h<P>(\n  type: ConcreteComponent | string,\n  children?: RawChildren,\n): VNode\nexport function h<P>(\n  type: ConcreteComponent<P> | string,\n  props?: (RawProps & P) | ({} extends P ? null : never),\n  children?: RawChildren,\n): VNode\n\n// component without props\nexport function h<P>(\n  type: Component<P>,\n  props?: (RawProps & P) | null,\n  children?: RawChildren | RawSlots,\n): VNode\n\n// exclude `defineComponent` constructors\nexport function h<P>(\n  type: ComponentOptions<P>,\n  props?: (RawProps & P) | ({} extends P ? null : never),\n  children?: RawChildren | RawSlots,\n): VNode\n\n// fake constructor type returned by `defineComponent` or class component\nexport function h(type: Constructor, children?: RawChildren): VNode\nexport function h<P>(\n  type: Constructor<P>,\n  props?: (RawProps & P) | ({} extends P ? null : never),\n  children?: RawChildren | RawSlots,\n): VNode\n\n// fake constructor type returned by `defineComponent`\nexport function h(type: DefineComponent, children?: RawChildren): VNode\nexport function h<P>(\n  type: DefineComponent<P>,\n  props?: (RawProps & P) | ({} extends P ? null : never),\n  children?: RawChildren | RawSlots,\n): VNode\n\n// catch all types\nexport function h(type: string | Component, children?: RawChildren): VNode\nexport function h<P>(\n  type: string | Component<P>,\n  props?: (RawProps & P) | ({} extends P ? null : never),\n  children?: RawChildren | RawSlots,\n): VNode\n\n// Actual implementation\nexport function h(type: any, propsOrChildren?: any, children?: any): VNode {\n  try {\n    // #6913 disable tracking block in h function\n    setBlockTracking(-1)\n    const l = arguments.length\n    if (l === 2) {\n      if (isObject(propsOrChildren) && !isArray(propsOrChildren)) {\n        // single vnode without props\n        if (isVNode(propsOrChildren)) {\n          return createVNode(type, null, [propsOrChildren])\n        }\n        // props without children\n        return createVNode(type, propsOrChildren)\n      } else {\n        // omit props\n        return createVNode(type, null, propsOrChildren)\n      }\n    } else {\n      if (l > 3) {\n        children = Array.prototype.slice.call(arguments, 2)\n      } else if (l === 3 && isVNode(children)) {\n        children = [children]\n      }\n      return createVNode(type, propsOrChildren, children)\n    }\n  } finally {\n    setBlockTracking(1)\n  }\n}\n"
  },
  {
    "path": "packages/runtime-core/src/helpers/createSlots.ts",
    "content": "import { isArray } from '@vue/shared'\nimport type { VNode } from '../vnode'\n\n// #6651 res can be undefined in SSR in string push mode\ntype SSRSlot = (...args: any[]) => VNode[] | undefined\n\ninterface CompiledSlotDescriptor {\n  name: string\n  fn: SSRSlot\n  key?: string\n}\n\n/**\n * Compiler runtime helper for creating dynamic slots object\n * @private\n */\nexport function createSlots(\n  slots: Record<string, SSRSlot>,\n  dynamicSlots: (\n    | CompiledSlotDescriptor\n    | CompiledSlotDescriptor[]\n    | undefined\n  )[],\n): Record<string, SSRSlot> {\n  for (let i = 0; i < dynamicSlots.length; i++) {\n    const slot = dynamicSlots[i]\n    // array of dynamic slot generated by <template v-for=\"...\" #[...]>\n    if (isArray(slot)) {\n      for (let j = 0; j < slot.length; j++) {\n        slots[slot[j].name] = slot[j].fn\n      }\n    } else if (slot) {\n      // conditional single slot generated by <template v-if=\"...\" #foo>\n      slots[slot.name] = slot.key\n        ? (...args: any[]) => {\n            const res = slot.fn(...args)\n            // attach branch key so each conditional branch is considered a\n            // different fragment\n            if (res) (res as any).key = slot.key\n            return res\n          }\n        : slot.fn\n    }\n  }\n  return slots\n}\n"
  },
  {
    "path": "packages/runtime-core/src/helpers/renderList.ts",
    "content": "import type { VNode, VNodeChild } from '../vnode'\nimport {\n  isReactive,\n  isReadonly,\n  isShallow,\n  shallowReadArray,\n  toReactive,\n  toReadonly,\n} from '@vue/reactivity'\nimport { isArray, isObject, isString } from '@vue/shared'\nimport { warn } from '../warning'\n\n/**\n * v-for string\n * @private\n */\nexport function renderList(\n  source: string,\n  renderItem: (value: string, index: number) => VNodeChild,\n): VNodeChild[]\n\n/**\n * v-for number\n */\nexport function renderList(\n  source: number,\n  renderItem: (value: number, index: number) => VNodeChild,\n): VNodeChild[]\n\n/**\n * v-for array\n */\nexport function renderList<T>(\n  source: T[],\n  renderItem: (value: T, index: number) => VNodeChild,\n): VNodeChild[]\n\n/**\n * v-for iterable\n */\nexport function renderList<T>(\n  source: Iterable<T>,\n  renderItem: (value: T, index: number) => VNodeChild,\n): VNodeChild[]\n\n/**\n * v-for object\n */\nexport function renderList<T>(\n  source: T,\n  renderItem: <K extends keyof T>(\n    value: T[K],\n    key: string,\n    index: number,\n  ) => VNodeChild,\n): VNodeChild[]\n\n/**\n * Actual implementation\n */\nexport function renderList(\n  source: any,\n  renderItem: (...args: any[]) => VNodeChild,\n  cache?: any[],\n  index?: number,\n): VNodeChild[] {\n  let ret: VNodeChild[]\n  const cached = (cache && cache[index!]) as VNode[] | undefined\n  const sourceIsArray = isArray(source)\n\n  if (sourceIsArray || isString(source)) {\n    const sourceIsReactiveArray = sourceIsArray && isReactive(source)\n    let needsWrap = false\n    let isReadonlySource = false\n    if (sourceIsReactiveArray) {\n      needsWrap = !isShallow(source)\n      isReadonlySource = isReadonly(source)\n      source = shallowReadArray(source)\n    }\n    ret = new Array(source.length)\n    for (let i = 0, l = source.length; i < l; i++) {\n      ret[i] = renderItem(\n        needsWrap\n          ? isReadonlySource\n            ? toReadonly(toReactive(source[i]))\n            : toReactive(source[i])\n          : source[i],\n        i,\n        undefined,\n        cached && cached[i],\n      )\n    }\n  } else if (typeof source === 'number') {\n    if (__DEV__ && (!Number.isInteger(source) || source < 0)) {\n      warn(\n        `The v-for range expects a positive integer value but got ${source}.`,\n      )\n      ret = []\n    } else {\n      ret = new Array(source)\n      for (let i = 0; i < source; i++) {\n        ret[i] = renderItem(i + 1, i, undefined, cached && cached[i])\n      }\n    }\n  } else if (isObject(source)) {\n    if (source[Symbol.iterator as any]) {\n      ret = Array.from(source as Iterable<any>, (item, i) =>\n        renderItem(item, i, undefined, cached && cached[i]),\n      )\n    } else {\n      const keys = Object.keys(source)\n      ret = new Array(keys.length)\n      for (let i = 0, l = keys.length; i < l; i++) {\n        const key = keys[i]\n        ret[i] = renderItem(source[key], key, i, cached && cached[i])\n      }\n    }\n  } else {\n    ret = []\n  }\n\n  if (cache) {\n    cache[index!] = ret\n  }\n  return ret\n}\n"
  },
  {
    "path": "packages/runtime-core/src/helpers/renderSlot.ts",
    "content": "import type { Data } from '../component'\nimport type { RawSlots, Slots } from '../componentSlots'\nimport {\n  type ContextualRenderFn,\n  currentRenderingInstance,\n} from '../componentRenderContext'\nimport {\n  Comment,\n  Fragment,\n  type VNode,\n  type VNodeArrayChildren,\n  createBlock,\n  createVNode,\n  isVNode,\n  openBlock,\n} from '../vnode'\nimport { PatchFlags, SlotFlags, isSymbol } from '@vue/shared'\nimport { warn } from '../warning'\nimport { isAsyncWrapper } from '../apiAsyncComponent'\n\n/**\n * Compiler runtime helper for rendering `<slot/>`\n * @private\n */\nexport function renderSlot(\n  slots: Slots,\n  name: string,\n  props: Data = {},\n  // this is not a user-facing function, so the fallback is always generated by\n  // the compiler and guaranteed to be a function returning an array\n  fallback?: () => VNodeArrayChildren,\n  noSlotted?: boolean,\n): VNode {\n  if (\n    currentRenderingInstance!.ce ||\n    (currentRenderingInstance!.parent &&\n      isAsyncWrapper(currentRenderingInstance!.parent) &&\n      currentRenderingInstance!.parent.ce)\n  ) {\n    const hasProps = Object.keys(props).length > 0\n    // in custom element mode, render <slot/> as actual slot outlets\n    // wrap it with a fragment because in shadowRoot: false mode the slot\n    // element gets replaced by injected content\n    if (name !== 'default') props.name = name\n    return (\n      openBlock(),\n      createBlock(\n        Fragment,\n        null,\n        [createVNode('slot', props, fallback && fallback())],\n        hasProps ? PatchFlags.BAIL : PatchFlags.STABLE_FRAGMENT,\n      )\n    )\n  }\n\n  let slot = slots[name]\n\n  if (__DEV__ && slot && slot.length > 1) {\n    warn(\n      `SSR-optimized slot function detected in a non-SSR-optimized render ` +\n        `function. You need to mark this component with $dynamic-slots in the ` +\n        `parent template.`,\n    )\n    slot = () => []\n  }\n\n  // a compiled slot disables block tracking by default to avoid manual\n  // invocation interfering with template-based block tracking, but in\n  // `renderSlot` we can be sure that it's template-based so we can force\n  // enable it.\n  if (slot && (slot as ContextualRenderFn)._c) {\n    ;(slot as ContextualRenderFn)._d = false\n  }\n  openBlock()\n  const validSlotContent = slot && ensureValidVNode(slot(props))\n  const slotKey =\n    props.key ||\n    // slot content array of a dynamic conditional slot may have a branch\n    // key attached in the `createSlots` helper, respect that\n    (validSlotContent && (validSlotContent as any).key)\n  const rendered = createBlock(\n    Fragment,\n    {\n      key:\n        (slotKey && !isSymbol(slotKey) ? slotKey : `_${name}`) +\n        // #7256 force differentiate fallback content from actual content\n        (!validSlotContent && fallback ? '_fb' : ''),\n    },\n    validSlotContent || (fallback ? fallback() : []),\n    validSlotContent && (slots as RawSlots)._ === SlotFlags.STABLE\n      ? PatchFlags.STABLE_FRAGMENT\n      : PatchFlags.BAIL,\n  )\n  if (!noSlotted && rendered.scopeId) {\n    rendered.slotScopeIds = [rendered.scopeId + '-s']\n  }\n  if (slot && (slot as ContextualRenderFn)._c) {\n    ;(slot as ContextualRenderFn)._d = true\n  }\n  return rendered\n}\n\nexport function ensureValidVNode(\n  vnodes: VNodeArrayChildren,\n): VNodeArrayChildren | null {\n  return vnodes.some(child => {\n    if (!isVNode(child)) return true\n    if (child.type === Comment) return false\n    if (\n      child.type === Fragment &&\n      !ensureValidVNode(child.children as VNodeArrayChildren)\n    )\n      return false\n    return true\n  })\n    ? vnodes\n    : null\n}\n"
  },
  {
    "path": "packages/runtime-core/src/helpers/resolveAssets.ts",
    "content": "import {\n  type ComponentOptions,\n  type ConcreteComponent,\n  currentInstance,\n  getComponentName,\n} from '../component'\nimport { currentRenderingInstance } from '../componentRenderContext'\nimport type { Directive } from '../directives'\nimport { camelize, capitalize, isString } from '@vue/shared'\nimport { warn } from '../warning'\nimport type { VNodeTypes } from '../vnode'\n\nexport const COMPONENTS = 'components'\nexport const DIRECTIVES = 'directives'\nexport const FILTERS = 'filters'\n\nexport type AssetTypes = typeof COMPONENTS | typeof DIRECTIVES | typeof FILTERS\n\n/**\n * @private\n */\nexport function resolveComponent(\n  name: string,\n  maybeSelfReference?: boolean,\n): ConcreteComponent | string {\n  return resolveAsset(COMPONENTS, name, true, maybeSelfReference) || name\n}\n\nexport const NULL_DYNAMIC_COMPONENT: unique symbol = Symbol.for('v-ndc')\n\n/**\n * @private\n */\nexport function resolveDynamicComponent(component: unknown): VNodeTypes {\n  if (isString(component)) {\n    return resolveAsset(COMPONENTS, component, false) || component\n  } else {\n    // invalid types will fallthrough to createVNode and raise warning\n    return (component || NULL_DYNAMIC_COMPONENT) as any\n  }\n}\n\n/**\n * @private\n */\nexport function resolveDirective(name: string): Directive | undefined {\n  return resolveAsset(DIRECTIVES, name)\n}\n\n/**\n * v2 compat only\n * @internal\n */\nexport function resolveFilter(name: string): Function | undefined {\n  return resolveAsset(FILTERS, name)\n}\n\n/**\n * @private\n * overload 1: components\n */\nfunction resolveAsset(\n  type: typeof COMPONENTS,\n  name: string,\n  warnMissing?: boolean,\n  maybeSelfReference?: boolean,\n): ConcreteComponent | undefined\n// overload 2: directives\nfunction resolveAsset(\n  type: typeof DIRECTIVES,\n  name: string,\n): Directive | undefined\n// implementation\n// overload 3: filters (compat only)\nfunction resolveAsset(type: typeof FILTERS, name: string): Function | undefined\n// implementation\nfunction resolveAsset(\n  type: AssetTypes,\n  name: string,\n  warnMissing = true,\n  maybeSelfReference = false,\n) {\n  const instance = currentRenderingInstance || currentInstance\n  if (instance) {\n    const Component = instance.type\n\n    // explicit self name has highest priority\n    if (type === COMPONENTS) {\n      const selfName = getComponentName(\n        Component,\n        false /* do not include inferred name to avoid breaking existing code */,\n      )\n      if (\n        selfName &&\n        (selfName === name ||\n          selfName === camelize(name) ||\n          selfName === capitalize(camelize(name)))\n      ) {\n        return Component\n      }\n    }\n\n    const res =\n      // local registration\n      // check instance[type] first which is resolved for options API\n      resolve(instance[type] || (Component as ComponentOptions)[type], name) ||\n      // global registration\n      resolve(instance.appContext[type], name)\n\n    if (!res && maybeSelfReference) {\n      // fallback to implicit self-reference\n      return Component\n    }\n\n    if (__DEV__ && warnMissing && !res) {\n      const extra =\n        type === COMPONENTS\n          ? `\\nIf this is a native custom element, make sure to exclude it from ` +\n            `component resolution via compilerOptions.isCustomElement.`\n          : ``\n      warn(`Failed to resolve ${type.slice(0, -1)}: ${name}${extra}`)\n    }\n\n    return res\n  } else if (__DEV__) {\n    warn(\n      `resolve${capitalize(type.slice(0, -1))} ` +\n        `can only be used in render() or setup().`,\n    )\n  }\n}\n\nfunction resolve(registry: Record<string, any> | undefined, name: string) {\n  return (\n    registry &&\n    (registry[name] ||\n      registry[camelize(name)] ||\n      registry[capitalize(camelize(name))])\n  )\n}\n"
  },
  {
    "path": "packages/runtime-core/src/helpers/toHandlers.ts",
    "content": "import { isObject, toHandlerKey } from '@vue/shared'\nimport { warn } from '../warning'\n\n/**\n * For prefixing keys in v-on=\"obj\" with \"on\"\n * @private\n */\nexport function toHandlers(\n  obj: Record<string, any>,\n  preserveCaseIfNecessary?: boolean,\n): Record<string, any> {\n  const ret: Record<string, any> = {}\n  if (__DEV__ && !isObject(obj)) {\n    warn(`v-on with no argument expects an object value.`)\n    return ret\n  }\n  for (const key in obj) {\n    ret[\n      preserveCaseIfNecessary && /[A-Z]/.test(key)\n        ? `on:${key}`\n        : toHandlerKey(key)\n    ] = obj[key]\n  }\n  return ret\n}\n"
  },
  {
    "path": "packages/runtime-core/src/helpers/useId.ts",
    "content": "import {\n  type ComponentInternalInstance,\n  getCurrentInstance,\n} from '../component'\nimport { warn } from '../warning'\n\nexport function useId(): string {\n  const i = getCurrentInstance()\n  if (i) {\n    return (i.appContext.config.idPrefix || 'v') + '-' + i.ids[0] + i.ids[1]++\n  } else if (__DEV__) {\n    warn(\n      `useId() is called when there is no active component ` +\n        `instance to be associated with.`,\n    )\n  }\n  return ''\n}\n\n/**\n * There are 3 types of async boundaries:\n * - async components\n * - components with async setup()\n * - components with serverPrefetch\n */\nexport function markAsyncBoundary(instance: ComponentInternalInstance): void {\n  instance.ids = [instance.ids[0] + instance.ids[2]++ + '-', 0, 0]\n}\n"
  },
  {
    "path": "packages/runtime-core/src/helpers/useModel.ts",
    "content": "import { type Ref, customRef, ref } from '@vue/reactivity'\nimport { EMPTY_OBJ, camelize, hasChanged, hyphenate } from '@vue/shared'\nimport type { DefineModelOptions, ModelRef } from '../apiSetupHelpers'\nimport { getCurrentInstance } from '../component'\nimport { warn } from '../warning'\nimport type { NormalizedProps } from '../componentProps'\nimport { watchSyncEffect } from '../apiWatch'\n\nexport function useModel<\n  M extends PropertyKey,\n  T extends Record<string, any>,\n  K extends keyof T,\n  G = T[K],\n  S = T[K],\n>(\n  props: T,\n  name: K,\n  options?: DefineModelOptions<T[K], G, S>,\n): ModelRef<T[K], M, G, S>\nexport function useModel(\n  props: Record<string, any>,\n  name: string,\n  options: DefineModelOptions = EMPTY_OBJ,\n): Ref {\n  const i = getCurrentInstance()!\n  if (__DEV__ && !i) {\n    warn(`useModel() called without active instance.`)\n    return ref() as any\n  }\n\n  const camelizedName = camelize(name)\n  if (__DEV__ && !(i.propsOptions[0] as NormalizedProps)[camelizedName]) {\n    warn(`useModel() called with prop \"${name}\" which is not declared.`)\n    return ref() as any\n  }\n\n  const hyphenatedName = hyphenate(name)\n  const modifiers = getModelModifiers(props, camelizedName)\n\n  const res = customRef((track, trigger) => {\n    let localValue: any\n    let prevSetValue: any = EMPTY_OBJ\n    let prevEmittedValue: any\n\n    watchSyncEffect(() => {\n      const propValue = props[camelizedName]\n      if (hasChanged(localValue, propValue)) {\n        localValue = propValue\n        trigger()\n      }\n    })\n\n    return {\n      get() {\n        track()\n        return options.get ? options.get(localValue) : localValue\n      },\n\n      set(value) {\n        const emittedValue = options.set ? options.set(value) : value\n        if (\n          !hasChanged(emittedValue, localValue) &&\n          !(prevSetValue !== EMPTY_OBJ && hasChanged(value, prevSetValue))\n        ) {\n          return\n        }\n        const rawProps = i.vnode!.props\n        if (\n          !(\n            rawProps &&\n            // check if parent has passed v-model\n            (name in rawProps ||\n              camelizedName in rawProps ||\n              hyphenatedName in rawProps) &&\n            (`onUpdate:${name}` in rawProps ||\n              `onUpdate:${camelizedName}` in rawProps ||\n              `onUpdate:${hyphenatedName}` in rawProps)\n          )\n        ) {\n          // no v-model, local update\n          localValue = value\n          trigger()\n        }\n\n        i.emit(`update:${name}`, emittedValue)\n        // #10279: if the local value is converted via a setter but the value\n        // emitted to parent was the same, the parent will not trigger any\n        // updates and there will be no prop sync. However the local input state\n        // may be out of sync, so we need to force an update here.\n        if (\n          hasChanged(value, emittedValue) &&\n          hasChanged(value, prevSetValue) &&\n          !hasChanged(emittedValue, prevEmittedValue)\n        ) {\n          trigger()\n        }\n        prevSetValue = value\n        prevEmittedValue = emittedValue\n      },\n    }\n  })\n\n  // @ts-expect-error\n  res[Symbol.iterator] = () => {\n    let i = 0\n    return {\n      next() {\n        if (i < 2) {\n          return { value: i++ ? modifiers || EMPTY_OBJ : res, done: false }\n        } else {\n          return { done: true }\n        }\n      },\n    }\n  }\n\n  return res\n}\n\nexport const getModelModifiers = (\n  props: Record<string, any>,\n  modelName: string,\n): Record<string, boolean> | undefined => {\n  return modelName === 'modelValue' || modelName === 'model-value'\n    ? props.modelModifiers\n    : props[`${modelName}Modifiers`] ||\n        props[`${camelize(modelName)}Modifiers`] ||\n        props[`${hyphenate(modelName)}Modifiers`]\n}\n"
  },
  {
    "path": "packages/runtime-core/src/helpers/useSsrContext.ts",
    "content": "import { inject } from '../apiInject'\nimport { warn } from '../warning'\n\nexport const ssrContextKey: unique symbol = Symbol.for('v-scx')\n\nexport const useSSRContext = <T = Record<string, any>>(): T | undefined => {\n  if (!__GLOBAL__) {\n    const ctx = inject<T>(ssrContextKey)\n    if (!ctx) {\n      __DEV__ &&\n        warn(\n          `Server rendering context not provided. Make sure to only call ` +\n            `useSSRContext() conditionally in the server build.`,\n        )\n    }\n    return ctx\n  } else if (__DEV__) {\n    warn(`useSSRContext() is not supported in the global build.`)\n  }\n}\n"
  },
  {
    "path": "packages/runtime-core/src/helpers/useTemplateRef.ts",
    "content": "import { type ShallowRef, readonly, shallowRef } from '@vue/reactivity'\nimport { type Data, getCurrentInstance } from '../component'\nimport { warn } from '../warning'\nimport { EMPTY_OBJ } from '@vue/shared'\n\nexport const knownTemplateRefs: WeakSet<ShallowRef> = new WeakSet()\n\nexport type TemplateRef<T = unknown> = Readonly<ShallowRef<T | null>>\n\nexport function useTemplateRef<T = unknown, Keys extends string = string>(\n  key: Keys,\n): TemplateRef<T> {\n  const i = getCurrentInstance()\n  const r = shallowRef(null)\n  if (i) {\n    const refs = i.refs === EMPTY_OBJ ? (i.refs = {}) : i.refs\n    if (__DEV__ && isTemplateRefKey(refs, key)) {\n      warn(`useTemplateRef('${key}') already exists.`)\n    } else {\n      Object.defineProperty(refs, key, {\n        enumerable: true,\n        get: () => r.value,\n        set: val => (r.value = val),\n      })\n    }\n  } else if (__DEV__) {\n    warn(\n      `useTemplateRef() is called when there is no active component ` +\n        `instance to be associated with.`,\n    )\n  }\n  const ret = __DEV__ ? readonly(r) : r\n  if (__DEV__) {\n    knownTemplateRefs.add(ret)\n  }\n  return ret\n}\n\nexport function isTemplateRefKey(refs: Data, key: string): boolean {\n  let desc: PropertyDescriptor | undefined\n  return !!(\n    (desc = Object.getOwnPropertyDescriptor(refs, key)) && !desc.configurable\n  )\n}\n"
  },
  {
    "path": "packages/runtime-core/src/helpers/withMemo.ts",
    "content": "import { hasChanged } from '@vue/shared'\nimport { type VNode, currentBlock, isBlockTreeEnabled } from '../vnode'\n\nexport function withMemo(\n  memo: any[],\n  render: () => VNode<any, any>,\n  cache: any[],\n  index: number,\n): VNode<any, any> {\n  const cached = cache[index] as VNode | undefined\n  if (cached && isMemoSame(cached, memo)) {\n    return cached\n  }\n  const ret = render()\n\n  // shallow clone\n  ret.memo = memo.slice()\n  ret.cacheIndex = index\n\n  return (cache[index] = ret)\n}\n\nexport function isMemoSame(cached: VNode, memo: any[]): boolean {\n  const prev: any[] = cached.memo!\n  if (prev.length != memo.length) {\n    return false\n  }\n\n  for (let i = 0; i < prev.length; i++) {\n    if (hasChanged(prev[i], memo[i])) {\n      return false\n    }\n  }\n\n  // make sure to let parent block track it when returning cached\n  if (isBlockTreeEnabled > 0 && currentBlock) {\n    currentBlock.push(cached)\n  }\n  return true\n}\n"
  },
  {
    "path": "packages/runtime-core/src/hmr.ts",
    "content": "/* eslint-disable no-restricted-globals */\nimport {\n  type ClassComponent,\n  type ComponentInternalInstance,\n  type ComponentOptions,\n  type ConcreteComponent,\n  type InternalRenderFunction,\n  isClassComponent,\n} from './component'\nimport { SchedulerJobFlags, queueJob, queuePostFlushCb } from './scheduler'\nimport { extend, getGlobalThis } from '@vue/shared'\n\ntype HMRComponent = ComponentOptions | ClassComponent\n\nexport let isHmrUpdating = false\n\nexport const hmrDirtyComponents: Map<\n  ConcreteComponent,\n  Set<ComponentInternalInstance>\n> = new Map<ConcreteComponent, Set<ComponentInternalInstance>>()\n\nexport interface HMRRuntime {\n  createRecord: typeof createRecord\n  rerender: typeof rerender\n  reload: typeof reload\n}\n\n// Expose the HMR runtime on the global object\n// This makes it entirely tree-shakable without polluting the exports and makes\n// it easier to be used in toolings like vue-loader\n// Note: for a component to be eligible for HMR it also needs the __hmrId option\n// to be set so that its instances can be registered / removed.\nif (__DEV__) {\n  getGlobalThis().__VUE_HMR_RUNTIME__ = {\n    createRecord: tryWrap(createRecord),\n    rerender: tryWrap(rerender),\n    reload: tryWrap(reload),\n  } as HMRRuntime\n}\n\nconst map: Map<\n  string,\n  {\n    // the initial component definition is recorded on import - this allows us\n    // to apply hot updates to the component even when there are no actively\n    // rendered instance.\n    initialDef: ComponentOptions\n    instances: Set<ComponentInternalInstance>\n  }\n> = new Map()\n\nexport function registerHMR(instance: ComponentInternalInstance): void {\n  const id = instance.type.__hmrId!\n  let record = map.get(id)\n  if (!record) {\n    createRecord(id, instance.type as HMRComponent)\n    record = map.get(id)!\n  }\n  record.instances.add(instance)\n}\n\nexport function unregisterHMR(instance: ComponentInternalInstance): void {\n  map.get(instance.type.__hmrId!)!.instances.delete(instance)\n}\n\nfunction createRecord(id: string, initialDef: HMRComponent): boolean {\n  if (map.has(id)) {\n    return false\n  }\n  map.set(id, {\n    initialDef: normalizeClassComponent(initialDef),\n    instances: new Set(),\n  })\n  return true\n}\n\nfunction normalizeClassComponent(component: HMRComponent): ComponentOptions {\n  return isClassComponent(component) ? component.__vccOpts : component\n}\n\nfunction rerender(id: string, newRender?: Function): void {\n  const record = map.get(id)\n  if (!record) {\n    return\n  }\n\n  // update initial record (for not-yet-rendered component)\n  record.initialDef.render = newRender\n\n  // Create a snapshot which avoids the set being mutated during updates\n  ;[...record.instances].forEach(instance => {\n    if (newRender) {\n      instance.render = newRender as InternalRenderFunction\n      normalizeClassComponent(instance.type as HMRComponent).render = newRender\n    }\n    instance.renderCache = []\n    // this flag forces child components with slot content to update\n    isHmrUpdating = true\n    // #13771 don't update if the job is already disposed\n    if (!(instance.job.flags! & SchedulerJobFlags.DISPOSED)) {\n      instance.update()\n    }\n    isHmrUpdating = false\n  })\n}\n\nfunction reload(id: string, newComp: HMRComponent): void {\n  const record = map.get(id)\n  if (!record) return\n\n  newComp = normalizeClassComponent(newComp)\n  // update initial def (for not-yet-rendered components)\n  updateComponentDef(record.initialDef, newComp)\n\n  // create a snapshot which avoids the set being mutated during updates\n  const instances = [...record.instances]\n\n  for (let i = 0; i < instances.length; i++) {\n    const instance = instances[i]\n    const oldComp = normalizeClassComponent(instance.type as HMRComponent)\n\n    let dirtyInstances = hmrDirtyComponents.get(oldComp)\n    if (!dirtyInstances) {\n      // 1. Update existing comp definition to match new one\n      if (oldComp !== record.initialDef) {\n        updateComponentDef(oldComp, newComp)\n      }\n      // 2. mark definition dirty. This forces the renderer to replace the\n      // component on patch.\n      hmrDirtyComponents.set(oldComp, (dirtyInstances = new Set()))\n    }\n    dirtyInstances.add(instance)\n\n    // 3. invalidate options resolution cache\n    instance.appContext.propsCache.delete(instance.type as any)\n    instance.appContext.emitsCache.delete(instance.type as any)\n    instance.appContext.optionsCache.delete(instance.type as any)\n\n    // 4. actually update\n    if (instance.ceReload) {\n      // custom element\n      dirtyInstances.add(instance)\n      instance.ceReload((newComp as any).styles)\n      dirtyInstances.delete(instance)\n    } else if (instance.parent) {\n      // 4. Force the parent instance to re-render. This will cause all updated\n      // components to be unmounted and re-mounted. Queue the update so that we\n      // don't end up forcing the same parent to re-render multiple times.\n      queueJob(() => {\n        // vite-plugin-vue/issues/599\n        // don't update if the job is already disposed\n        if (!(instance.job.flags! & SchedulerJobFlags.DISPOSED)) {\n          isHmrUpdating = true\n          instance.parent!.update()\n          isHmrUpdating = false\n          // #6930, #11248 avoid infinite recursion\n          dirtyInstances.delete(instance)\n        }\n      })\n    } else if (instance.appContext.reload) {\n      // root instance mounted via createApp() has a reload method\n      instance.appContext.reload()\n    } else if (typeof window !== 'undefined') {\n      // root instance inside tree created via raw render(). Force reload.\n      window.location.reload()\n    } else {\n      console.warn(\n        '[HMR] Root or manually mounted instance modified. Full reload required.',\n      )\n    }\n\n    // update custom element child style\n    if (instance.root.ce && instance !== instance.root) {\n      instance.root.ce._removeChildStyle(oldComp)\n    }\n  }\n\n  // 5. make sure to cleanup dirty hmr components after update\n  queuePostFlushCb(() => {\n    hmrDirtyComponents.clear()\n  })\n}\n\nfunction updateComponentDef(\n  oldComp: ComponentOptions,\n  newComp: ComponentOptions,\n) {\n  extend(oldComp, newComp)\n  for (const key in oldComp) {\n    if (key !== '__file' && !(key in newComp)) {\n      delete oldComp[key]\n    }\n  }\n}\n\nfunction tryWrap(fn: (id: string, arg: any) => any): Function {\n  return (id: string, arg: any) => {\n    try {\n      return fn(id, arg)\n    } catch (e: any) {\n      console.error(e)\n      console.warn(\n        `[HMR] Something went wrong during Vue component hot-reload. ` +\n          `Full reload required.`,\n      )\n    }\n  }\n}\n"
  },
  {
    "path": "packages/runtime-core/src/hydration.ts",
    "content": "import {\n  Fragment,\n  Static,\n  Text,\n  Comment as VComment,\n  type VNode,\n  type VNodeHook,\n  createTextVNode,\n  createVNode,\n  invokeVNodeHook,\n  normalizeVNode,\n} from './vnode'\nimport { flushPostFlushCbs } from './scheduler'\nimport type { ComponentInternalInstance, ComponentOptions } from './component'\nimport { invokeDirectiveHook } from './directives'\nimport { warn } from './warning'\nimport {\n  PatchFlags,\n  ShapeFlags,\n  def,\n  getEscapedCssVarName,\n  includeBooleanAttr,\n  isBooleanAttr,\n  isKnownHtmlAttr,\n  isKnownSvgAttr,\n  isOn,\n  isRenderableAttrValue,\n  isReservedProp,\n  isString,\n  normalizeClass,\n  normalizeCssVarValue,\n  normalizeStyle,\n  stringifyStyle,\n} from '@vue/shared'\nimport { type RendererInternals, needTransition } from './renderer'\nimport { setRef } from './rendererTemplateRef'\nimport {\n  type SuspenseBoundary,\n  type SuspenseImpl,\n  queueEffectWithSuspense,\n} from './components/Suspense'\nimport type { TeleportImpl, TeleportVNode } from './components/Teleport'\nimport { isAsyncWrapper } from './apiAsyncComponent'\nimport { isReactive } from '@vue/reactivity'\nimport { updateHOCHostEl } from './componentRenderUtils'\n\nexport type RootHydrateFunction = (\n  vnode: VNode<Node, Element>,\n  container: (Element | ShadowRoot) & { _vnode?: VNode },\n) => void\n\nexport enum DOMNodeTypes {\n  ELEMENT = 1,\n  TEXT = 3,\n  COMMENT = 8,\n}\n\nlet hasLoggedMismatchError = false\nconst logMismatchError = () => {\n  if (__TEST__ || hasLoggedMismatchError) {\n    return\n  }\n  // this error should show up in production\n  console.error('Hydration completed but contains mismatches.')\n  hasLoggedMismatchError = true\n}\n\nconst isSVGContainer = (container: Element) =>\n  container.namespaceURI!.includes('svg') &&\n  container.tagName !== 'foreignObject'\n\nconst isMathMLContainer = (container: Element) =>\n  container.namespaceURI!.includes('MathML')\n\nconst getContainerType = (\n  container: Element | ShadowRoot,\n): 'svg' | 'mathml' | undefined => {\n  if (container.nodeType !== DOMNodeTypes.ELEMENT) return undefined\n  if (isSVGContainer(container as Element)) return 'svg'\n  if (isMathMLContainer(container as Element)) return 'mathml'\n  return undefined\n}\n\nexport const isComment = (node: Node): node is Comment =>\n  node.nodeType === DOMNodeTypes.COMMENT\n\n// Note: hydration is DOM-specific\n// But we have to place it in core due to tight coupling with core - splitting\n// it out creates a ton of unnecessary complexity.\n// Hydration also depends on some renderer internal logic which needs to be\n// passed in via arguments.\nexport function createHydrationFunctions(\n  rendererInternals: RendererInternals<Node, Element>,\n): [\n  RootHydrateFunction,\n  (\n    node: Node,\n    vnode: VNode,\n    parentComponent: ComponentInternalInstance | null,\n    parentSuspense: SuspenseBoundary | null,\n    slotScopeIds: string[] | null,\n    optimized?: boolean,\n  ) => Node | null,\n] {\n  const {\n    mt: mountComponent,\n    p: patch,\n    o: {\n      patchProp,\n      createText,\n      nextSibling,\n      parentNode,\n      remove,\n      insert,\n      createComment,\n    },\n  } = rendererInternals\n\n  const hydrate: RootHydrateFunction = (vnode, container) => {\n    if (!container.hasChildNodes()) {\n      ;(__DEV__ || __FEATURE_PROD_HYDRATION_MISMATCH_DETAILS__) &&\n        warn(\n          `Attempting to hydrate existing markup but container is empty. ` +\n            `Performing full mount instead.`,\n        )\n      patch(null, vnode, container)\n      flushPostFlushCbs()\n      container._vnode = vnode\n      return\n    }\n\n    hydrateNode(container.firstChild!, vnode, null, null, null)\n    flushPostFlushCbs()\n    container._vnode = vnode\n  }\n\n  const hydrateNode = (\n    node: Node,\n    vnode: VNode,\n    parentComponent: ComponentInternalInstance | null,\n    parentSuspense: SuspenseBoundary | null,\n    slotScopeIds: string[] | null,\n    optimized = false,\n  ): Node | null => {\n    optimized = optimized || !!vnode.dynamicChildren\n    const isFragmentStart = isComment(node) && node.data === '['\n    const onMismatch = () =>\n      handleMismatch(\n        node,\n        vnode,\n        parentComponent,\n        parentSuspense,\n        slotScopeIds,\n        isFragmentStart,\n      )\n\n    const { type, ref, shapeFlag, patchFlag } = vnode\n    let domType = node.nodeType\n    vnode.el = node\n\n    if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {\n      def(node, '__vnode', vnode, true)\n      def(node, '__vueParentComponent', parentComponent, true)\n    }\n\n    if (patchFlag === PatchFlags.BAIL) {\n      optimized = false\n      vnode.dynamicChildren = null\n    }\n\n    let nextNode: Node | null = null\n    switch (type) {\n      case Text:\n        if (domType !== DOMNodeTypes.TEXT) {\n          // #5728 empty text node inside a slot can cause hydration failure\n          // because the server rendered HTML won't contain a text node\n          if (vnode.children === '') {\n            insert((vnode.el = createText('')), parentNode(node)!, node)\n            nextNode = node\n          } else {\n            nextNode = onMismatch()\n          }\n        } else {\n          if ((node as Text).data !== vnode.children) {\n            ;(__DEV__ || __FEATURE_PROD_HYDRATION_MISMATCH_DETAILS__) &&\n              warn(\n                `Hydration text mismatch in`,\n                node.parentNode,\n                `\\n  - rendered on server: ${JSON.stringify(\n                  (node as Text).data,\n                )}` +\n                  `\\n  - expected on client: ${JSON.stringify(vnode.children)}`,\n              )\n            logMismatchError()\n            ;(node as Text).data = vnode.children as string\n          }\n          nextNode = nextSibling(node)\n        }\n        break\n      case VComment:\n        if (isTemplateNode(node)) {\n          nextNode = nextSibling(node)\n          // wrapped <transition appear>\n          // replace <template> node with inner child\n          replaceNode(\n            (vnode.el = node.content.firstChild!),\n            node,\n            parentComponent,\n          )\n        } else if (domType !== DOMNodeTypes.COMMENT || isFragmentStart) {\n          nextNode = onMismatch()\n        } else {\n          nextNode = nextSibling(node)\n        }\n        break\n      case Static:\n        if (isFragmentStart) {\n          // entire template is static but SSRed as a fragment\n          node = nextSibling(node)!\n          domType = node.nodeType\n        }\n        if (domType === DOMNodeTypes.ELEMENT || domType === DOMNodeTypes.TEXT) {\n          // determine anchor, adopt content\n          nextNode = node\n          // if the static vnode has its content stripped during build,\n          // adopt it from the server-rendered HTML.\n          const needToAdoptContent = !(vnode.children as string).length\n          for (let i = 0; i < vnode.staticCount!; i++) {\n            if (needToAdoptContent)\n              vnode.children +=\n                nextNode.nodeType === DOMNodeTypes.ELEMENT\n                  ? (nextNode as Element).outerHTML\n                  : (nextNode as Text).data\n            if (i === vnode.staticCount! - 1) {\n              vnode.anchor = nextNode\n            }\n            nextNode = nextSibling(nextNode)!\n          }\n          return isFragmentStart ? nextSibling(nextNode) : nextNode\n        } else {\n          onMismatch()\n        }\n        break\n      case Fragment:\n        if (!isFragmentStart) {\n          nextNode = onMismatch()\n        } else {\n          nextNode = hydrateFragment(\n            node as Comment,\n            vnode,\n            parentComponent,\n            parentSuspense,\n            slotScopeIds,\n            optimized,\n          )\n        }\n        break\n      default:\n        if (shapeFlag & ShapeFlags.ELEMENT) {\n          if (\n            (domType !== DOMNodeTypes.ELEMENT ||\n              (vnode.type as string).toLowerCase() !==\n                (node as Element).tagName.toLowerCase()) &&\n            !isTemplateNode(node)\n          ) {\n            nextNode = onMismatch()\n          } else {\n            nextNode = hydrateElement(\n              node as Element,\n              vnode,\n              parentComponent,\n              parentSuspense,\n              slotScopeIds,\n              optimized,\n            )\n          }\n        } else if (shapeFlag & ShapeFlags.COMPONENT) {\n          // when setting up the render effect, if the initial vnode already\n          // has .el set, the component will perform hydration instead of mount\n          // on its sub-tree.\n          vnode.slotScopeIds = slotScopeIds\n          const container = parentNode(node)!\n\n          // Locate the next node.\n          if (isFragmentStart) {\n            // If it's a fragment: since components may be async, we cannot rely\n            // on component's rendered output to determine the end of the\n            // fragment. Instead, we do a lookahead to find the end anchor node.\n            nextNode = locateClosingAnchor(node)\n          } else if (isComment(node) && node.data === 'teleport start') {\n            // #4293 #6152\n            // If a teleport is at component root, look ahead for teleport end.\n            nextNode = locateClosingAnchor(node, node.data, 'teleport end')\n          } else {\n            nextNode = nextSibling(node)\n          }\n\n          mountComponent(\n            vnode,\n            container,\n            null,\n            parentComponent,\n            parentSuspense,\n            getContainerType(container),\n            optimized,\n          )\n\n          // #3787\n          // if component is async, it may get moved / unmounted before its\n          // inner component is loaded, so we need to give it a placeholder\n          // vnode that matches its adopted DOM.\n          if (\n            isAsyncWrapper(vnode) &&\n            !(vnode.type as ComponentOptions).__asyncResolved\n          ) {\n            let subTree\n            if (isFragmentStart) {\n              subTree = createVNode(Fragment)\n              subTree.anchor = nextNode\n                ? nextNode.previousSibling\n                : container.lastChild\n            } else {\n              subTree =\n                node.nodeType === 3 ? createTextVNode('') : createVNode('div')\n            }\n            subTree.el = node\n            vnode.component!.subTree = subTree\n          }\n        } else if (shapeFlag & ShapeFlags.TELEPORT) {\n          if (domType !== DOMNodeTypes.COMMENT) {\n            nextNode = onMismatch()\n          } else {\n            nextNode = (vnode.type as typeof TeleportImpl).hydrate(\n              node,\n              vnode as TeleportVNode,\n              parentComponent,\n              parentSuspense,\n              slotScopeIds,\n              optimized,\n              rendererInternals,\n              hydrateChildren,\n            )\n          }\n        } else if (__FEATURE_SUSPENSE__ && shapeFlag & ShapeFlags.SUSPENSE) {\n          nextNode = (vnode.type as typeof SuspenseImpl).hydrate(\n            node,\n            vnode,\n            parentComponent,\n            parentSuspense,\n            getContainerType(parentNode(node)!),\n            slotScopeIds,\n            optimized,\n            rendererInternals,\n            hydrateNode,\n          )\n        } else if (__DEV__ || __FEATURE_PROD_HYDRATION_MISMATCH_DETAILS__) {\n          warn('Invalid HostVNode type:', type, `(${typeof type})`)\n        }\n    }\n\n    if (ref != null) {\n      setRef(ref, null, parentSuspense, vnode)\n    }\n\n    return nextNode\n  }\n\n  const hydrateElement = (\n    el: Element,\n    vnode: VNode,\n    parentComponent: ComponentInternalInstance | null,\n    parentSuspense: SuspenseBoundary | null,\n    slotScopeIds: string[] | null,\n    optimized: boolean,\n  ) => {\n    optimized = optimized || !!vnode.dynamicChildren\n    const { type, props, patchFlag, shapeFlag, dirs, transition } = vnode\n    // #4006 for form elements with non-string v-model value bindings\n    // e.g. <option :value=\"obj\">, <input type=\"checkbox\" :true-value=\"1\">\n    // #7476 <input indeterminate>\n    const forcePatch = type === 'input' || type === 'option'\n    // skip props & children if this is hoisted static nodes\n    // #5405 in dev, always hydrate children for HMR\n    if (__DEV__ || forcePatch || patchFlag !== PatchFlags.CACHED) {\n      if (dirs) {\n        invokeDirectiveHook(vnode, null, parentComponent, 'created')\n      }\n\n      // handle appear transition\n      let needCallTransitionHooks = false\n      if (isTemplateNode(el)) {\n        needCallTransitionHooks =\n          needTransition(\n            null, // no need check parentSuspense in hydration\n            transition,\n          ) &&\n          parentComponent &&\n          parentComponent.vnode.props &&\n          parentComponent.vnode.props.appear\n\n        const content = (el as HTMLTemplateElement).content\n          .firstChild as Element & { $cls?: string }\n\n        if (needCallTransitionHooks) {\n          const cls = content.getAttribute('class')\n          if (cls) content.$cls = cls\n          transition!.beforeEnter(content)\n        }\n\n        // replace <template> node with inner children\n        replaceNode(content, el, parentComponent)\n        vnode.el = el = content\n      }\n\n      // children\n      if (\n        shapeFlag & ShapeFlags.ARRAY_CHILDREN &&\n        // skip if element has innerHTML / textContent\n        !(props && (props.innerHTML || props.textContent))\n      ) {\n        let next = hydrateChildren(\n          el.firstChild,\n          vnode,\n          el,\n          parentComponent,\n          parentSuspense,\n          slotScopeIds,\n          optimized,\n        )\n        let hasWarned = false\n        while (next) {\n          if (!isMismatchAllowed(el, MismatchTypes.CHILDREN)) {\n            if (\n              (__DEV__ || __FEATURE_PROD_HYDRATION_MISMATCH_DETAILS__) &&\n              !hasWarned\n            ) {\n              warn(\n                `Hydration children mismatch on`,\n                el,\n                `\\nServer rendered element contains more child nodes than client vdom.`,\n              )\n              hasWarned = true\n            }\n            logMismatchError()\n          }\n\n          // The SSRed DOM contains more nodes than it should. Remove them.\n          const cur = next\n          next = next.nextSibling\n          remove(cur)\n        }\n      } else if (shapeFlag & ShapeFlags.TEXT_CHILDREN) {\n        // #11873 the HTML parser will \"eat\" the first newline when parsing\n        // <pre> and <textarea>, so if the client value starts with a newline,\n        // we need to remove it before comparing\n        let clientText = vnode.children as string\n        if (\n          clientText[0] === '\\n' &&\n          (el.tagName === 'PRE' || el.tagName === 'TEXTAREA')\n        ) {\n          clientText = clientText.slice(1)\n        }\n        const { textContent } = el\n        if (\n          textContent !== clientText &&\n          // innerHTML normalize \\r\\n or \\r into a single \\n in the DOM\n          textContent !== clientText.replace(/\\r\\n|\\r/g, '\\n')\n        ) {\n          if (!isMismatchAllowed(el, MismatchTypes.TEXT)) {\n            ;(__DEV__ || __FEATURE_PROD_HYDRATION_MISMATCH_DETAILS__) &&\n              warn(\n                `Hydration text content mismatch on`,\n                el,\n                `\\n  - rendered on server: ${textContent}` +\n                  `\\n  - expected on client: ${clientText}`,\n              )\n            logMismatchError()\n          }\n          el.textContent = vnode.children as string\n        }\n      }\n\n      // props\n      if (props) {\n        if (\n          __DEV__ ||\n          __FEATURE_PROD_HYDRATION_MISMATCH_DETAILS__ ||\n          forcePatch ||\n          !optimized ||\n          patchFlag & (PatchFlags.FULL_PROPS | PatchFlags.NEED_HYDRATION)\n        ) {\n          const isCustomElement = el.tagName.includes('-')\n          for (const key in props) {\n            // check hydration mismatch\n            if (\n              (__DEV__ || __FEATURE_PROD_HYDRATION_MISMATCH_DETAILS__) &&\n              // #11189 skip if this node has directives that have created hooks\n              // as it could have mutated the DOM in any possible way\n              !(dirs && dirs.some(d => d.dir.created)) &&\n              propHasMismatch(el, key, props[key], vnode, parentComponent)\n            ) {\n              logMismatchError()\n            }\n            if (\n              (forcePatch &&\n                (key.endsWith('value') || key === 'indeterminate')) ||\n              (isOn(key) && !isReservedProp(key)) ||\n              // force hydrate v-bind with .prop modifiers\n              key[0] === '.' ||\n              (isCustomElement && !isReservedProp(key))\n            ) {\n              patchProp(el, key, null, props[key], undefined, parentComponent)\n            }\n          }\n        } else if (props.onClick) {\n          // Fast path for click listeners (which is most often) to avoid\n          // iterating through props.\n          patchProp(\n            el,\n            'onClick',\n            null,\n            props.onClick,\n            undefined,\n            parentComponent,\n          )\n        } else if (patchFlag & PatchFlags.STYLE && isReactive(props.style)) {\n          // #11372: object style values are iterated during patch instead of\n          // render/normalization phase, but style patch is skipped during\n          // hydration, so we need to force iterate the object to track deps\n          for (const key in props.style) props.style[key]\n        }\n      }\n\n      // vnode / directive hooks\n      let vnodeHooks: VNodeHook | null | undefined\n      if ((vnodeHooks = props && props.onVnodeBeforeMount)) {\n        invokeVNodeHook(vnodeHooks, parentComponent, vnode)\n      }\n      if (dirs) {\n        invokeDirectiveHook(vnode, null, parentComponent, 'beforeMount')\n      }\n      if (\n        (vnodeHooks = props && props.onVnodeMounted) ||\n        dirs ||\n        needCallTransitionHooks\n      ) {\n        queueEffectWithSuspense(() => {\n          vnodeHooks && invokeVNodeHook(vnodeHooks, parentComponent, vnode)\n          needCallTransitionHooks && transition!.enter(el)\n          dirs && invokeDirectiveHook(vnode, null, parentComponent, 'mounted')\n        }, parentSuspense)\n      }\n    }\n\n    return el.nextSibling\n  }\n\n  const hydrateChildren = (\n    node: Node | null,\n    parentVNode: VNode,\n    container: Element,\n    parentComponent: ComponentInternalInstance | null,\n    parentSuspense: SuspenseBoundary | null,\n    slotScopeIds: string[] | null,\n    optimized: boolean,\n  ): Node | null => {\n    optimized = optimized || !!parentVNode.dynamicChildren\n    const children = parentVNode.children as VNode[]\n    const l = children.length\n    let hasWarned = false\n    for (let i = 0; i < l; i++) {\n      const vnode = optimized\n        ? children[i]\n        : (children[i] = normalizeVNode(children[i]))\n      const isText = vnode.type === Text\n      if (node) {\n        if (isText && !optimized) {\n          // #7285 possible consecutive text vnodes from manual render fns or\n          // JSX-compiled fns, but on the client the browser parses only 1 text\n          // node.\n          // look ahead for next possible text vnode\n          if (i + 1 < l && normalizeVNode(children[i + 1]).type === Text) {\n            // create an extra TextNode on the client for the next vnode to\n            // adopt\n            insert(\n              createText(\n                (node as Text).data.slice((vnode.children as string).length),\n              ),\n              container,\n              nextSibling(node),\n            )\n            ;(node as Text).data = vnode.children as string\n          }\n        }\n        node = hydrateNode(\n          node,\n          vnode,\n          parentComponent,\n          parentSuspense,\n          slotScopeIds,\n          optimized,\n        )\n      } else if (isText && !vnode.children) {\n        // #7215 create a TextNode for empty text node\n        // because server rendered HTML won't contain a text node\n        insert((vnode.el = createText('')), container)\n      } else {\n        if (!isMismatchAllowed(container, MismatchTypes.CHILDREN)) {\n          if (\n            (__DEV__ || __FEATURE_PROD_HYDRATION_MISMATCH_DETAILS__) &&\n            !hasWarned\n          ) {\n            warn(\n              `Hydration children mismatch on`,\n              container,\n              `\\nServer rendered element contains fewer child nodes than client vdom.`,\n            )\n            hasWarned = true\n          }\n          logMismatchError()\n        }\n\n        // the SSRed DOM didn't contain enough nodes. Mount the missing ones.\n        patch(\n          null,\n          vnode,\n          container,\n          null,\n          parentComponent,\n          parentSuspense,\n          getContainerType(container),\n          slotScopeIds,\n        )\n      }\n    }\n    return node\n  }\n\n  const hydrateFragment = (\n    node: Comment,\n    vnode: VNode,\n    parentComponent: ComponentInternalInstance | null,\n    parentSuspense: SuspenseBoundary | null,\n    slotScopeIds: string[] | null,\n    optimized: boolean,\n  ) => {\n    const { slotScopeIds: fragmentSlotScopeIds } = vnode\n    if (fragmentSlotScopeIds) {\n      slotScopeIds = slotScopeIds\n        ? slotScopeIds.concat(fragmentSlotScopeIds)\n        : fragmentSlotScopeIds\n    }\n\n    const container = parentNode(node)!\n    const next = hydrateChildren(\n      nextSibling(node)!,\n      vnode,\n      container,\n      parentComponent,\n      parentSuspense,\n      slotScopeIds,\n      optimized,\n    )\n    if (next && isComment(next) && next.data === ']') {\n      return nextSibling((vnode.anchor = next))\n    } else {\n      // fragment didn't hydrate successfully, since we didn't get a end anchor\n      // back. This should have led to node/children mismatch warnings.\n      logMismatchError()\n\n      // since the anchor is missing, we need to create one and insert it\n      insert((vnode.anchor = createComment(`]`)), container, next)\n      return next\n    }\n  }\n\n  const handleMismatch = (\n    node: Node,\n    vnode: VNode,\n    parentComponent: ComponentInternalInstance | null,\n    parentSuspense: SuspenseBoundary | null,\n    slotScopeIds: string[] | null,\n    isFragment: boolean,\n  ): Node | null => {\n    if (!isMismatchAllowed(node.parentElement!, MismatchTypes.CHILDREN)) {\n      ;(__DEV__ || __FEATURE_PROD_HYDRATION_MISMATCH_DETAILS__) &&\n        warn(\n          `Hydration node mismatch:\\n- rendered on server:`,\n          node,\n          node.nodeType === DOMNodeTypes.TEXT\n            ? `(text)`\n            : isComment(node) && node.data === '['\n              ? `(start of fragment)`\n              : ``,\n          `\\n- expected on client:`,\n          vnode.type,\n        )\n      logMismatchError()\n    }\n\n    vnode.el = null\n\n    if (isFragment) {\n      // remove excessive fragment nodes\n      const end = locateClosingAnchor(node)\n      while (true) {\n        const next = nextSibling(node)\n        if (next && next !== end) {\n          remove(next)\n        } else {\n          break\n        }\n      }\n    }\n\n    const next = nextSibling(node)\n    const container = parentNode(node)!\n    remove(node)\n\n    patch(\n      null,\n      vnode,\n      container,\n      next,\n      parentComponent,\n      parentSuspense,\n      getContainerType(container),\n      slotScopeIds,\n    )\n    // the component vnode's el should be updated when a mismatch occurs.\n    if (parentComponent) {\n      parentComponent.vnode.el = vnode.el\n      updateHOCHostEl(parentComponent, vnode.el)\n    }\n    return next\n  }\n\n  // looks ahead for a start and closing comment node\n  const locateClosingAnchor = (\n    node: Node | null,\n    open = '[',\n    close = ']',\n  ): Node | null => {\n    let match = 0\n    while (node) {\n      node = nextSibling(node)\n      if (node && isComment(node)) {\n        if (node.data === open) match++\n        if (node.data === close) {\n          if (match === 0) {\n            return nextSibling(node)\n          } else {\n            match--\n          }\n        }\n      }\n    }\n    return node\n  }\n\n  const replaceNode = (\n    newNode: Node,\n    oldNode: Node,\n    parentComponent: ComponentInternalInstance | null,\n  ): void => {\n    // replace node\n    const parentNode = oldNode.parentNode\n    if (parentNode) {\n      parentNode.replaceChild(newNode, oldNode)\n    }\n\n    // update vnode\n    let parent = parentComponent\n    while (parent) {\n      if (parent.vnode.el === oldNode) {\n        parent.vnode.el = parent.subTree.el = newNode\n      }\n      parent = parent.parent\n    }\n  }\n\n  const isTemplateNode = (node: Node): node is HTMLTemplateElement => {\n    return (\n      node.nodeType === DOMNodeTypes.ELEMENT &&\n      (node as Element).tagName === 'TEMPLATE'\n    )\n  }\n\n  return [hydrate, hydrateNode]\n}\n\n/**\n * Dev only\n */\nfunction propHasMismatch(\n  el: Element & { $cls?: string },\n  key: string,\n  clientValue: any,\n  vnode: VNode,\n  instance: ComponentInternalInstance | null,\n): boolean {\n  let mismatchType: MismatchTypes | undefined\n  let mismatchKey: string | undefined\n  let actual: string | boolean | null | undefined\n  let expected: string | boolean | null | undefined\n  if (key === 'class') {\n    // classes might be in different order, but that doesn't affect cascade\n    // so we just need to check if the class lists contain the same classes.\n    if (el.$cls) {\n      actual = el.$cls\n      delete el.$cls\n    } else {\n      actual = el.getAttribute('class')\n    }\n    expected = normalizeClass(clientValue)\n    if (!isSetEqual(toClassSet(actual || ''), toClassSet(expected))) {\n      mismatchType = MismatchTypes.CLASS\n      mismatchKey = `class`\n    }\n  } else if (key === 'style') {\n    // style might be in different order, but that doesn't affect cascade\n    actual = el.getAttribute('style') || ''\n    expected = isString(clientValue)\n      ? clientValue\n      : stringifyStyle(normalizeStyle(clientValue))\n    const actualMap = toStyleMap(actual)\n    const expectedMap = toStyleMap(expected)\n    // If `v-show=false`, `display: 'none'` should be added to expected\n    if (vnode.dirs) {\n      for (const { dir, value } of vnode.dirs) {\n        // @ts-expect-error only vShow has this internal name\n        if (dir.name === 'show' && !value) {\n          expectedMap.set('display', 'none')\n        }\n      }\n    }\n\n    if (instance) {\n      resolveCssVars(instance, vnode, expectedMap)\n    }\n\n    if (!isMapEqual(actualMap, expectedMap)) {\n      mismatchType = MismatchTypes.STYLE\n      mismatchKey = 'style'\n    }\n  } else if (\n    (el instanceof SVGElement && isKnownSvgAttr(key)) ||\n    (el instanceof HTMLElement && (isBooleanAttr(key) || isKnownHtmlAttr(key)))\n  ) {\n    if (isBooleanAttr(key)) {\n      actual = el.hasAttribute(key)\n      expected = includeBooleanAttr(clientValue)\n    } else if (clientValue == null) {\n      actual = el.hasAttribute(key)\n      expected = false\n    } else {\n      if (el.hasAttribute(key)) {\n        actual = el.getAttribute(key)\n      } else if (key === 'value' && el.tagName === 'TEXTAREA') {\n        // #10000 textarea.value can't be retrieved by `hasAttribute`\n        actual = (el as HTMLTextAreaElement).value\n      } else {\n        actual = false\n      }\n      expected = isRenderableAttrValue(clientValue)\n        ? String(clientValue)\n        : false\n    }\n    if (actual !== expected) {\n      mismatchType = MismatchTypes.ATTRIBUTE\n      mismatchKey = key\n    }\n  }\n\n  if (mismatchType != null && !isMismatchAllowed(el, mismatchType)) {\n    const format = (v: any) =>\n      v === false ? `(not rendered)` : `${mismatchKey}=\"${v}\"`\n    const preSegment = `Hydration ${MismatchTypeString[mismatchType]} mismatch on`\n    const postSegment =\n      `\\n  - rendered on server: ${format(actual)}` +\n      `\\n  - expected on client: ${format(expected)}` +\n      `\\n  Note: this mismatch is check-only. The DOM will not be rectified ` +\n      `in production due to performance overhead.` +\n      `\\n  You should fix the source of the mismatch.`\n    if (__TEST__) {\n      // during tests, log the full message in one single string for easier\n      // debugging.\n      warn(`${preSegment} ${el.tagName}${postSegment}`)\n    } else {\n      warn(preSegment, el, postSegment)\n    }\n    return true\n  }\n  return false\n}\n\nfunction toClassSet(str: string): Set<string> {\n  return new Set(str.trim().split(/\\s+/))\n}\n\nfunction isSetEqual(a: Set<string>, b: Set<string>): boolean {\n  if (a.size !== b.size) {\n    return false\n  }\n  for (const s of a) {\n    if (!b.has(s)) {\n      return false\n    }\n  }\n  return true\n}\n\nfunction toStyleMap(str: string): Map<string, string> {\n  const styleMap: Map<string, string> = new Map()\n  for (const item of str.split(';')) {\n    let [key, value] = item.split(':')\n    key = key.trim()\n    value = value && value.trim()\n    if (key && value) {\n      styleMap.set(key, value)\n    }\n  }\n  return styleMap\n}\n\nfunction isMapEqual(a: Map<string, string>, b: Map<string, string>): boolean {\n  if (a.size !== b.size) {\n    return false\n  }\n  for (const [key, value] of a) {\n    if (value !== b.get(key)) {\n      return false\n    }\n  }\n  return true\n}\n\nfunction resolveCssVars(\n  instance: ComponentInternalInstance,\n  vnode: VNode,\n  expectedMap: Map<string, string>,\n) {\n  const root = instance.subTree\n  if (\n    instance.getCssVars &&\n    (vnode === root ||\n      (root &&\n        root.type === Fragment &&\n        (root.children as VNode[]).includes(vnode)))\n  ) {\n    const cssVars = instance.getCssVars()\n    for (const key in cssVars) {\n      const value = normalizeCssVarValue(cssVars[key])\n      expectedMap.set(`--${getEscapedCssVarName(key, false)}`, value)\n    }\n  }\n  if (vnode === root && instance.parent) {\n    resolveCssVars(instance.parent, instance.vnode, expectedMap)\n  }\n}\n\nconst allowMismatchAttr = 'data-allow-mismatch'\n\nenum MismatchTypes {\n  TEXT = 0,\n  CHILDREN = 1,\n  CLASS = 2,\n  STYLE = 3,\n  ATTRIBUTE = 4,\n}\n\nconst MismatchTypeString: Record<MismatchTypes, string> = {\n  [MismatchTypes.TEXT]: 'text',\n  [MismatchTypes.CHILDREN]: 'children',\n  [MismatchTypes.CLASS]: 'class',\n  [MismatchTypes.STYLE]: 'style',\n  [MismatchTypes.ATTRIBUTE]: 'attribute',\n} as const\n\nfunction isMismatchAllowed(\n  el: Element | null,\n  allowedType: MismatchTypes,\n): boolean {\n  if (\n    allowedType === MismatchTypes.TEXT ||\n    allowedType === MismatchTypes.CHILDREN\n  ) {\n    while (el && !el.hasAttribute(allowMismatchAttr)) {\n      el = el.parentElement\n    }\n  }\n  const allowedAttr = el && el.getAttribute(allowMismatchAttr)\n  if (allowedAttr == null) {\n    return false\n  } else if (allowedAttr === '') {\n    return true\n  } else {\n    const list = allowedAttr.split(',')\n    // text is a subset of children\n    if (allowedType === MismatchTypes.TEXT && list.includes('children')) {\n      return true\n    }\n    return list.includes(MismatchTypeString[allowedType])\n  }\n}\n"
  },
  {
    "path": "packages/runtime-core/src/hydrationStrategies.ts",
    "content": "import { getGlobalThis, isString } from '@vue/shared'\nimport { DOMNodeTypes, isComment } from './hydration'\n\n// Polyfills for Safari support\n// see https://caniuse.com/requestidlecallback\nconst requestIdleCallback: Window['requestIdleCallback'] =\n  getGlobalThis().requestIdleCallback || (cb => setTimeout(cb, 1))\nconst cancelIdleCallback: Window['cancelIdleCallback'] =\n  getGlobalThis().cancelIdleCallback || (id => clearTimeout(id))\n\n/**\n * A lazy hydration strategy for async components.\n * @param hydrate - call this to perform the actual hydration.\n * @param forEachElement - iterate through the root elements of the component's\n *                         non-hydrated DOM, accounting for possible fragments.\n * @returns a teardown function to be called if the async component is unmounted\n *          before it is hydrated. This can be used to e.g. remove DOM event\n *          listeners.\n */\nexport type HydrationStrategy = (\n  hydrate: () => void,\n  forEachElement: (cb: (el: Element) => any) => void,\n) => (() => void) | void\n\nexport type HydrationStrategyFactory<Options> = (\n  options?: Options,\n) => HydrationStrategy\n\nexport const hydrateOnIdle: HydrationStrategyFactory<number> =\n  (timeout = 10000) =>\n  hydrate => {\n    const id = requestIdleCallback(hydrate, { timeout })\n    return () => cancelIdleCallback(id)\n  }\n\nfunction elementIsVisibleInViewport(el: Element) {\n  const { top, left, bottom, right } = el.getBoundingClientRect()\n  // eslint-disable-next-line no-restricted-globals\n  const { innerHeight, innerWidth } = window\n  return (\n    ((top > 0 && top < innerHeight) || (bottom > 0 && bottom < innerHeight)) &&\n    ((left > 0 && left < innerWidth) || (right > 0 && right < innerWidth))\n  )\n}\n\nexport const hydrateOnVisible: HydrationStrategyFactory<\n  IntersectionObserverInit\n> = opts => (hydrate, forEach) => {\n  const ob = new IntersectionObserver(entries => {\n    for (const e of entries) {\n      if (!e.isIntersecting) continue\n      ob.disconnect()\n      hydrate()\n      break\n    }\n  }, opts)\n  forEach(el => {\n    if (!(el instanceof Element)) return\n    if (elementIsVisibleInViewport(el)) {\n      hydrate()\n      ob.disconnect()\n      return false\n    }\n    ob.observe(el)\n  })\n  return () => ob.disconnect()\n}\n\nexport const hydrateOnMediaQuery: HydrationStrategyFactory<string> =\n  query => hydrate => {\n    if (query) {\n      const mql = matchMedia(query)\n      if (mql.matches) {\n        hydrate()\n      } else {\n        mql.addEventListener('change', hydrate, { once: true })\n        return () => mql.removeEventListener('change', hydrate)\n      }\n    }\n  }\n\nexport const hydrateOnInteraction: HydrationStrategyFactory<\n  keyof HTMLElementEventMap | Array<keyof HTMLElementEventMap>\n> =\n  (interactions = []) =>\n  (hydrate, forEach) => {\n    if (isString(interactions)) interactions = [interactions]\n    let hasHydrated = false\n    const doHydrate = (e: Event) => {\n      if (!hasHydrated) {\n        hasHydrated = true\n        teardown()\n        hydrate()\n        // replay event\n        e.target!.dispatchEvent(new (e.constructor as any)(e.type, e))\n      }\n    }\n    const teardown = () => {\n      forEach(el => {\n        for (const i of interactions) {\n          el.removeEventListener(i, doHydrate)\n        }\n      })\n    }\n    forEach(el => {\n      for (const i of interactions) {\n        el.addEventListener(i, doHydrate, { once: true })\n      }\n    })\n    return teardown\n  }\n\nexport function forEachElement(\n  node: Node,\n  cb: (el: Element) => void | false,\n): void {\n  // fragment\n  if (isComment(node) && node.data === '[') {\n    let depth = 1\n    let next = node.nextSibling\n    while (next) {\n      if (next.nodeType === DOMNodeTypes.ELEMENT) {\n        const result = cb(next as Element)\n        if (result === false) {\n          break\n        }\n      } else if (isComment(next)) {\n        if (next.data === ']') {\n          if (--depth === 0) break\n        } else if (next.data === '[') {\n          depth++\n        }\n      }\n      next = next.nextSibling\n    }\n  } else {\n    cb(node as Element)\n  }\n}\n"
  },
  {
    "path": "packages/runtime-core/src/index.ts",
    "content": "// Core API ------------------------------------------------------------------\n\nexport const version: string = __VERSION__\nexport {\n  // core\n  reactive,\n  ref,\n  readonly,\n  // utilities\n  unref,\n  proxyRefs,\n  isRef,\n  toRef,\n  toValue,\n  toRefs,\n  isProxy,\n  isReactive,\n  isReadonly,\n  isShallow,\n  // advanced\n  customRef,\n  triggerRef,\n  shallowRef,\n  shallowReactive,\n  shallowReadonly,\n  markRaw,\n  toRaw,\n  // effect\n  effect,\n  stop,\n  getCurrentWatcher,\n  onWatcherCleanup,\n  ReactiveEffect,\n  // effect scope\n  effectScope,\n  EffectScope,\n  getCurrentScope,\n  onScopeDispose,\n} from '@vue/reactivity'\nexport { computed } from './apiComputed'\nexport {\n  watch,\n  watchEffect,\n  watchPostEffect,\n  watchSyncEffect,\n} from './apiWatch'\nexport {\n  onBeforeMount,\n  onMounted,\n  onBeforeUpdate,\n  onUpdated,\n  onBeforeUnmount,\n  onUnmounted,\n  onActivated,\n  onDeactivated,\n  onRenderTracked,\n  onRenderTriggered,\n  onErrorCaptured,\n  onServerPrefetch,\n} from './apiLifecycle'\nexport { provide, inject, hasInjectionContext } from './apiInject'\nexport { nextTick } from './scheduler'\nexport { defineComponent } from './apiDefineComponent'\nexport { defineAsyncComponent } from './apiAsyncComponent'\nexport { useAttrs, useSlots } from './apiSetupHelpers'\nexport { useModel } from './helpers/useModel'\nexport { useTemplateRef, type TemplateRef } from './helpers/useTemplateRef'\nexport { useId } from './helpers/useId'\nexport {\n  hydrateOnIdle,\n  hydrateOnVisible,\n  hydrateOnMediaQuery,\n  hydrateOnInteraction,\n} from './hydrationStrategies'\n\n// <script setup> API ----------------------------------------------------------\n\nexport {\n  // macros runtime, for typing and warnings only\n  defineProps,\n  defineEmits,\n  defineExpose,\n  defineOptions,\n  defineSlots,\n  defineModel,\n  withDefaults,\n  type DefineProps,\n  type ModelRef,\n  type ComponentTypeEmits,\n} from './apiSetupHelpers'\n\n/**\n * @internal\n */\nexport {\n  mergeDefaults,\n  mergeModels,\n  createPropsRestProxy,\n  withAsyncContext,\n} from './apiSetupHelpers'\n\n// Advanced API ----------------------------------------------------------------\n\n// For getting a hold of the internal instance in setup() - useful for advanced\n// plugins\nexport { getCurrentInstance } from './component'\n\n// For raw render function users\nexport { h } from './h'\n// Advanced render function utilities\nexport { createVNode, cloneVNode, mergeProps, isVNode } from './vnode'\n// VNode types\nexport { Fragment, Text, Comment, Static, type VNodeRef } from './vnode'\n// Built-in components\nexport { Teleport, type TeleportProps } from './components/Teleport'\nexport { Suspense, type SuspenseProps } from './components/Suspense'\nexport { KeepAlive, type KeepAliveProps } from './components/KeepAlive'\nexport {\n  BaseTransition,\n  BaseTransitionPropsValidators,\n  type BaseTransitionProps,\n} from './components/BaseTransition'\n// For using custom directives\nexport { withDirectives } from './directives'\n// SSR context\nexport { useSSRContext, ssrContextKey } from './helpers/useSsrContext'\n\n// Custom Renderer API ---------------------------------------------------------\n\nexport { createRenderer, createHydrationRenderer } from './renderer'\nexport { queuePostFlushCb } from './scheduler'\nimport { warn as _warn } from './warning'\nexport const warn = (__DEV__ ? _warn : NOOP) as typeof _warn\n\n/** @internal */\nexport { assertNumber } from './warning'\nexport {\n  handleError,\n  callWithErrorHandling,\n  callWithAsyncErrorHandling,\n  ErrorCodes,\n} from './errorHandling'\nexport {\n  resolveComponent,\n  resolveDirective,\n  resolveDynamicComponent,\n} from './helpers/resolveAssets'\n// For integration with runtime compiler\nexport { registerRuntimeCompiler, isRuntimeOnly } from './component'\nexport {\n  useTransitionState,\n  resolveTransitionHooks,\n  setTransitionHooks,\n  getTransitionRawChildren,\n} from './components/BaseTransition'\nexport { initCustomFormatter } from './customFormatter'\n\nimport { ErrorTypeStrings as _ErrorTypeStrings } from './errorHandling'\n/**\n * Runtime error messages. Only exposed in dev or esm builds.\n * @internal\n */\nexport const ErrorTypeStrings = (\n  __ESM_BUNDLER__ || __CJS__ || __DEV__ ? _ErrorTypeStrings : null\n) as typeof _ErrorTypeStrings\n\n// For devtools\nimport {\n  type DevtoolsHook,\n  devtools as _devtools,\n  setDevtoolsHook as _setDevtoolsHook,\n} from './devtools'\n\nexport const devtools = (\n  __DEV__ || __ESM_BUNDLER__ ? _devtools : undefined\n) as DevtoolsHook\nexport const setDevtoolsHook = (\n  __DEV__ || __ESM_BUNDLER__ ? _setDevtoolsHook : NOOP\n) as typeof _setDevtoolsHook\n\n// Types -----------------------------------------------------------------------\n\nimport type { VNode } from './vnode'\nimport type { ComponentInternalInstance } from './component'\n\n// Augment Ref unwrap bail types.\ndeclare module '@vue/reactivity' {\n  export interface RefUnwrapBailTypes {\n    runtimeCoreBailTypes:\n      | VNode\n      | {\n          // directly bailing on ComponentPublicInstance results in recursion\n          // so we use this as a bail hint\n          $: ComponentInternalInstance\n        }\n  }\n}\n\nexport { TrackOpTypes, TriggerOpTypes } from '@vue/reactivity'\nexport type {\n  Ref,\n  MaybeRef,\n  MaybeRefOrGetter,\n  ToRef,\n  ToRefs,\n  UnwrapRef,\n  ShallowRef,\n  ShallowUnwrapRef,\n  CustomRefFactory,\n  ReactiveFlags,\n  DeepReadonly,\n  ShallowReactive,\n  UnwrapNestedRefs,\n  ComputedRef,\n  WritableComputedRef,\n  WritableComputedOptions,\n  ComputedGetter,\n  ComputedSetter,\n  ReactiveEffectRunner,\n  ReactiveEffectOptions,\n  EffectScheduler,\n  DebuggerOptions,\n  DebuggerEvent,\n  DebuggerEventExtraInfo,\n  Raw,\n  Reactive,\n} from '@vue/reactivity'\nexport type {\n  MultiWatchSources,\n  WatchEffect,\n  WatchOptions,\n  WatchEffectOptions as WatchOptionsBase,\n  WatchCallback,\n  WatchSource,\n  WatchHandle,\n  WatchStopHandle,\n} from './apiWatch'\nexport type { InjectionKey } from './apiInject'\nexport type {\n  App,\n  AppConfig,\n  AppContext,\n  Plugin,\n  ObjectPlugin,\n  FunctionPlugin,\n  CreateAppFunction,\n  OptionMergeFunction,\n} from './apiCreateApp'\nexport type {\n  VNode,\n  VNodeChild,\n  VNodeTypes,\n  VNodeProps,\n  VNodeArrayChildren,\n  VNodeNormalizedChildren,\n} from './vnode'\nexport type {\n  Component,\n  ConcreteComponent,\n  FunctionalComponent,\n  ComponentInternalInstance,\n  Attrs,\n  SetupContext,\n  AllowedAttrs,\n  ComponentCustomProps,\n  AllowedComponentProps,\n  GlobalComponents,\n  GlobalDirectives,\n  ComponentInstance,\n  ComponentCustomElementInterface,\n} from './component'\nexport type {\n  DefineComponent,\n  DefineSetupFnComponent,\n  PublicProps,\n} from './apiDefineComponent'\nexport type {\n  ComponentOptions,\n  ComponentOptionsMixin,\n  ComponentCustomOptions,\n  ComponentOptionsBase,\n  ComponentProvideOptions,\n  RenderFunction,\n  MethodOptions,\n  ComputedOptions,\n  RuntimeCompilerOptions,\n  ComponentInjectOptions,\n  // deprecated\n  ComponentOptionsWithoutProps,\n  ComponentOptionsWithArrayProps,\n  ComponentOptionsWithObjectProps,\n} from './componentOptions'\nexport type {\n  EmitsOptions,\n  ObjectEmitsOptions,\n  EmitsToProps,\n  ShortEmitsToObject,\n  EmitFn,\n} from './componentEmits'\nexport type {\n  ComponentPublicInstance,\n  ComponentCustomProperties,\n  CreateComponentPublicInstance,\n  CreateComponentPublicInstanceWithMixins,\n} from './componentPublicInstance'\nexport type {\n  Renderer,\n  RendererNode,\n  RendererElement,\n  HydrationRenderer,\n  RendererOptions,\n  RootRenderFunction,\n  ElementNamespace,\n} from './renderer'\nexport type { RootHydrateFunction } from './hydration'\nexport type { Slot, Slots, SlotsType } from './componentSlots'\nexport type {\n  Prop,\n  PropType,\n  ComponentPropsOptions,\n  ComponentObjectPropsOptions,\n  ExtractPropTypes,\n  ExtractPublicPropTypes,\n  ExtractDefaultPropTypes,\n} from './componentProps'\nexport type {\n  Directive,\n  DirectiveBinding,\n  DirectiveHook,\n  ObjectDirective,\n  FunctionDirective,\n  DirectiveModifiers,\n  DirectiveArguments,\n} from './directives'\nexport type { SuspenseBoundary } from './components/Suspense'\nexport type {\n  TransitionState,\n  TransitionHooks,\n} from './components/BaseTransition'\nexport type {\n  AsyncComponentOptions,\n  AsyncComponentLoader,\n} from './apiAsyncComponent'\nexport type {\n  HydrationStrategy,\n  HydrationStrategyFactory,\n} from './hydrationStrategies'\nexport type { HMRRuntime } from './hmr'\n\n// Internal API ----------------------------------------------------------------\n\n// **IMPORTANT** Internal APIs may change without notice between versions and\n// user code should avoid relying on them.\n\n// For compiler generated code\n// should sync with '@vue/compiler-core/src/runtimeHelpers.ts'\nexport {\n  withCtx,\n  pushScopeId,\n  popScopeId,\n  withScopeId,\n} from './componentRenderContext'\nexport { renderList } from './helpers/renderList'\nexport { toHandlers } from './helpers/toHandlers'\nexport { renderSlot } from './helpers/renderSlot'\nexport { createSlots } from './helpers/createSlots'\nexport { withMemo, isMemoSame } from './helpers/withMemo'\nexport {\n  openBlock,\n  createBlock,\n  setBlockTracking,\n  createTextVNode,\n  createCommentVNode,\n  createStaticVNode,\n  createElementVNode,\n  createElementBlock,\n  guardReactiveProps,\n} from './vnode'\nexport {\n  toDisplayString,\n  camelize,\n  capitalize,\n  toHandlerKey,\n  normalizeProps,\n  normalizeClass,\n  normalizeStyle,\n} from '@vue/shared'\n\n// For test-utils\nexport { transformVNodeArgs } from './vnode'\n\n// SSR -------------------------------------------------------------------------\n\n// **IMPORTANT** These APIs are exposed solely for @vue/server-renderer and may\n// change without notice between versions. User code should never rely on them.\n\nimport {\n  createComponentInstance,\n  getComponentPublicInstance,\n  setupComponent,\n} from './component'\nimport { renderComponentRoot } from './componentRenderUtils'\nimport { setCurrentRenderingInstance } from './componentRenderContext'\nimport { isVNode, normalizeVNode } from './vnode'\nimport { ensureValidVNode } from './helpers/renderSlot'\nimport { popWarningContext, pushWarningContext } from './warning'\n\nconst _ssrUtils: {\n  createComponentInstance: typeof createComponentInstance\n  setupComponent: typeof setupComponent\n  renderComponentRoot: typeof renderComponentRoot\n  setCurrentRenderingInstance: typeof setCurrentRenderingInstance\n  isVNode: typeof isVNode\n  normalizeVNode: typeof normalizeVNode\n  getComponentPublicInstance: typeof getComponentPublicInstance\n  ensureValidVNode: typeof ensureValidVNode\n  pushWarningContext: typeof pushWarningContext\n  popWarningContext: typeof popWarningContext\n} = {\n  createComponentInstance,\n  setupComponent,\n  renderComponentRoot,\n  setCurrentRenderingInstance,\n  isVNode,\n  normalizeVNode,\n  getComponentPublicInstance,\n  ensureValidVNode,\n  pushWarningContext,\n  popWarningContext,\n}\n\n/**\n * SSR utils for \\@vue/server-renderer. Only exposed in ssr-possible builds.\n * @internal\n */\nexport const ssrUtils = (__SSR__ ? _ssrUtils : null) as typeof _ssrUtils\n\n// 2.x COMPAT ------------------------------------------------------------------\n\nimport { DeprecationTypes as _DeprecationTypes } from './compat/compatConfig'\nexport type { CompatVue } from './compat/global'\nexport type { LegacyConfig } from './compat/globalConfig'\n\nimport { warnDeprecation } from './compat/compatConfig'\nimport { createCompatVue } from './compat/global'\nimport {\n  checkCompatEnabled,\n  isCompatEnabled,\n  softAssertCompatEnabled,\n} from './compat/compatConfig'\nimport { resolveFilter as _resolveFilter } from './helpers/resolveAssets'\nimport { NOOP } from '@vue/shared'\n\n/**\n * @internal only exposed in compat builds\n */\nexport const resolveFilter: typeof _resolveFilter | null = __COMPAT__\n  ? _resolveFilter\n  : null\n\nconst _compatUtils: {\n  warnDeprecation: typeof warnDeprecation\n  createCompatVue: typeof createCompatVue\n  isCompatEnabled: typeof isCompatEnabled\n  checkCompatEnabled: typeof checkCompatEnabled\n  softAssertCompatEnabled: typeof softAssertCompatEnabled\n} = {\n  warnDeprecation,\n  createCompatVue,\n  isCompatEnabled,\n  checkCompatEnabled,\n  softAssertCompatEnabled,\n}\n\n/**\n * @internal only exposed in compat builds.\n */\nexport const compatUtils = (\n  __COMPAT__ ? _compatUtils : null\n) as typeof _compatUtils\n\nexport const DeprecationTypes = (\n  __COMPAT__ ? _DeprecationTypes : null\n) as typeof _DeprecationTypes\n"
  },
  {
    "path": "packages/runtime-core/src/internalObject.ts",
    "content": "/**\n * Used during vnode props/slots normalization to check if the vnode props/slots\n * are the internal attrs / slots object of a component via\n * `Object.getPrototypeOf`. This is more performant than defining a\n * non-enumerable property. (one of the optimizations done for ssr-benchmark)\n */\nconst internalObjectProto = {}\n\nexport const createInternalObject = (): any =>\n  Object.create(internalObjectProto)\n\nexport const isInternalObject = (obj: object): boolean =>\n  Object.getPrototypeOf(obj) === internalObjectProto\n"
  },
  {
    "path": "packages/runtime-core/src/profiling.ts",
    "content": "/* eslint-disable no-restricted-globals */\nimport {\n  type ComponentInternalInstance,\n  formatComponentName,\n} from './component'\nimport { devtoolsPerfEnd, devtoolsPerfStart } from './devtools'\n\nlet supported: boolean\nlet perf: Performance\n\nexport function startMeasure(\n  instance: ComponentInternalInstance,\n  type: string,\n): void {\n  if (instance.appContext.config.performance && isSupported()) {\n    perf.mark(`vue-${type}-${instance.uid}`)\n  }\n\n  if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {\n    devtoolsPerfStart(instance, type, isSupported() ? perf.now() : Date.now())\n  }\n}\n\nexport function endMeasure(\n  instance: ComponentInternalInstance,\n  type: string,\n): void {\n  if (instance.appContext.config.performance && isSupported()) {\n    const startTag = `vue-${type}-${instance.uid}`\n    const endTag = startTag + `:end`\n    const measureName = `<${formatComponentName(instance, instance.type)}> ${type}`\n    perf.mark(endTag)\n    perf.measure(measureName, startTag, endTag)\n    perf.clearMeasures(measureName)\n    perf.clearMarks(startTag)\n    perf.clearMarks(endTag)\n  }\n\n  if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {\n    devtoolsPerfEnd(instance, type, isSupported() ? perf.now() : Date.now())\n  }\n}\n\nfunction isSupported() {\n  if (supported !== undefined) {\n    return supported\n  }\n  if (typeof window !== 'undefined' && window.performance) {\n    supported = true\n    perf = window.performance\n  } else {\n    supported = false\n  }\n  return supported\n}\n"
  },
  {
    "path": "packages/runtime-core/src/renderer.ts",
    "content": "import {\n  Comment,\n  Fragment,\n  Static,\n  Text,\n  type VNode,\n  type VNodeArrayChildren,\n  type VNodeHook,\n  type VNodeProps,\n  cloneIfMounted,\n  createVNode,\n  invokeVNodeHook,\n  isSameVNodeType,\n  normalizeVNode,\n} from './vnode'\nimport {\n  type ComponentInternalInstance,\n  type ComponentOptions,\n  type Data,\n  type LifecycleHook,\n  createComponentInstance,\n  setupComponent,\n} from './component'\nimport {\n  filterSingleRoot,\n  renderComponentRoot,\n  shouldUpdateComponent,\n  updateHOCHostEl,\n} from './componentRenderUtils'\nimport {\n  EMPTY_ARR,\n  EMPTY_OBJ,\n  NOOP,\n  PatchFlags,\n  ShapeFlags,\n  def,\n  getGlobalThis,\n  invokeArrayFns,\n  isArray,\n  isReservedProp,\n} from '@vue/shared'\nimport {\n  type SchedulerJob,\n  SchedulerJobFlags,\n  type SchedulerJobs,\n  flushPostFlushCbs,\n  flushPreFlushCbs,\n  queueJob,\n  queuePostFlushCb,\n} from './scheduler'\nimport {\n  EffectFlags,\n  ReactiveEffect,\n  pauseTracking,\n  resetTracking,\n} from '@vue/reactivity'\nimport { updateProps } from './componentProps'\nimport { updateSlots } from './componentSlots'\nimport { popWarningContext, pushWarningContext, warn } from './warning'\nimport { type CreateAppFunction, createAppAPI } from './apiCreateApp'\nimport { setRef } from './rendererTemplateRef'\nimport {\n  type SuspenseBoundary,\n  type SuspenseImpl,\n  isSuspense,\n  queueEffectWithSuspense,\n} from './components/Suspense'\nimport {\n  TeleportEndKey,\n  type TeleportImpl,\n  type TeleportVNode,\n} from './components/Teleport'\nimport { type KeepAliveContext, isKeepAlive } from './components/KeepAlive'\nimport { isHmrUpdating, registerHMR, unregisterHMR } from './hmr'\nimport { type RootHydrateFunction, createHydrationFunctions } from './hydration'\nimport { invokeDirectiveHook } from './directives'\nimport { endMeasure, startMeasure } from './profiling'\nimport {\n  devtoolsComponentAdded,\n  devtoolsComponentRemoved,\n  devtoolsComponentUpdated,\n  setDevtoolsHook,\n} from './devtools'\nimport { initFeatureFlags } from './featureFlags'\nimport { isAsyncWrapper } from './apiAsyncComponent'\nimport { isCompatEnabled } from './compat/compatConfig'\nimport { DeprecationTypes } from './compat/compatConfig'\nimport { type TransitionHooks, leaveCbKey } from './components/BaseTransition'\nimport type { ComponentCustomElementInterface } from './component'\n\nexport interface Renderer<HostElement = RendererElement> {\n  render: RootRenderFunction<HostElement>\n  createApp: CreateAppFunction<HostElement>\n}\n\nexport interface HydrationRenderer extends Renderer<Element | ShadowRoot> {\n  hydrate: RootHydrateFunction\n}\n\nexport type ElementNamespace = 'svg' | 'mathml' | undefined\n\nexport type RootRenderFunction<HostElement = RendererElement> = (\n  vnode: VNode | null,\n  container: HostElement,\n  namespace?: ElementNamespace,\n) => void\n\nexport interface RendererOptions<\n  HostNode = RendererNode,\n  HostElement = RendererElement,\n> {\n  patchProp(\n    el: HostElement,\n    key: string,\n    prevValue: any,\n    nextValue: any,\n    namespace?: ElementNamespace,\n    parentComponent?: ComponentInternalInstance | null,\n  ): void\n  insert(el: HostNode, parent: HostElement, anchor?: HostNode | null): void\n  remove(el: HostNode): void\n  createElement(\n    type: string,\n    namespace?: ElementNamespace,\n    isCustomizedBuiltIn?: string,\n    vnodeProps?: (VNodeProps & { [key: string]: any }) | null,\n  ): HostElement\n  createText(text: string): HostNode\n  createComment(text: string): HostNode\n  setText(node: HostNode, text: string): void\n  setElementText(node: HostElement, text: string): void\n  parentNode(node: HostNode): HostElement | null\n  nextSibling(node: HostNode): HostNode | null\n  querySelector?(selector: string): HostElement | null\n  setScopeId?(el: HostElement, id: string): void\n  cloneNode?(node: HostNode): HostNode\n  insertStaticContent?(\n    content: string,\n    parent: HostElement,\n    anchor: HostNode | null,\n    namespace: ElementNamespace,\n    start?: HostNode | null,\n    end?: HostNode | null,\n  ): [HostNode, HostNode]\n}\n\n// Renderer Node can technically be any object in the context of core renderer\n// logic - they are never directly operated on and always passed to the node op\n// functions provided via options, so the internal constraint is really just\n// a generic object.\nexport interface RendererNode {\n  [key: string | symbol]: any\n}\n\nexport interface RendererElement extends RendererNode {}\n\n// An object exposing the internals of a renderer, passed to tree-shakeable\n// features so that they can be decoupled from this file. Keys are shortened\n// to optimize bundle size.\nexport interface RendererInternals<\n  HostNode = RendererNode,\n  HostElement = RendererElement,\n> {\n  p: PatchFn\n  um: UnmountFn\n  r: RemoveFn\n  m: MoveFn\n  mt: MountComponentFn\n  mc: MountChildrenFn\n  pc: PatchChildrenFn\n  pbc: PatchBlockChildrenFn\n  n: NextFn\n  o: RendererOptions<HostNode, HostElement>\n}\n\n// These functions are created inside a closure and therefore their types cannot\n// be directly exported. In order to avoid maintaining function signatures in\n// two places, we declare them once here and use them inside the closure.\ntype PatchFn = (\n  n1: VNode | null, // null means this is a mount\n  n2: VNode,\n  container: RendererElement,\n  anchor?: RendererNode | null,\n  parentComponent?: ComponentInternalInstance | null,\n  parentSuspense?: SuspenseBoundary | null,\n  namespace?: ElementNamespace,\n  slotScopeIds?: string[] | null,\n  optimized?: boolean,\n) => void\n\ntype MountChildrenFn = (\n  children: VNodeArrayChildren,\n  container: RendererElement,\n  anchor: RendererNode | null,\n  parentComponent: ComponentInternalInstance | null,\n  parentSuspense: SuspenseBoundary | null,\n  namespace: ElementNamespace,\n  slotScopeIds: string[] | null,\n  optimized: boolean,\n  start?: number,\n) => void\n\ntype PatchChildrenFn = (\n  n1: VNode | null,\n  n2: VNode,\n  container: RendererElement,\n  anchor: RendererNode | null,\n  parentComponent: ComponentInternalInstance | null,\n  parentSuspense: SuspenseBoundary | null,\n  namespace: ElementNamespace,\n  slotScopeIds: string[] | null,\n  optimized: boolean,\n) => void\n\ntype PatchBlockChildrenFn = (\n  oldChildren: VNode[],\n  newChildren: VNode[],\n  fallbackContainer: RendererElement,\n  parentComponent: ComponentInternalInstance | null,\n  parentSuspense: SuspenseBoundary | null,\n  namespace: ElementNamespace,\n  slotScopeIds: string[] | null,\n) => void\n\ntype MoveFn = (\n  vnode: VNode,\n  container: RendererElement,\n  anchor: RendererNode | null,\n  type: MoveType,\n  parentSuspense?: SuspenseBoundary | null,\n) => void\n\ntype NextFn = (vnode: VNode) => RendererNode | null\n\ntype UnmountFn = (\n  vnode: VNode,\n  parentComponent: ComponentInternalInstance | null,\n  parentSuspense: SuspenseBoundary | null,\n  doRemove?: boolean,\n  optimized?: boolean,\n) => void\n\ntype RemoveFn = (vnode: VNode) => void\n\ntype UnmountChildrenFn = (\n  children: VNode[],\n  parentComponent: ComponentInternalInstance | null,\n  parentSuspense: SuspenseBoundary | null,\n  doRemove?: boolean,\n  optimized?: boolean,\n  start?: number,\n) => void\n\nexport type MountComponentFn = (\n  initialVNode: VNode,\n  container: RendererElement,\n  anchor: RendererNode | null,\n  parentComponent: ComponentInternalInstance | null,\n  parentSuspense: SuspenseBoundary | null,\n  namespace: ElementNamespace,\n  optimized: boolean,\n) => void\n\ntype ProcessTextOrCommentFn = (\n  n1: VNode | null,\n  n2: VNode,\n  container: RendererElement,\n  anchor: RendererNode | null,\n) => void\n\nexport type SetupRenderEffectFn = (\n  instance: ComponentInternalInstance,\n  initialVNode: VNode,\n  container: RendererElement,\n  anchor: RendererNode | null,\n  parentSuspense: SuspenseBoundary | null,\n  namespace: ElementNamespace,\n  optimized: boolean,\n) => void\n\nexport enum MoveType {\n  ENTER,\n  LEAVE,\n  REORDER,\n}\n\nexport const queuePostRenderEffect: (\n  fn: SchedulerJobs,\n  suspense: SuspenseBoundary | null,\n) => void = __FEATURE_SUSPENSE__\n  ? __TEST__\n    ? // vitest can't seem to handle eager circular dependency\n      (fn: Function | Function[], suspense: SuspenseBoundary | null) =>\n        queueEffectWithSuspense(fn, suspense)\n    : queueEffectWithSuspense\n  : queuePostFlushCb\n\n/**\n * The createRenderer function accepts two generic arguments:\n * HostNode and HostElement, corresponding to Node and Element types in the\n * host environment. For example, for runtime-dom, HostNode would be the DOM\n * `Node` interface and HostElement would be the DOM `Element` interface.\n *\n * Custom renderers can pass in the platform specific types like this:\n *\n * ``` js\n * const { render, createApp } = createRenderer<Node, Element>({\n *   patchProp,\n *   ...nodeOps\n * })\n * ```\n */\nexport function createRenderer<\n  HostNode = RendererNode,\n  HostElement = RendererElement,\n>(options: RendererOptions<HostNode, HostElement>): Renderer<HostElement> {\n  return baseCreateRenderer<HostNode, HostElement>(options)\n}\n\n// Separate API for creating hydration-enabled renderer.\n// Hydration logic is only used when calling this function, making it\n// tree-shakable.\nexport function createHydrationRenderer(\n  options: RendererOptions<Node, Element>,\n): HydrationRenderer {\n  return baseCreateRenderer(options, createHydrationFunctions)\n}\n\n// overload 1: no hydration\nfunction baseCreateRenderer<\n  HostNode = RendererNode,\n  HostElement = RendererElement,\n>(options: RendererOptions<HostNode, HostElement>): Renderer<HostElement>\n\n// overload 2: with hydration\nfunction baseCreateRenderer(\n  options: RendererOptions<Node, Element>,\n  createHydrationFns: typeof createHydrationFunctions,\n): HydrationRenderer\n\n// implementation\nfunction baseCreateRenderer(\n  options: RendererOptions,\n  createHydrationFns?: typeof createHydrationFunctions,\n): any {\n  // compile-time feature flags check\n  if (__ESM_BUNDLER__ && !__TEST__) {\n    initFeatureFlags()\n  }\n\n  const target = getGlobalThis()\n  target.__VUE__ = true\n  if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {\n    setDevtoolsHook(target.__VUE_DEVTOOLS_GLOBAL_HOOK__, target)\n  }\n\n  const {\n    insert: hostInsert,\n    remove: hostRemove,\n    patchProp: hostPatchProp,\n    createElement: hostCreateElement,\n    createText: hostCreateText,\n    createComment: hostCreateComment,\n    setText: hostSetText,\n    setElementText: hostSetElementText,\n    parentNode: hostParentNode,\n    nextSibling: hostNextSibling,\n    setScopeId: hostSetScopeId = NOOP,\n    insertStaticContent: hostInsertStaticContent,\n  } = options\n\n  // Note: functions inside this closure should use `const xxx = () => {}`\n  // style in order to prevent being inlined by minifiers.\n  const patch: PatchFn = (\n    n1,\n    n2,\n    container,\n    anchor = null,\n    parentComponent = null,\n    parentSuspense = null,\n    namespace = undefined,\n    slotScopeIds = null,\n    optimized = __DEV__ && isHmrUpdating ? false : !!n2.dynamicChildren,\n  ) => {\n    if (n1 === n2) {\n      return\n    }\n\n    // patching & not same type, unmount old tree\n    if (n1 && !isSameVNodeType(n1, n2)) {\n      anchor = getNextHostNode(n1)\n      unmount(n1, parentComponent, parentSuspense, true)\n      n1 = null\n    }\n\n    if (n2.patchFlag === PatchFlags.BAIL) {\n      optimized = false\n      n2.dynamicChildren = null\n    }\n\n    const { type, ref, shapeFlag } = n2\n    switch (type) {\n      case Text:\n        processText(n1, n2, container, anchor)\n        break\n      case Comment:\n        processCommentNode(n1, n2, container, anchor)\n        break\n      case Static:\n        if (n1 == null) {\n          mountStaticNode(n2, container, anchor, namespace)\n        } else if (__DEV__) {\n          patchStaticNode(n1, n2, container, namespace)\n        }\n        break\n      case Fragment:\n        processFragment(\n          n1,\n          n2,\n          container,\n          anchor,\n          parentComponent,\n          parentSuspense,\n          namespace,\n          slotScopeIds,\n          optimized,\n        )\n        break\n      default:\n        if (shapeFlag & ShapeFlags.ELEMENT) {\n          processElement(\n            n1,\n            n2,\n            container,\n            anchor,\n            parentComponent,\n            parentSuspense,\n            namespace,\n            slotScopeIds,\n            optimized,\n          )\n        } else if (shapeFlag & ShapeFlags.COMPONENT) {\n          processComponent(\n            n1,\n            n2,\n            container,\n            anchor,\n            parentComponent,\n            parentSuspense,\n            namespace,\n            slotScopeIds,\n            optimized,\n          )\n        } else if (shapeFlag & ShapeFlags.TELEPORT) {\n          ;(type as typeof TeleportImpl).process(\n            n1 as TeleportVNode,\n            n2 as TeleportVNode,\n            container,\n            anchor,\n            parentComponent,\n            parentSuspense,\n            namespace,\n            slotScopeIds,\n            optimized,\n            internals,\n          )\n        } else if (__FEATURE_SUSPENSE__ && shapeFlag & ShapeFlags.SUSPENSE) {\n          ;(type as typeof SuspenseImpl).process(\n            n1,\n            n2,\n            container,\n            anchor,\n            parentComponent,\n            parentSuspense,\n            namespace,\n            slotScopeIds,\n            optimized,\n            internals,\n          )\n        } else if (__DEV__) {\n          warn('Invalid VNode type:', type, `(${typeof type})`)\n        }\n    }\n\n    // set ref\n    if (ref != null && parentComponent) {\n      setRef(ref, n1 && n1.ref, parentSuspense, n2 || n1, !n2)\n    } else if (ref == null && n1 && n1.ref != null) {\n      setRef(n1.ref, null, parentSuspense, n1, true)\n    }\n  }\n\n  const processText: ProcessTextOrCommentFn = (n1, n2, container, anchor) => {\n    if (n1 == null) {\n      hostInsert(\n        (n2.el = hostCreateText(n2.children as string)),\n        container,\n        anchor,\n      )\n    } else {\n      const el = (n2.el = n1.el!)\n      if (n2.children !== n1.children) {\n        hostSetText(el, n2.children as string)\n      }\n    }\n  }\n\n  const processCommentNode: ProcessTextOrCommentFn = (\n    n1,\n    n2,\n    container,\n    anchor,\n  ) => {\n    if (n1 == null) {\n      hostInsert(\n        (n2.el = hostCreateComment((n2.children as string) || '')),\n        container,\n        anchor,\n      )\n    } else {\n      // there's no support for dynamic comments\n      n2.el = n1.el\n    }\n  }\n\n  const mountStaticNode = (\n    n2: VNode,\n    container: RendererElement,\n    anchor: RendererNode | null,\n    namespace: ElementNamespace,\n  ) => {\n    // static nodes are only present when used with compiler-dom/runtime-dom\n    // which guarantees presence of hostInsertStaticContent.\n    ;[n2.el, n2.anchor] = hostInsertStaticContent!(\n      n2.children as string,\n      container,\n      anchor,\n      namespace,\n      n2.el,\n      n2.anchor,\n    )\n  }\n\n  /**\n   * Dev / HMR only\n   */\n  const patchStaticNode = (\n    n1: VNode,\n    n2: VNode,\n    container: RendererElement,\n    namespace: ElementNamespace,\n  ) => {\n    // static nodes are only patched during dev for HMR\n    if (n2.children !== n1.children) {\n      const anchor = hostNextSibling(n1.anchor!)\n      // remove existing\n      removeStaticNode(n1)\n      // insert new\n      ;[n2.el, n2.anchor] = hostInsertStaticContent!(\n        n2.children as string,\n        container,\n        anchor,\n        namespace,\n      )\n    } else {\n      n2.el = n1.el\n      n2.anchor = n1.anchor\n    }\n  }\n\n  const moveStaticNode = (\n    { el, anchor }: VNode,\n    container: RendererElement,\n    nextSibling: RendererNode | null,\n  ) => {\n    let next\n    while (el && el !== anchor) {\n      next = hostNextSibling(el)\n      hostInsert(el, container, nextSibling)\n      el = next\n    }\n    hostInsert(anchor!, container, nextSibling)\n  }\n\n  const removeStaticNode = ({ el, anchor }: VNode) => {\n    let next\n    while (el && el !== anchor) {\n      next = hostNextSibling(el)\n      hostRemove(el)\n      el = next\n    }\n    hostRemove(anchor!)\n  }\n\n  const processElement = (\n    n1: VNode | null,\n    n2: VNode,\n    container: RendererElement,\n    anchor: RendererNode | null,\n    parentComponent: ComponentInternalInstance | null,\n    parentSuspense: SuspenseBoundary | null,\n    namespace: ElementNamespace,\n    slotScopeIds: string[] | null,\n    optimized: boolean,\n  ) => {\n    if (n2.type === 'svg') {\n      namespace = 'svg'\n    } else if (n2.type === 'math') {\n      namespace = 'mathml'\n    }\n\n    if (n1 == null) {\n      mountElement(\n        n2,\n        container,\n        anchor,\n        parentComponent,\n        parentSuspense,\n        namespace,\n        slotScopeIds,\n        optimized,\n      )\n    } else {\n      const customElement =\n        n1.el && (n1.el as ComponentCustomElementInterface)._isVueCE\n          ? (n1.el as ComponentCustomElementInterface)\n          : null\n      try {\n        if (customElement) {\n          customElement._beginPatch()\n        }\n        patchElement(\n          n1,\n          n2,\n          parentComponent,\n          parentSuspense,\n          namespace,\n          slotScopeIds,\n          optimized,\n        )\n      } finally {\n        if (customElement) {\n          customElement._endPatch()\n        }\n      }\n    }\n  }\n\n  const mountElement = (\n    vnode: VNode,\n    container: RendererElement,\n    anchor: RendererNode | null,\n    parentComponent: ComponentInternalInstance | null,\n    parentSuspense: SuspenseBoundary | null,\n    namespace: ElementNamespace,\n    slotScopeIds: string[] | null,\n    optimized: boolean,\n  ) => {\n    let el: RendererElement\n    let vnodeHook: VNodeHook | undefined | null\n    const { props, shapeFlag, transition, dirs } = vnode\n\n    el = vnode.el = hostCreateElement(\n      vnode.type as string,\n      namespace,\n      props && props.is,\n      props,\n    )\n\n    // mount children first, since some props may rely on child content\n    // being already rendered, e.g. `<select value>`\n    if (shapeFlag & ShapeFlags.TEXT_CHILDREN) {\n      hostSetElementText(el, vnode.children as string)\n    } else if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) {\n      mountChildren(\n        vnode.children as VNodeArrayChildren,\n        el,\n        null,\n        parentComponent,\n        parentSuspense,\n        resolveChildrenNamespace(vnode, namespace),\n        slotScopeIds,\n        optimized,\n      )\n    }\n\n    if (dirs) {\n      invokeDirectiveHook(vnode, null, parentComponent, 'created')\n    }\n    // scopeId\n    setScopeId(el, vnode, vnode.scopeId, slotScopeIds, parentComponent)\n    // props\n    if (props) {\n      for (const key in props) {\n        if (key !== 'value' && !isReservedProp(key)) {\n          hostPatchProp(el, key, null, props[key], namespace, parentComponent)\n        }\n      }\n      /**\n       * Special case for setting value on DOM elements:\n       * - it can be order-sensitive (e.g. should be set *after* min/max, #2325, #4024)\n       * - it needs to be forced (#1471)\n       * #2353 proposes adding another renderer option to configure this, but\n       * the properties affects are so finite it is worth special casing it\n       * here to reduce the complexity. (Special casing it also should not\n       * affect non-DOM renderers)\n       */\n      if ('value' in props) {\n        hostPatchProp(el, 'value', null, props.value, namespace)\n      }\n      if ((vnodeHook = props.onVnodeBeforeMount)) {\n        invokeVNodeHook(vnodeHook, parentComponent, vnode)\n      }\n    }\n\n    if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {\n      def(el, '__vnode', vnode, true)\n      def(el, '__vueParentComponent', parentComponent, true)\n    }\n\n    if (dirs) {\n      invokeDirectiveHook(vnode, null, parentComponent, 'beforeMount')\n    }\n    // #1583 For inside suspense + suspense not resolved case, enter hook should call when suspense resolved\n    // #1689 For inside suspense + suspense resolved case, just call it\n    const needCallTransitionHooks = needTransition(parentSuspense, transition)\n    if (needCallTransitionHooks) {\n      transition!.beforeEnter(el)\n    }\n    hostInsert(el, container, anchor)\n    if (\n      (vnodeHook = props && props.onVnodeMounted) ||\n      needCallTransitionHooks ||\n      dirs\n    ) {\n      queuePostRenderEffect(() => {\n        vnodeHook && invokeVNodeHook(vnodeHook, parentComponent, vnode)\n        needCallTransitionHooks && transition!.enter(el)\n        dirs && invokeDirectiveHook(vnode, null, parentComponent, 'mounted')\n      }, parentSuspense)\n    }\n  }\n\n  const setScopeId = (\n    el: RendererElement,\n    vnode: VNode,\n    scopeId: string | null,\n    slotScopeIds: string[] | null,\n    parentComponent: ComponentInternalInstance | null,\n  ) => {\n    if (scopeId) {\n      hostSetScopeId(el, scopeId)\n    }\n    if (slotScopeIds) {\n      for (let i = 0; i < slotScopeIds.length; i++) {\n        hostSetScopeId(el, slotScopeIds[i])\n      }\n    }\n    if (parentComponent) {\n      let subTree = parentComponent.subTree\n      if (\n        __DEV__ &&\n        subTree.patchFlag > 0 &&\n        subTree.patchFlag & PatchFlags.DEV_ROOT_FRAGMENT\n      ) {\n        subTree =\n          filterSingleRoot(subTree.children as VNodeArrayChildren) || subTree\n      }\n      if (\n        vnode === subTree ||\n        (isSuspense(subTree.type) &&\n          (subTree.ssContent === vnode || subTree.ssFallback === vnode))\n      ) {\n        const parentVNode = parentComponent.vnode\n        setScopeId(\n          el,\n          parentVNode,\n          parentVNode.scopeId,\n          parentVNode.slotScopeIds,\n          parentComponent.parent,\n        )\n      }\n    }\n  }\n\n  const mountChildren: MountChildrenFn = (\n    children,\n    container,\n    anchor,\n    parentComponent,\n    parentSuspense,\n    namespace: ElementNamespace,\n    slotScopeIds,\n    optimized,\n    start = 0,\n  ) => {\n    for (let i = start; i < children.length; i++) {\n      const child = (children[i] = optimized\n        ? cloneIfMounted(children[i] as VNode)\n        : normalizeVNode(children[i]))\n      patch(\n        null,\n        child,\n        container,\n        anchor,\n        parentComponent,\n        parentSuspense,\n        namespace,\n        slotScopeIds,\n        optimized,\n      )\n    }\n  }\n\n  const patchElement = (\n    n1: VNode,\n    n2: VNode,\n    parentComponent: ComponentInternalInstance | null,\n    parentSuspense: SuspenseBoundary | null,\n    namespace: ElementNamespace,\n    slotScopeIds: string[] | null,\n    optimized: boolean,\n  ) => {\n    const el = (n2.el = n1.el!)\n    if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {\n      el.__vnode = n2\n    }\n    let { patchFlag, dynamicChildren, dirs } = n2\n    // #1426 take the old vnode's patch flag into account since user may clone a\n    // compiler-generated vnode, which de-opts to FULL_PROPS\n    patchFlag |= n1.patchFlag & PatchFlags.FULL_PROPS\n    const oldProps = n1.props || EMPTY_OBJ\n    const newProps = n2.props || EMPTY_OBJ\n    let vnodeHook: VNodeHook | undefined | null\n\n    // disable recurse in beforeUpdate hooks\n    parentComponent && toggleRecurse(parentComponent, false)\n    if ((vnodeHook = newProps.onVnodeBeforeUpdate)) {\n      invokeVNodeHook(vnodeHook, parentComponent, n2, n1)\n    }\n    if (dirs) {\n      invokeDirectiveHook(n2, n1, parentComponent, 'beforeUpdate')\n    }\n    parentComponent && toggleRecurse(parentComponent, true)\n\n    if (__DEV__ && isHmrUpdating) {\n      // HMR updated, force full diff\n      patchFlag = 0\n      optimized = false\n      dynamicChildren = null\n    }\n\n    // #9135 innerHTML / textContent unset needs to happen before possible\n    // new children mount\n    if (\n      (oldProps.innerHTML && newProps.innerHTML == null) ||\n      (oldProps.textContent && newProps.textContent == null)\n    ) {\n      hostSetElementText(el, '')\n    }\n\n    if (dynamicChildren) {\n      patchBlockChildren(\n        n1.dynamicChildren!,\n        dynamicChildren,\n        el,\n        parentComponent,\n        parentSuspense,\n        resolveChildrenNamespace(n2, namespace),\n        slotScopeIds,\n      )\n      if (__DEV__) {\n        // necessary for HMR\n        traverseStaticChildren(n1, n2)\n      }\n    } else if (!optimized) {\n      // full diff\n      patchChildren(\n        n1,\n        n2,\n        el,\n        null,\n        parentComponent,\n        parentSuspense,\n        resolveChildrenNamespace(n2, namespace),\n        slotScopeIds,\n        false,\n      )\n    }\n\n    if (patchFlag > 0) {\n      // the presence of a patchFlag means this element's render code was\n      // generated by the compiler and can take the fast path.\n      // in this path old node and new node are guaranteed to have the same shape\n      // (i.e. at the exact same position in the source template)\n      if (patchFlag & PatchFlags.FULL_PROPS) {\n        // element props contain dynamic keys, full diff needed\n        patchProps(el, oldProps, newProps, parentComponent, namespace)\n      } else {\n        // class\n        // this flag is matched when the element has dynamic class bindings.\n        if (patchFlag & PatchFlags.CLASS) {\n          if (oldProps.class !== newProps.class) {\n            hostPatchProp(el, 'class', null, newProps.class, namespace)\n          }\n        }\n\n        // style\n        // this flag is matched when the element has dynamic style bindings\n        if (patchFlag & PatchFlags.STYLE) {\n          hostPatchProp(el, 'style', oldProps.style, newProps.style, namespace)\n        }\n\n        // props\n        // This flag is matched when the element has dynamic prop/attr bindings\n        // other than class and style. The keys of dynamic prop/attrs are saved for\n        // faster iteration.\n        // Note dynamic keys like :[foo]=\"bar\" will cause this optimization to\n        // bail out and go through a full diff because we need to unset the old key\n        if (patchFlag & PatchFlags.PROPS) {\n          // if the flag is present then dynamicProps must be non-null\n          const propsToUpdate = n2.dynamicProps!\n          for (let i = 0; i < propsToUpdate.length; i++) {\n            const key = propsToUpdate[i]\n            const prev = oldProps[key]\n            const next = newProps[key]\n            // #1471 force patch value\n            if (next !== prev || key === 'value') {\n              hostPatchProp(el, key, prev, next, namespace, parentComponent)\n            }\n          }\n        }\n      }\n\n      // text\n      // This flag is matched when the element has only dynamic text children.\n      if (patchFlag & PatchFlags.TEXT) {\n        if (n1.children !== n2.children) {\n          hostSetElementText(el, n2.children as string)\n        }\n      }\n    } else if (!optimized && dynamicChildren == null) {\n      // unoptimized, full diff\n      patchProps(el, oldProps, newProps, parentComponent, namespace)\n    }\n\n    if ((vnodeHook = newProps.onVnodeUpdated) || dirs) {\n      queuePostRenderEffect(() => {\n        vnodeHook && invokeVNodeHook(vnodeHook, parentComponent, n2, n1)\n        dirs && invokeDirectiveHook(n2, n1, parentComponent, 'updated')\n      }, parentSuspense)\n    }\n  }\n\n  // The fast path for blocks.\n  const patchBlockChildren: PatchBlockChildrenFn = (\n    oldChildren,\n    newChildren,\n    fallbackContainer,\n    parentComponent,\n    parentSuspense,\n    namespace: ElementNamespace,\n    slotScopeIds,\n  ) => {\n    for (let i = 0; i < newChildren.length; i++) {\n      const oldVNode = oldChildren[i]\n      const newVNode = newChildren[i]\n      // Determine the container (parent element) for the patch.\n      const container =\n        // oldVNode may be an errored async setup() component inside Suspense\n        // which will not have a mounted element\n        oldVNode.el &&\n        // - In the case of a Fragment, we need to provide the actual parent\n        // of the Fragment itself so it can move its children.\n        (oldVNode.type === Fragment ||\n          // - In the case of different nodes, there is going to be a replacement\n          // which also requires the correct parent container\n          !isSameVNodeType(oldVNode, newVNode) ||\n          // - In the case of a component, it could contain anything.\n          oldVNode.shapeFlag &\n            (ShapeFlags.COMPONENT | ShapeFlags.TELEPORT | ShapeFlags.SUSPENSE))\n          ? hostParentNode(oldVNode.el)!\n          : // In other cases, the parent container is not actually used so we\n            // just pass the block element here to avoid a DOM parentNode call.\n            fallbackContainer\n      patch(\n        oldVNode,\n        newVNode,\n        container,\n        null,\n        parentComponent,\n        parentSuspense,\n        namespace,\n        slotScopeIds,\n        true,\n      )\n    }\n  }\n\n  const patchProps = (\n    el: RendererElement,\n    oldProps: Data,\n    newProps: Data,\n    parentComponent: ComponentInternalInstance | null,\n    namespace: ElementNamespace,\n  ) => {\n    if (oldProps !== newProps) {\n      if (oldProps !== EMPTY_OBJ) {\n        for (const key in oldProps) {\n          if (!isReservedProp(key) && !(key in newProps)) {\n            hostPatchProp(\n              el,\n              key,\n              oldProps[key],\n              null,\n              namespace,\n              parentComponent,\n            )\n          }\n        }\n      }\n      for (const key in newProps) {\n        // empty string is not valid prop\n        if (isReservedProp(key)) continue\n        const next = newProps[key]\n        const prev = oldProps[key]\n        // defer patching value\n        if (next !== prev && key !== 'value') {\n          hostPatchProp(el, key, prev, next, namespace, parentComponent)\n        }\n      }\n      if ('value' in newProps) {\n        hostPatchProp(el, 'value', oldProps.value, newProps.value, namespace)\n      }\n    }\n  }\n\n  const processFragment = (\n    n1: VNode | null,\n    n2: VNode,\n    container: RendererElement,\n    anchor: RendererNode | null,\n    parentComponent: ComponentInternalInstance | null,\n    parentSuspense: SuspenseBoundary | null,\n    namespace: ElementNamespace,\n    slotScopeIds: string[] | null,\n    optimized: boolean,\n  ) => {\n    const fragmentStartAnchor = (n2.el = n1 ? n1.el : hostCreateText(''))!\n    const fragmentEndAnchor = (n2.anchor = n1 ? n1.anchor : hostCreateText(''))!\n\n    let { patchFlag, dynamicChildren, slotScopeIds: fragmentSlotScopeIds } = n2\n\n    if (\n      __DEV__ &&\n      // #5523 dev root fragment may inherit directives\n      (isHmrUpdating || patchFlag & PatchFlags.DEV_ROOT_FRAGMENT)\n    ) {\n      // HMR updated / Dev root fragment (w/ comments), force full diff\n      patchFlag = 0\n      optimized = false\n      dynamicChildren = null\n    }\n\n    // check if this is a slot fragment with :slotted scope ids\n    if (fragmentSlotScopeIds) {\n      slotScopeIds = slotScopeIds\n        ? slotScopeIds.concat(fragmentSlotScopeIds)\n        : fragmentSlotScopeIds\n    }\n\n    if (n1 == null) {\n      hostInsert(fragmentStartAnchor, container, anchor)\n      hostInsert(fragmentEndAnchor, container, anchor)\n      // a fragment can only have array children\n      // since they are either generated by the compiler, or implicitly created\n      // from arrays.\n      mountChildren(\n        // #10007\n        // such fragment like `<></>` will be compiled into\n        // a fragment which doesn't have a children.\n        // In this case fallback to an empty array\n        (n2.children || []) as VNodeArrayChildren,\n        container,\n        fragmentEndAnchor,\n        parentComponent,\n        parentSuspense,\n        namespace,\n        slotScopeIds,\n        optimized,\n      )\n    } else {\n      if (\n        patchFlag > 0 &&\n        patchFlag & PatchFlags.STABLE_FRAGMENT &&\n        dynamicChildren &&\n        // #2715 the previous fragment could've been a BAILed one as a result\n        // of renderSlot() with no valid children\n        n1.dynamicChildren &&\n        n1.dynamicChildren.length === dynamicChildren.length\n      ) {\n        // a stable fragment (template root or <template v-for>) doesn't need to\n        // patch children order, but it may contain dynamicChildren.\n        patchBlockChildren(\n          n1.dynamicChildren,\n          dynamicChildren,\n          container,\n          parentComponent,\n          parentSuspense,\n          namespace,\n          slotScopeIds,\n        )\n        if (__DEV__) {\n          // necessary for HMR\n          traverseStaticChildren(n1, n2)\n        } else if (\n          // #2080 if the stable fragment has a key, it's a <template v-for> that may\n          //  get moved around. Make sure all root level vnodes inherit el.\n          // #2134 or if it's a component root, it may also get moved around\n          // as the component is being moved.\n          n2.key != null ||\n          (parentComponent && n2 === parentComponent.subTree)\n        ) {\n          traverseStaticChildren(n1, n2, true /* shallow */)\n        }\n      } else {\n        // keyed / unkeyed, or manual fragments.\n        // for keyed & unkeyed, since they are compiler generated from v-for,\n        // each child is guaranteed to be a block so the fragment will never\n        // have dynamicChildren.\n        patchChildren(\n          n1,\n          n2,\n          container,\n          fragmentEndAnchor,\n          parentComponent,\n          parentSuspense,\n          namespace,\n          slotScopeIds,\n          optimized,\n        )\n      }\n    }\n  }\n\n  const processComponent = (\n    n1: VNode | null,\n    n2: VNode,\n    container: RendererElement,\n    anchor: RendererNode | null,\n    parentComponent: ComponentInternalInstance | null,\n    parentSuspense: SuspenseBoundary | null,\n    namespace: ElementNamespace,\n    slotScopeIds: string[] | null,\n    optimized: boolean,\n  ) => {\n    n2.slotScopeIds = slotScopeIds\n    if (n1 == null) {\n      if (n2.shapeFlag & ShapeFlags.COMPONENT_KEPT_ALIVE) {\n        ;(parentComponent!.ctx as KeepAliveContext).activate(\n          n2,\n          container,\n          anchor,\n          namespace,\n          optimized,\n        )\n      } else {\n        mountComponent(\n          n2,\n          container,\n          anchor,\n          parentComponent,\n          parentSuspense,\n          namespace,\n          optimized,\n        )\n      }\n    } else {\n      updateComponent(n1, n2, optimized)\n    }\n  }\n\n  const mountComponent: MountComponentFn = (\n    initialVNode,\n    container,\n    anchor,\n    parentComponent,\n    parentSuspense,\n    namespace: ElementNamespace,\n    optimized,\n  ) => {\n    // 2.x compat may pre-create the component instance before actually\n    // mounting\n    const compatMountInstance =\n      __COMPAT__ && initialVNode.isCompatRoot && initialVNode.component\n    const instance: ComponentInternalInstance =\n      compatMountInstance ||\n      (initialVNode.component = createComponentInstance(\n        initialVNode,\n        parentComponent,\n        parentSuspense,\n      ))\n\n    if (__DEV__ && instance.type.__hmrId) {\n      registerHMR(instance)\n    }\n\n    if (__DEV__) {\n      pushWarningContext(initialVNode)\n      startMeasure(instance, `mount`)\n    }\n\n    // inject renderer internals for keepAlive\n    if (isKeepAlive(initialVNode)) {\n      ;(instance.ctx as KeepAliveContext).renderer = internals\n    }\n\n    // resolve props and slots for setup context\n    if (!(__COMPAT__ && compatMountInstance)) {\n      if (__DEV__) {\n        startMeasure(instance, `init`)\n      }\n      setupComponent(instance, false, optimized)\n      if (__DEV__) {\n        endMeasure(instance, `init`)\n      }\n    }\n\n    // avoid hydration for hmr updating\n    if (__DEV__ && isHmrUpdating) initialVNode.el = null\n\n    // setup() is async. This component relies on async logic to be resolved\n    // before proceeding\n    if (__FEATURE_SUSPENSE__ && instance.asyncDep) {\n      parentSuspense &&\n        parentSuspense.registerDep(instance, setupRenderEffect, optimized)\n\n      // Give it a placeholder if this is not hydration\n      // TODO handle self-defined fallback\n      if (!initialVNode.el) {\n        const placeholder = (instance.subTree = createVNode(Comment))\n        processCommentNode(null, placeholder, container!, anchor)\n        initialVNode.placeholder = placeholder.el\n      }\n    } else {\n      setupRenderEffect(\n        instance,\n        initialVNode,\n        container,\n        anchor,\n        parentSuspense,\n        namespace,\n        optimized,\n      )\n    }\n\n    if (__DEV__) {\n      popWarningContext()\n      endMeasure(instance, `mount`)\n    }\n  }\n\n  const updateComponent = (n1: VNode, n2: VNode, optimized: boolean) => {\n    const instance = (n2.component = n1.component)!\n    if (shouldUpdateComponent(n1, n2, optimized)) {\n      if (\n        __FEATURE_SUSPENSE__ &&\n        instance.asyncDep &&\n        !instance.asyncResolved\n      ) {\n        // async & still pending - just update props and slots\n        // since the component's reactive effect for render isn't set-up yet\n        if (__DEV__) {\n          pushWarningContext(n2)\n        }\n        updateComponentPreRender(instance, n2, optimized)\n        if (__DEV__) {\n          popWarningContext()\n        }\n        return\n      } else {\n        // normal update\n        instance.next = n2\n        // instance.update is the reactive effect.\n        instance.update()\n      }\n    } else {\n      // no update needed. just copy over properties\n      n2.el = n1.el\n      instance.vnode = n2\n    }\n  }\n\n  const setupRenderEffect: SetupRenderEffectFn = (\n    instance,\n    initialVNode,\n    container,\n    anchor,\n    parentSuspense,\n    namespace: ElementNamespace,\n    optimized,\n  ) => {\n    const componentUpdateFn = () => {\n      if (!instance.isMounted) {\n        let vnodeHook: VNodeHook | null | undefined\n        const { el, props } = initialVNode\n        const { bm, m, parent, root, type } = instance\n        const isAsyncWrapperVNode = isAsyncWrapper(initialVNode)\n\n        toggleRecurse(instance, false)\n        // beforeMount hook\n        if (bm) {\n          invokeArrayFns(bm)\n        }\n        // onVnodeBeforeMount\n        if (\n          !isAsyncWrapperVNode &&\n          (vnodeHook = props && props.onVnodeBeforeMount)\n        ) {\n          invokeVNodeHook(vnodeHook, parent, initialVNode)\n        }\n        if (\n          __COMPAT__ &&\n          isCompatEnabled(DeprecationTypes.INSTANCE_EVENT_HOOKS, instance)\n        ) {\n          instance.emit('hook:beforeMount')\n        }\n        toggleRecurse(instance, true)\n\n        if (el && hydrateNode) {\n          // vnode has adopted host node - perform hydration instead of mount.\n          const hydrateSubTree = () => {\n            if (__DEV__) {\n              startMeasure(instance, `render`)\n            }\n            instance.subTree = renderComponentRoot(instance)\n            if (__DEV__) {\n              endMeasure(instance, `render`)\n            }\n            if (__DEV__) {\n              startMeasure(instance, `hydrate`)\n            }\n            hydrateNode!(\n              el as Node,\n              instance.subTree,\n              instance,\n              parentSuspense,\n              null,\n            )\n            if (__DEV__) {\n              endMeasure(instance, `hydrate`)\n            }\n          }\n\n          if (\n            isAsyncWrapperVNode &&\n            (type as ComponentOptions).__asyncHydrate\n          ) {\n            ;(type as ComponentOptions).__asyncHydrate!(\n              el as Element,\n              instance,\n              hydrateSubTree,\n            )\n          } else {\n            hydrateSubTree()\n          }\n        } else {\n          // custom element style injection\n          if (root.ce && root.ce._hasShadowRoot()) {\n            root.ce._injectChildStyle(\n              type,\n              instance.parent ? instance.parent.type : undefined,\n            )\n          }\n\n          if (__DEV__) {\n            startMeasure(instance, `render`)\n          }\n          const subTree = (instance.subTree = renderComponentRoot(instance))\n          if (__DEV__) {\n            endMeasure(instance, `render`)\n          }\n          if (__DEV__) {\n            startMeasure(instance, `patch`)\n          }\n          patch(\n            null,\n            subTree,\n            container,\n            anchor,\n            instance,\n            parentSuspense,\n            namespace,\n          )\n          if (__DEV__) {\n            endMeasure(instance, `patch`)\n          }\n          initialVNode.el = subTree.el\n        }\n        // mounted hook\n        if (m) {\n          queuePostRenderEffect(m, parentSuspense)\n        }\n        // onVnodeMounted\n        if (\n          !isAsyncWrapperVNode &&\n          (vnodeHook = props && props.onVnodeMounted)\n        ) {\n          const scopedInitialVNode = initialVNode\n          queuePostRenderEffect(\n            () => invokeVNodeHook(vnodeHook!, parent, scopedInitialVNode),\n            parentSuspense,\n          )\n        }\n        if (\n          __COMPAT__ &&\n          isCompatEnabled(DeprecationTypes.INSTANCE_EVENT_HOOKS, instance)\n        ) {\n          queuePostRenderEffect(\n            () => instance.emit('hook:mounted'),\n            parentSuspense,\n          )\n        }\n\n        // activated hook for keep-alive roots.\n        // #1742 activated hook must be accessed after first render\n        // since the hook may be injected by a child keep-alive\n        if (\n          initialVNode.shapeFlag & ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE ||\n          (parent &&\n            isAsyncWrapper(parent.vnode) &&\n            parent.vnode.shapeFlag & ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE)\n        ) {\n          instance.a && queuePostRenderEffect(instance.a, parentSuspense)\n          if (\n            __COMPAT__ &&\n            isCompatEnabled(DeprecationTypes.INSTANCE_EVENT_HOOKS, instance)\n          ) {\n            queuePostRenderEffect(\n              () => instance.emit('hook:activated'),\n              parentSuspense,\n            )\n          }\n        }\n        instance.isMounted = true\n\n        if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {\n          devtoolsComponentAdded(instance)\n        }\n\n        // #2458: deference mount-only object parameters to prevent memleaks\n        initialVNode = container = anchor = null as any\n      } else {\n        let { next, bu, u, parent, vnode } = instance\n\n        if (__FEATURE_SUSPENSE__) {\n          const nonHydratedAsyncRoot = locateNonHydratedAsyncRoot(instance)\n          // we are trying to update some async comp before hydration\n          // this will cause crash because we don't know the root node yet\n          if (nonHydratedAsyncRoot) {\n            // only sync the properties and abort the rest of operations\n            if (next) {\n              next.el = vnode.el\n              updateComponentPreRender(instance, next, optimized)\n            }\n            // and continue the rest of operations once the deps are resolved\n            nonHydratedAsyncRoot.asyncDep!.then(() => {\n              // the instance may be destroyed during the time period\n              queuePostRenderEffect(() => {\n                if (!instance.isUnmounted) update()\n              }, parentSuspense)\n            })\n            return\n          }\n        }\n\n        // updateComponent\n        // This is triggered by mutation of component's own state (next: null)\n        // OR parent calling processComponent (next: VNode)\n        let originNext = next\n        let vnodeHook: VNodeHook | null | undefined\n        if (__DEV__) {\n          pushWarningContext(next || instance.vnode)\n        }\n\n        // Disallow component effect recursion during pre-lifecycle hooks.\n        toggleRecurse(instance, false)\n        if (next) {\n          next.el = vnode.el\n          updateComponentPreRender(instance, next, optimized)\n        } else {\n          next = vnode\n        }\n\n        // beforeUpdate hook\n        if (bu) {\n          invokeArrayFns(bu)\n        }\n        // onVnodeBeforeUpdate\n        if ((vnodeHook = next.props && next.props.onVnodeBeforeUpdate)) {\n          invokeVNodeHook(vnodeHook, parent, next, vnode)\n        }\n        if (\n          __COMPAT__ &&\n          isCompatEnabled(DeprecationTypes.INSTANCE_EVENT_HOOKS, instance)\n        ) {\n          instance.emit('hook:beforeUpdate')\n        }\n        toggleRecurse(instance, true)\n\n        // render\n        if (__DEV__) {\n          startMeasure(instance, `render`)\n        }\n        const nextTree = renderComponentRoot(instance)\n        if (__DEV__) {\n          endMeasure(instance, `render`)\n        }\n        const prevTree = instance.subTree\n        instance.subTree = nextTree\n\n        if (__DEV__) {\n          startMeasure(instance, `patch`)\n        }\n        patch(\n          prevTree,\n          nextTree,\n          // parent may have changed if it's in a teleport\n          hostParentNode(prevTree.el!)!,\n          // anchor may have changed if it's in a fragment\n          getNextHostNode(prevTree),\n          instance,\n          parentSuspense,\n          namespace,\n        )\n        if (__DEV__) {\n          endMeasure(instance, `patch`)\n        }\n        next.el = nextTree.el\n        if (originNext === null) {\n          // self-triggered update. In case of HOC, update parent component\n          // vnode el. HOC is indicated by parent instance's subTree pointing\n          // to child component's vnode\n          updateHOCHostEl(instance, nextTree.el)\n        }\n        // updated hook\n        if (u) {\n          queuePostRenderEffect(u, parentSuspense)\n        }\n        // onVnodeUpdated\n        if ((vnodeHook = next.props && next.props.onVnodeUpdated)) {\n          queuePostRenderEffect(\n            () => invokeVNodeHook(vnodeHook!, parent, next!, vnode),\n            parentSuspense,\n          )\n        }\n        if (\n          __COMPAT__ &&\n          isCompatEnabled(DeprecationTypes.INSTANCE_EVENT_HOOKS, instance)\n        ) {\n          queuePostRenderEffect(\n            () => instance.emit('hook:updated'),\n            parentSuspense,\n          )\n        }\n\n        if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {\n          devtoolsComponentUpdated(instance)\n        }\n\n        if (__DEV__) {\n          popWarningContext()\n        }\n      }\n    }\n\n    // create reactive effect for rendering\n    instance.scope.on()\n    const effect = (instance.effect = new ReactiveEffect(componentUpdateFn))\n    instance.scope.off()\n\n    const update = (instance.update = effect.run.bind(effect))\n    const job: SchedulerJob = (instance.job = effect.runIfDirty.bind(effect))\n    job.i = instance\n    job.id = instance.uid\n    effect.scheduler = () => queueJob(job)\n\n    // allowRecurse\n    // #1801, #2043 component render effects should allow recursive updates\n    toggleRecurse(instance, true)\n\n    if (__DEV__) {\n      effect.onTrack = instance.rtc\n        ? e => invokeArrayFns(instance.rtc!, e)\n        : void 0\n      effect.onTrigger = instance.rtg\n        ? e => invokeArrayFns(instance.rtg!, e)\n        : void 0\n    }\n\n    update()\n  }\n\n  const updateComponentPreRender = (\n    instance: ComponentInternalInstance,\n    nextVNode: VNode,\n    optimized: boolean,\n  ) => {\n    nextVNode.component = instance\n    const prevProps = instance.vnode.props\n    instance.vnode = nextVNode\n    instance.next = null\n    updateProps(instance, nextVNode.props, prevProps, optimized)\n    updateSlots(instance, nextVNode.children, optimized)\n\n    pauseTracking()\n    // props update may have triggered pre-flush watchers.\n    // flush them before the render update.\n    flushPreFlushCbs(instance)\n    resetTracking()\n  }\n\n  const patchChildren: PatchChildrenFn = (\n    n1,\n    n2,\n    container,\n    anchor,\n    parentComponent,\n    parentSuspense,\n    namespace: ElementNamespace,\n    slotScopeIds,\n    optimized = false,\n  ) => {\n    const c1 = n1 && n1.children\n    const prevShapeFlag = n1 ? n1.shapeFlag : 0\n    const c2 = n2.children\n\n    const { patchFlag, shapeFlag } = n2\n    // fast path\n    if (patchFlag > 0) {\n      if (patchFlag & PatchFlags.KEYED_FRAGMENT) {\n        // this could be either fully-keyed or mixed (some keyed some not)\n        // presence of patchFlag means children are guaranteed to be arrays\n        patchKeyedChildren(\n          c1 as VNode[],\n          c2 as VNodeArrayChildren,\n          container,\n          anchor,\n          parentComponent,\n          parentSuspense,\n          namespace,\n          slotScopeIds,\n          optimized,\n        )\n        return\n      } else if (patchFlag & PatchFlags.UNKEYED_FRAGMENT) {\n        // unkeyed\n        patchUnkeyedChildren(\n          c1 as VNode[],\n          c2 as VNodeArrayChildren,\n          container,\n          anchor,\n          parentComponent,\n          parentSuspense,\n          namespace,\n          slotScopeIds,\n          optimized,\n        )\n        return\n      }\n    }\n\n    // children has 3 possibilities: text, array or no children.\n    if (shapeFlag & ShapeFlags.TEXT_CHILDREN) {\n      // text children fast path\n      if (prevShapeFlag & ShapeFlags.ARRAY_CHILDREN) {\n        unmountChildren(c1 as VNode[], parentComponent, parentSuspense)\n      }\n      if (c2 !== c1) {\n        hostSetElementText(container, c2 as string)\n      }\n    } else {\n      if (prevShapeFlag & ShapeFlags.ARRAY_CHILDREN) {\n        // prev children was array\n        if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) {\n          // two arrays, cannot assume anything, do full diff\n          patchKeyedChildren(\n            c1 as VNode[],\n            c2 as VNodeArrayChildren,\n            container,\n            anchor,\n            parentComponent,\n            parentSuspense,\n            namespace,\n            slotScopeIds,\n            optimized,\n          )\n        } else {\n          // no new children, just unmount old\n          unmountChildren(c1 as VNode[], parentComponent, parentSuspense, true)\n        }\n      } else {\n        // prev children was text OR null\n        // new children is array OR null\n        if (prevShapeFlag & ShapeFlags.TEXT_CHILDREN) {\n          hostSetElementText(container, '')\n        }\n        // mount new if array\n        if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) {\n          mountChildren(\n            c2 as VNodeArrayChildren,\n            container,\n            anchor,\n            parentComponent,\n            parentSuspense,\n            namespace,\n            slotScopeIds,\n            optimized,\n          )\n        }\n      }\n    }\n  }\n\n  const patchUnkeyedChildren = (\n    c1: VNode[],\n    c2: VNodeArrayChildren,\n    container: RendererElement,\n    anchor: RendererNode | null,\n    parentComponent: ComponentInternalInstance | null,\n    parentSuspense: SuspenseBoundary | null,\n    namespace: ElementNamespace,\n    slotScopeIds: string[] | null,\n    optimized: boolean,\n  ) => {\n    c1 = c1 || EMPTY_ARR\n    c2 = c2 || EMPTY_ARR\n    const oldLength = c1.length\n    const newLength = c2.length\n    const commonLength = Math.min(oldLength, newLength)\n    let i\n    for (i = 0; i < commonLength; i++) {\n      const nextChild = (c2[i] = optimized\n        ? cloneIfMounted(c2[i] as VNode)\n        : normalizeVNode(c2[i]))\n      patch(\n        c1[i],\n        nextChild,\n        container,\n        null,\n        parentComponent,\n        parentSuspense,\n        namespace,\n        slotScopeIds,\n        optimized,\n      )\n    }\n    if (oldLength > newLength) {\n      // remove old\n      unmountChildren(\n        c1,\n        parentComponent,\n        parentSuspense,\n        true,\n        false,\n        commonLength,\n      )\n    } else {\n      // mount new\n      mountChildren(\n        c2,\n        container,\n        anchor,\n        parentComponent,\n        parentSuspense,\n        namespace,\n        slotScopeIds,\n        optimized,\n        commonLength,\n      )\n    }\n  }\n\n  // can be all-keyed or mixed\n  const patchKeyedChildren = (\n    c1: VNode[],\n    c2: VNodeArrayChildren,\n    container: RendererElement,\n    parentAnchor: RendererNode | null,\n    parentComponent: ComponentInternalInstance | null,\n    parentSuspense: SuspenseBoundary | null,\n    namespace: ElementNamespace,\n    slotScopeIds: string[] | null,\n    optimized: boolean,\n  ) => {\n    let i = 0\n    const l2 = c2.length\n    let e1 = c1.length - 1 // prev ending index\n    let e2 = l2 - 1 // next ending index\n\n    // 1. sync from start\n    // (a b) c\n    // (a b) d e\n    while (i <= e1 && i <= e2) {\n      const n1 = c1[i]\n      const n2 = (c2[i] = optimized\n        ? cloneIfMounted(c2[i] as VNode)\n        : normalizeVNode(c2[i]))\n      if (isSameVNodeType(n1, n2)) {\n        patch(\n          n1,\n          n2,\n          container,\n          null,\n          parentComponent,\n          parentSuspense,\n          namespace,\n          slotScopeIds,\n          optimized,\n        )\n      } else {\n        break\n      }\n      i++\n    }\n\n    // 2. sync from end\n    // a (b c)\n    // d e (b c)\n    while (i <= e1 && i <= e2) {\n      const n1 = c1[e1]\n      const n2 = (c2[e2] = optimized\n        ? cloneIfMounted(c2[e2] as VNode)\n        : normalizeVNode(c2[e2]))\n      if (isSameVNodeType(n1, n2)) {\n        patch(\n          n1,\n          n2,\n          container,\n          null,\n          parentComponent,\n          parentSuspense,\n          namespace,\n          slotScopeIds,\n          optimized,\n        )\n      } else {\n        break\n      }\n      e1--\n      e2--\n    }\n\n    // 3. common sequence + mount\n    // (a b)\n    // (a b) c\n    // i = 2, e1 = 1, e2 = 2\n    // (a b)\n    // c (a b)\n    // i = 0, e1 = -1, e2 = 0\n    if (i > e1) {\n      if (i <= e2) {\n        const nextPos = e2 + 1\n        const anchor = nextPos < l2 ? (c2[nextPos] as VNode).el : parentAnchor\n        while (i <= e2) {\n          patch(\n            null,\n            (c2[i] = optimized\n              ? cloneIfMounted(c2[i] as VNode)\n              : normalizeVNode(c2[i])),\n            container,\n            anchor,\n            parentComponent,\n            parentSuspense,\n            namespace,\n            slotScopeIds,\n            optimized,\n          )\n          i++\n        }\n      }\n    }\n\n    // 4. common sequence + unmount\n    // (a b) c\n    // (a b)\n    // i = 2, e1 = 2, e2 = 1\n    // a (b c)\n    // (b c)\n    // i = 0, e1 = 0, e2 = -1\n    else if (i > e2) {\n      while (i <= e1) {\n        unmount(c1[i], parentComponent, parentSuspense, true)\n        i++\n      }\n    }\n\n    // 5. unknown sequence\n    // [i ... e1 + 1]: a b [c d e] f g\n    // [i ... e2 + 1]: a b [e d c h] f g\n    // i = 2, e1 = 4, e2 = 5\n    else {\n      const s1 = i // prev starting index\n      const s2 = i // next starting index\n\n      // 5.1 build key:index map for newChildren\n      const keyToNewIndexMap: Map<PropertyKey, number> = new Map()\n      for (i = s2; i <= e2; i++) {\n        const nextChild = (c2[i] = optimized\n          ? cloneIfMounted(c2[i] as VNode)\n          : normalizeVNode(c2[i]))\n        if (nextChild.key != null) {\n          if (__DEV__ && keyToNewIndexMap.has(nextChild.key)) {\n            warn(\n              `Duplicate keys found during update:`,\n              JSON.stringify(nextChild.key),\n              `Make sure keys are unique.`,\n            )\n          }\n          keyToNewIndexMap.set(nextChild.key, i)\n        }\n      }\n\n      // 5.2 loop through old children left to be patched and try to patch\n      // matching nodes & remove nodes that are no longer present\n      let j\n      let patched = 0\n      const toBePatched = e2 - s2 + 1\n      let moved = false\n      // used to track whether any node has moved\n      let maxNewIndexSoFar = 0\n      // works as Map<newIndex, oldIndex>\n      // Note that oldIndex is offset by +1\n      // and oldIndex = 0 is a special value indicating the new node has\n      // no corresponding old node.\n      // used for determining longest stable subsequence\n      const newIndexToOldIndexMap = new Array(toBePatched)\n      for (i = 0; i < toBePatched; i++) newIndexToOldIndexMap[i] = 0\n\n      for (i = s1; i <= e1; i++) {\n        const prevChild = c1[i]\n        if (patched >= toBePatched) {\n          // all new children have been patched so this can only be a removal\n          unmount(prevChild, parentComponent, parentSuspense, true)\n          continue\n        }\n        let newIndex\n        if (prevChild.key != null) {\n          newIndex = keyToNewIndexMap.get(prevChild.key)\n        } else {\n          // key-less node, try to locate a key-less node of the same type\n          for (j = s2; j <= e2; j++) {\n            if (\n              newIndexToOldIndexMap[j - s2] === 0 &&\n              isSameVNodeType(prevChild, c2[j] as VNode)\n            ) {\n              newIndex = j\n              break\n            }\n          }\n        }\n        if (newIndex === undefined) {\n          unmount(prevChild, parentComponent, parentSuspense, true)\n        } else {\n          newIndexToOldIndexMap[newIndex - s2] = i + 1\n          if (newIndex >= maxNewIndexSoFar) {\n            maxNewIndexSoFar = newIndex\n          } else {\n            moved = true\n          }\n          patch(\n            prevChild,\n            c2[newIndex] as VNode,\n            container,\n            null,\n            parentComponent,\n            parentSuspense,\n            namespace,\n            slotScopeIds,\n            optimized,\n          )\n          patched++\n        }\n      }\n\n      // 5.3 move and mount\n      // generate longest stable subsequence only when nodes have moved\n      const increasingNewIndexSequence = moved\n        ? getSequence(newIndexToOldIndexMap)\n        : EMPTY_ARR\n      j = increasingNewIndexSequence.length - 1\n      // looping backwards so that we can use last patched node as anchor\n      for (i = toBePatched - 1; i >= 0; i--) {\n        const nextIndex = s2 + i\n        const nextChild = c2[nextIndex] as VNode\n        const anchorVNode = c2[nextIndex + 1] as VNode\n        const anchor =\n          nextIndex + 1 < l2\n            ? // #13559, #14173 fallback to el placeholder for unresolved async component\n              anchorVNode.el || resolveAsyncComponentPlaceholder(anchorVNode)\n            : parentAnchor\n        if (newIndexToOldIndexMap[i] === 0) {\n          // mount new\n          patch(\n            null,\n            nextChild,\n            container,\n            anchor,\n            parentComponent,\n            parentSuspense,\n            namespace,\n            slotScopeIds,\n            optimized,\n          )\n        } else if (moved) {\n          // move if:\n          // There is no stable subsequence (e.g. a reverse)\n          // OR current node is not among the stable sequence\n          if (j < 0 || i !== increasingNewIndexSequence[j]) {\n            move(nextChild, container, anchor, MoveType.REORDER)\n          } else {\n            j--\n          }\n        }\n      }\n    }\n  }\n\n  const move: MoveFn = (\n    vnode,\n    container,\n    anchor,\n    moveType,\n    parentSuspense = null,\n  ) => {\n    const { el, type, transition, children, shapeFlag } = vnode\n    if (shapeFlag & ShapeFlags.COMPONENT) {\n      move(vnode.component!.subTree, container, anchor, moveType)\n      return\n    }\n\n    if (__FEATURE_SUSPENSE__ && shapeFlag & ShapeFlags.SUSPENSE) {\n      vnode.suspense!.move(container, anchor, moveType)\n      return\n    }\n\n    if (shapeFlag & ShapeFlags.TELEPORT) {\n      ;(type as typeof TeleportImpl).move(vnode, container, anchor, internals)\n      return\n    }\n\n    if (type === Fragment) {\n      hostInsert(el!, container, anchor)\n      for (let i = 0; i < (children as VNode[]).length; i++) {\n        move((children as VNode[])[i], container, anchor, moveType)\n      }\n      hostInsert(vnode.anchor!, container, anchor)\n      return\n    }\n\n    if (type === Static) {\n      moveStaticNode(vnode, container, anchor)\n      return\n    }\n\n    // single nodes\n    const needTransition =\n      moveType !== MoveType.REORDER &&\n      shapeFlag & ShapeFlags.ELEMENT &&\n      transition\n    if (needTransition) {\n      if (moveType === MoveType.ENTER) {\n        transition!.beforeEnter(el!)\n        hostInsert(el!, container, anchor)\n        queuePostRenderEffect(() => transition!.enter(el!), parentSuspense)\n      } else {\n        const { leave, delayLeave, afterLeave } = transition!\n        const remove = () => {\n          if (vnode.ctx!.isUnmounted) {\n            hostRemove(el!)\n          } else {\n            hostInsert(el!, container, anchor)\n          }\n        }\n        const performLeave = () => {\n          // #13153 move kept-alive node before v-show transition leave finishes\n          // it needs to call the leaving callback to ensure element's `display`\n          // is `none`\n          if (el!._isLeaving) {\n            el![leaveCbKey](true /* cancelled */)\n          }\n          leave(el!, () => {\n            remove()\n            afterLeave && afterLeave()\n          })\n        }\n        if (delayLeave) {\n          delayLeave(el!, remove, performLeave)\n        } else {\n          performLeave()\n        }\n      }\n    } else {\n      hostInsert(el!, container, anchor)\n    }\n  }\n\n  const unmount: UnmountFn = (\n    vnode,\n    parentComponent,\n    parentSuspense,\n    doRemove = false,\n    optimized = false,\n  ) => {\n    const {\n      type,\n      props,\n      ref,\n      children,\n      dynamicChildren,\n      shapeFlag,\n      patchFlag,\n      dirs,\n      cacheIndex,\n    } = vnode\n\n    if (patchFlag === PatchFlags.BAIL) {\n      optimized = false\n    }\n\n    // unset ref\n    if (ref != null) {\n      pauseTracking()\n      setRef(ref, null, parentSuspense, vnode, true)\n      resetTracking()\n    }\n\n    // #6593 should clean memo cache when unmount\n    if (cacheIndex != null) {\n      parentComponent!.renderCache[cacheIndex] = undefined\n    }\n\n    if (shapeFlag & ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE) {\n      ;(parentComponent!.ctx as KeepAliveContext).deactivate(vnode)\n      return\n    }\n\n    const shouldInvokeDirs = shapeFlag & ShapeFlags.ELEMENT && dirs\n    const shouldInvokeVnodeHook = !isAsyncWrapper(vnode)\n\n    let vnodeHook: VNodeHook | undefined | null\n    if (\n      shouldInvokeVnodeHook &&\n      (vnodeHook = props && props.onVnodeBeforeUnmount)\n    ) {\n      invokeVNodeHook(vnodeHook, parentComponent, vnode)\n    }\n\n    if (shapeFlag & ShapeFlags.COMPONENT) {\n      unmountComponent(vnode.component!, parentSuspense, doRemove)\n    } else {\n      if (__FEATURE_SUSPENSE__ && shapeFlag & ShapeFlags.SUSPENSE) {\n        vnode.suspense!.unmount(parentSuspense, doRemove)\n        return\n      }\n\n      if (shouldInvokeDirs) {\n        invokeDirectiveHook(vnode, null, parentComponent, 'beforeUnmount')\n      }\n\n      if (shapeFlag & ShapeFlags.TELEPORT) {\n        ;(vnode.type as typeof TeleportImpl).remove(\n          vnode,\n          parentComponent,\n          parentSuspense,\n          internals,\n          doRemove,\n        )\n      } else if (\n        dynamicChildren &&\n        // #5154\n        // when v-once is used inside a block, setBlockTracking(-1) marks the\n        // parent block with hasOnce: true\n        // so that it doesn't take the fast path during unmount - otherwise\n        // components nested in v-once are never unmounted.\n        !dynamicChildren.hasOnce &&\n        // #1153: fast path should not be taken for non-stable (v-for) fragments\n        (type !== Fragment ||\n          (patchFlag > 0 && patchFlag & PatchFlags.STABLE_FRAGMENT))\n      ) {\n        // fast path for block nodes: only need to unmount dynamic children.\n        unmountChildren(\n          dynamicChildren,\n          parentComponent,\n          parentSuspense,\n          false,\n          true,\n        )\n      } else if (\n        (type === Fragment &&\n          patchFlag &\n            (PatchFlags.KEYED_FRAGMENT | PatchFlags.UNKEYED_FRAGMENT)) ||\n        (!optimized && shapeFlag & ShapeFlags.ARRAY_CHILDREN)\n      ) {\n        unmountChildren(children as VNode[], parentComponent, parentSuspense)\n      }\n\n      if (doRemove) {\n        remove(vnode)\n      }\n    }\n\n    if (\n      (shouldInvokeVnodeHook &&\n        (vnodeHook = props && props.onVnodeUnmounted)) ||\n      shouldInvokeDirs\n    ) {\n      queuePostRenderEffect(() => {\n        vnodeHook && invokeVNodeHook(vnodeHook, parentComponent, vnode)\n        shouldInvokeDirs &&\n          invokeDirectiveHook(vnode, null, parentComponent, 'unmounted')\n      }, parentSuspense)\n    }\n  }\n\n  const remove: RemoveFn = vnode => {\n    const { type, el, anchor, transition } = vnode\n    if (type === Fragment) {\n      if (\n        __DEV__ &&\n        vnode.patchFlag > 0 &&\n        vnode.patchFlag & PatchFlags.DEV_ROOT_FRAGMENT &&\n        transition &&\n        !transition.persisted\n      ) {\n        ;(vnode.children as VNode[]).forEach(child => {\n          if (child.type === Comment) {\n            hostRemove(child.el!)\n          } else {\n            remove(child)\n          }\n        })\n      } else {\n        removeFragment(el!, anchor!)\n      }\n      return\n    }\n\n    if (type === Static) {\n      removeStaticNode(vnode)\n      return\n    }\n\n    const performRemove = () => {\n      hostRemove(el!)\n      if (transition && !transition.persisted && transition.afterLeave) {\n        transition.afterLeave()\n      }\n    }\n\n    if (\n      vnode.shapeFlag & ShapeFlags.ELEMENT &&\n      transition &&\n      !transition.persisted\n    ) {\n      const { leave, delayLeave } = transition\n      const performLeave = () => leave(el!, performRemove)\n      if (delayLeave) {\n        delayLeave(vnode.el!, performRemove, performLeave)\n      } else {\n        performLeave()\n      }\n    } else {\n      performRemove()\n    }\n  }\n\n  const removeFragment = (cur: RendererNode, end: RendererNode) => {\n    // For fragments, directly remove all contained DOM nodes.\n    // (fragment child nodes cannot have transition)\n    let next\n    while (cur !== end) {\n      next = hostNextSibling(cur)!\n      hostRemove(cur)\n      cur = next\n    }\n    hostRemove(end)\n  }\n\n  const unmountComponent = (\n    instance: ComponentInternalInstance,\n    parentSuspense: SuspenseBoundary | null,\n    doRemove?: boolean,\n  ) => {\n    if (__DEV__ && instance.type.__hmrId) {\n      unregisterHMR(instance)\n    }\n\n    const { bum, scope, job, subTree, um, m, a } = instance\n    invalidateMount(m)\n    invalidateMount(a)\n\n    // beforeUnmount hook\n    if (bum) {\n      invokeArrayFns(bum)\n    }\n\n    if (\n      __COMPAT__ &&\n      isCompatEnabled(DeprecationTypes.INSTANCE_EVENT_HOOKS, instance)\n    ) {\n      instance.emit('hook:beforeDestroy')\n    }\n\n    // stop effects in component scope\n    scope.stop()\n\n    // job may be null if a component is unmounted before its async\n    // setup has resolved.\n    if (job) {\n      // so that scheduler will no longer invoke it\n      job.flags! |= SchedulerJobFlags.DISPOSED\n      unmount(subTree, instance, parentSuspense, doRemove)\n    }\n    // unmounted hook\n    if (um) {\n      queuePostRenderEffect(um, parentSuspense)\n    }\n    if (\n      __COMPAT__ &&\n      isCompatEnabled(DeprecationTypes.INSTANCE_EVENT_HOOKS, instance)\n    ) {\n      queuePostRenderEffect(\n        () => instance.emit('hook:destroyed'),\n        parentSuspense,\n      )\n    }\n    queuePostRenderEffect(() => {\n      instance.isUnmounted = true\n    }, parentSuspense)\n\n    if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {\n      devtoolsComponentRemoved(instance)\n    }\n  }\n\n  const unmountChildren: UnmountChildrenFn = (\n    children,\n    parentComponent,\n    parentSuspense,\n    doRemove = false,\n    optimized = false,\n    start = 0,\n  ) => {\n    for (let i = start; i < children.length; i++) {\n      unmount(children[i], parentComponent, parentSuspense, doRemove, optimized)\n    }\n  }\n\n  const getNextHostNode: NextFn = vnode => {\n    if (vnode.shapeFlag & ShapeFlags.COMPONENT) {\n      return getNextHostNode(vnode.component!.subTree)\n    }\n    if (__FEATURE_SUSPENSE__ && vnode.shapeFlag & ShapeFlags.SUSPENSE) {\n      return vnode.suspense!.next()\n    }\n    const el = hostNextSibling((vnode.anchor || vnode.el)!)\n    // #9071, #9313\n    // teleported content can mess up nextSibling searches during patch so\n    // we need to skip them during nextSibling search\n    const teleportEnd = el && el[TeleportEndKey]\n    return teleportEnd ? hostNextSibling(teleportEnd) : el\n  }\n\n  let isFlushing = false\n  const render: RootRenderFunction = (vnode, container, namespace) => {\n    let instance\n    if (vnode == null) {\n      if (container._vnode) {\n        unmount(container._vnode, null, null, true)\n        instance = container._vnode.component\n      }\n    } else {\n      patch(\n        container._vnode || null,\n        vnode,\n        container,\n        null,\n        null,\n        null,\n        namespace,\n      )\n    }\n    container._vnode = vnode\n    if (!isFlushing) {\n      isFlushing = true\n      flushPreFlushCbs(instance)\n      flushPostFlushCbs()\n      isFlushing = false\n    }\n  }\n\n  const internals: RendererInternals = {\n    p: patch,\n    um: unmount,\n    m: move,\n    r: remove,\n    mt: mountComponent,\n    mc: mountChildren,\n    pc: patchChildren,\n    pbc: patchBlockChildren,\n    n: getNextHostNode,\n    o: options,\n  }\n\n  let hydrate: ReturnType<typeof createHydrationFunctions>[0] | undefined\n  let hydrateNode: ReturnType<typeof createHydrationFunctions>[1] | undefined\n  if (createHydrationFns) {\n    ;[hydrate, hydrateNode] = createHydrationFns(\n      internals as RendererInternals<Node, Element>,\n    )\n  }\n\n  return {\n    render,\n    hydrate,\n    createApp: createAppAPI(render, hydrate),\n  }\n}\n\nfunction resolveChildrenNamespace(\n  { type, props }: VNode,\n  currentNamespace: ElementNamespace,\n): ElementNamespace {\n  return (currentNamespace === 'svg' && type === 'foreignObject') ||\n    (currentNamespace === 'mathml' &&\n      type === 'annotation-xml' &&\n      props &&\n      props.encoding &&\n      props.encoding.includes('html'))\n    ? undefined\n    : currentNamespace\n}\n\nfunction toggleRecurse(\n  { effect, job }: ComponentInternalInstance,\n  allowed: boolean,\n) {\n  if (allowed) {\n    effect.flags |= EffectFlags.ALLOW_RECURSE\n    job.flags! |= SchedulerJobFlags.ALLOW_RECURSE\n  } else {\n    effect.flags &= ~EffectFlags.ALLOW_RECURSE\n    job.flags! &= ~SchedulerJobFlags.ALLOW_RECURSE\n  }\n}\n\nexport function needTransition(\n  parentSuspense: SuspenseBoundary | null,\n  transition: TransitionHooks | null,\n): boolean | null {\n  return (\n    (!parentSuspense || (parentSuspense && !parentSuspense.pendingBranch)) &&\n    transition &&\n    !transition.persisted\n  )\n}\n\n/**\n * #1156\n * When a component is HMR-enabled, we need to make sure that all static nodes\n * inside a block also inherit the DOM element from the previous tree so that\n * HMR updates (which are full updates) can retrieve the element for patching.\n *\n * #2080\n * Inside keyed `template` fragment static children, if a fragment is moved,\n * the children will always be moved. Therefore, in order to ensure correct move\n * position, el should be inherited from previous nodes.\n */\nexport function traverseStaticChildren(\n  n1: VNode,\n  n2: VNode,\n  shallow = false,\n): void {\n  const ch1 = n1.children\n  const ch2 = n2.children\n  if (isArray(ch1) && isArray(ch2)) {\n    for (let i = 0; i < ch1.length; i++) {\n      // this is only called in the optimized path so array children are\n      // guaranteed to be vnodes\n      const c1 = ch1[i] as VNode\n      let c2 = ch2[i] as VNode\n      if (c2.shapeFlag & ShapeFlags.ELEMENT && !c2.dynamicChildren) {\n        if (c2.patchFlag <= 0 || c2.patchFlag === PatchFlags.NEED_HYDRATION) {\n          c2 = ch2[i] = cloneIfMounted(ch2[i] as VNode)\n          c2.el = c1.el\n        }\n        if (!shallow && c2.patchFlag !== PatchFlags.BAIL)\n          traverseStaticChildren(c1, c2)\n      }\n      // #6852 also inherit for text nodes\n      if (c2.type === Text) {\n        // avoid cached text nodes retaining detached dom nodes\n        if (c2.patchFlag === PatchFlags.CACHED) {\n          c2 = ch2[i] = cloneIfMounted(c2)\n        }\n        c2.el = c1.el\n      }\n      // #2324 also inherit for comment nodes, but not placeholders (e.g. v-if which\n      // would have received .el during block patch)\n      if (c2.type === Comment && !c2.el) {\n        c2.el = c1.el\n      }\n\n      if (__DEV__) {\n        c2.el && (c2.el.__vnode = c2)\n      }\n    }\n  }\n}\n\n// https://en.wikipedia.org/wiki/Longest_increasing_subsequence\nfunction getSequence(arr: number[]): number[] {\n  const p = arr.slice()\n  const result = [0]\n  let i, j, u, v, c\n  const len = arr.length\n  for (i = 0; i < len; i++) {\n    const arrI = arr[i]\n    if (arrI !== 0) {\n      j = result[result.length - 1]\n      if (arr[j] < arrI) {\n        p[i] = j\n        result.push(i)\n        continue\n      }\n      u = 0\n      v = result.length - 1\n      while (u < v) {\n        c = (u + v) >> 1\n        if (arr[result[c]] < arrI) {\n          u = c + 1\n        } else {\n          v = c\n        }\n      }\n      if (arrI < arr[result[u]]) {\n        if (u > 0) {\n          p[i] = result[u - 1]\n        }\n        result[u] = i\n      }\n    }\n  }\n  u = result.length\n  v = result[u - 1]\n  while (u-- > 0) {\n    result[u] = v\n    v = p[v]\n  }\n  return result\n}\n\nfunction locateNonHydratedAsyncRoot(\n  instance: ComponentInternalInstance,\n): ComponentInternalInstance | undefined {\n  const subComponent = instance.subTree.component\n  if (subComponent) {\n    if (subComponent.asyncDep && !subComponent.asyncResolved) {\n      return subComponent\n    } else {\n      return locateNonHydratedAsyncRoot(subComponent)\n    }\n  }\n}\n\nexport function invalidateMount(hooks: LifecycleHook): void {\n  if (hooks) {\n    for (let i = 0; i < hooks.length; i++)\n      hooks[i].flags! |= SchedulerJobFlags.DISPOSED\n  }\n}\n\nfunction resolveAsyncComponentPlaceholder(anchorVnode: VNode) {\n  if (anchorVnode.placeholder) {\n    return anchorVnode.placeholder\n  }\n\n  // anchor vnode maybe is a wrapper component has single unresolved async component\n  const instance = anchorVnode.component\n  if (instance) {\n    return resolveAsyncComponentPlaceholder(instance.subTree)\n  }\n\n  return null\n}\n"
  },
  {
    "path": "packages/runtime-core/src/rendererTemplateRef.ts",
    "content": "import type { SuspenseBoundary } from './components/Suspense'\nimport type {\n  VNode,\n  VNodeNormalizedRef,\n  VNodeNormalizedRefAtom,\n  VNodeRef,\n} from './vnode'\nimport {\n  EMPTY_OBJ,\n  NO,\n  ShapeFlags,\n  hasOwn,\n  isArray,\n  isFunction,\n  isString,\n  remove,\n} from '@vue/shared'\nimport { isAsyncWrapper } from './apiAsyncComponent'\nimport { warn } from './warning'\nimport { isRef, toRaw } from '@vue/reactivity'\nimport { ErrorCodes, callWithErrorHandling } from './errorHandling'\nimport { type SchedulerJob, SchedulerJobFlags } from './scheduler'\nimport { queuePostRenderEffect } from './renderer'\nimport { type ComponentOptions, getComponentPublicInstance } from './component'\nimport { isTemplateRefKey, knownTemplateRefs } from './helpers/useTemplateRef'\n\nconst pendingSetRefMap = new WeakMap<VNodeNormalizedRef, SchedulerJob>()\n/**\n * Function for handling a template ref\n */\nexport function setRef(\n  rawRef: VNodeNormalizedRef,\n  oldRawRef: VNodeNormalizedRef | null,\n  parentSuspense: SuspenseBoundary | null,\n  vnode: VNode,\n  isUnmount = false,\n): void {\n  if (isArray(rawRef)) {\n    rawRef.forEach((r, i) =>\n      setRef(\n        r,\n        oldRawRef && (isArray(oldRawRef) ? oldRawRef[i] : oldRawRef),\n        parentSuspense,\n        vnode,\n        isUnmount,\n      ),\n    )\n    return\n  }\n\n  if (isAsyncWrapper(vnode) && !isUnmount) {\n    // #4999 if an async component already resolved and cached by KeepAlive,\n    // we need to set the ref to inner component\n    if (\n      vnode.shapeFlag & ShapeFlags.COMPONENT_KEPT_ALIVE &&\n      (vnode.type as ComponentOptions).__asyncResolved &&\n      vnode.component!.subTree.component\n    ) {\n      setRef(rawRef, oldRawRef, parentSuspense, vnode.component!.subTree)\n    }\n\n    // otherwise, nothing needs to be done because the template ref\n    // is forwarded to inner component\n    return\n  }\n\n  const refValue =\n    vnode.shapeFlag & ShapeFlags.STATEFUL_COMPONENT\n      ? getComponentPublicInstance(vnode.component!)\n      : vnode.el\n  const value = isUnmount ? null : refValue\n\n  const { i: owner, r: ref } = rawRef\n  if (__DEV__ && !owner) {\n    warn(\n      `Missing ref owner context. ref cannot be used on hoisted vnodes. ` +\n        `A vnode with ref must be created inside the render function.`,\n    )\n    return\n  }\n  const oldRef = oldRawRef && (oldRawRef as VNodeNormalizedRefAtom).r\n  const refs = owner.refs === EMPTY_OBJ ? (owner.refs = {}) : owner.refs\n  const setupState = owner.setupState\n  const rawSetupState = toRaw(setupState)\n  const canSetSetupRef =\n    setupState === EMPTY_OBJ\n      ? NO\n      : (key: string) => {\n          if (__DEV__) {\n            if (hasOwn(rawSetupState, key) && !isRef(rawSetupState[key])) {\n              warn(\n                `Template ref \"${key}\" used on a non-ref value. ` +\n                  `It will not work in the production build.`,\n              )\n            }\n\n            if (knownTemplateRefs.has(rawSetupState[key] as any)) {\n              return false\n            }\n          }\n\n          // skip setting up ref if the key is from useTemplateRef\n          if (isTemplateRefKey(refs, key)) {\n            return false\n          }\n\n          return hasOwn(rawSetupState, key)\n        }\n\n  const canSetRef = (ref: VNodeRef, key?: string) => {\n    if (__DEV__ && knownTemplateRefs.has(ref as any)) {\n      return false\n    }\n    if (key && isTemplateRefKey(refs, key)) {\n      return false\n    }\n    return true\n  }\n\n  // dynamic ref changed. unset old ref\n  if (oldRef != null && oldRef !== ref) {\n    invalidatePendingSetRef(oldRawRef!)\n    if (isString(oldRef)) {\n      refs[oldRef] = null\n      if (canSetSetupRef(oldRef)) {\n        setupState[oldRef] = null\n      }\n    } else if (isRef(oldRef)) {\n      // this type assertion is valid since `oldRef` has already been asserted to be non-null\n      const oldRawRefAtom = oldRawRef as VNodeNormalizedRefAtom\n      if (canSetRef(oldRef, oldRawRefAtom.k)) {\n        oldRef.value = null\n      }\n      if (oldRawRefAtom.k) refs[oldRawRefAtom.k] = null\n    }\n  }\n\n  if (isFunction(ref)) {\n    callWithErrorHandling(ref, owner, ErrorCodes.FUNCTION_REF, [value, refs])\n  } else {\n    const _isString = isString(ref)\n    const _isRef = isRef(ref)\n\n    if (_isString || _isRef) {\n      const doSet = () => {\n        if (rawRef.f) {\n          const existing = _isString\n            ? canSetSetupRef(ref)\n              ? setupState[ref]\n              : refs[ref]\n            : canSetRef(ref) || !rawRef.k\n              ? ref.value\n              : refs[rawRef.k]\n          if (isUnmount) {\n            isArray(existing) && remove(existing, refValue)\n          } else {\n            if (!isArray(existing)) {\n              if (_isString) {\n                refs[ref] = [refValue]\n                if (canSetSetupRef(ref)) {\n                  setupState[ref] = refs[ref]\n                }\n              } else {\n                const newVal = [refValue]\n                if (canSetRef(ref, rawRef.k)) {\n                  ref.value = newVal\n                }\n                if (rawRef.k) refs[rawRef.k] = newVal\n              }\n            } else if (!existing.includes(refValue)) {\n              existing.push(refValue)\n            }\n          }\n        } else if (_isString) {\n          refs[ref] = value\n          if (canSetSetupRef(ref)) {\n            setupState[ref] = value\n          }\n        } else if (_isRef) {\n          if (canSetRef(ref, rawRef.k)) {\n            ref.value = value\n          }\n          if (rawRef.k) refs[rawRef.k] = value\n        } else if (__DEV__) {\n          warn('Invalid template ref type:', ref, `(${typeof ref})`)\n        }\n      }\n      if (value) {\n        // #1789: for non-null values, set them after render\n        // null values means this is unmount and it should not overwrite another\n        // ref with the same key\n        const job: SchedulerJob = () => {\n          doSet()\n          pendingSetRefMap.delete(rawRef)\n        }\n        job.id = -1\n        pendingSetRefMap.set(rawRef, job)\n        queuePostRenderEffect(job, parentSuspense)\n      } else {\n        invalidatePendingSetRef(rawRef)\n        doSet()\n      }\n    } else if (__DEV__) {\n      warn('Invalid template ref type:', ref, `(${typeof ref})`)\n    }\n  }\n}\n\nfunction invalidatePendingSetRef(rawRef: VNodeNormalizedRef) {\n  const pendingSetRef = pendingSetRefMap.get(rawRef)\n  if (pendingSetRef) {\n    pendingSetRef.flags! |= SchedulerJobFlags.DISPOSED\n    pendingSetRefMap.delete(rawRef)\n  }\n}\n"
  },
  {
    "path": "packages/runtime-core/src/scheduler.ts",
    "content": "import { ErrorCodes, callWithErrorHandling, handleError } from './errorHandling'\nimport { NOOP, isArray } from '@vue/shared'\nimport { type ComponentInternalInstance, getComponentName } from './component'\n\nexport enum SchedulerJobFlags {\n  QUEUED = 1 << 0,\n  PRE = 1 << 1,\n  /**\n   * Indicates whether the effect is allowed to recursively trigger itself\n   * when managed by the scheduler.\n   *\n   * By default, a job cannot trigger itself because some built-in method calls,\n   * e.g. Array.prototype.push actually performs reads as well (#1740) which\n   * can lead to confusing infinite loops.\n   * The allowed cases are component update functions and watch callbacks.\n   * Component update functions may update child component props, which in turn\n   * trigger flush: \"pre\" watch callbacks that mutates state that the parent\n   * relies on (#1801). Watch callbacks doesn't track its dependencies so if it\n   * triggers itself again, it's likely intentional and it is the user's\n   * responsibility to perform recursive state mutation that eventually\n   * stabilizes (#1727).\n   */\n  ALLOW_RECURSE = 1 << 2,\n  DISPOSED = 1 << 3,\n}\n\nexport interface SchedulerJob extends Function {\n  id?: number\n  /**\n   * flags can technically be undefined, but it can still be used in bitwise\n   * operations just like 0.\n   */\n  flags?: SchedulerJobFlags\n  /**\n   * Attached by renderer.ts when setting up a component's render effect\n   * Used to obtain component information when reporting max recursive updates.\n   */\n  i?: ComponentInternalInstance\n}\n\nexport type SchedulerJobs = SchedulerJob | SchedulerJob[]\n\nconst queue: SchedulerJob[] = []\nlet flushIndex = -1\n\nconst pendingPostFlushCbs: SchedulerJob[] = []\nlet activePostFlushCbs: SchedulerJob[] | null = null\nlet postFlushIndex = 0\n\nconst resolvedPromise = /*@__PURE__*/ Promise.resolve() as Promise<any>\nlet currentFlushPromise: Promise<void> | null = null\n\nconst RECURSION_LIMIT = 100\ntype CountMap = Map<SchedulerJob, number>\n\nexport function nextTick(): Promise<void>\nexport function nextTick<T, R>(\n  this: T,\n  fn: (this: T) => R | Promise<R>,\n): Promise<R>\nexport function nextTick<T, R>(\n  this: T,\n  fn?: (this: T) => R | Promise<R>,\n): Promise<void | R> {\n  const p = currentFlushPromise || resolvedPromise\n  return fn ? p.then(this ? fn.bind(this) : fn) : p\n}\n\n// Use binary-search to find a suitable position in the queue. The queue needs\n// to be sorted in increasing order of the job ids. This ensures that:\n// 1. Components are updated from parent to child. As the parent is always\n//    created before the child it will always have a smaller id.\n// 2. If a component is unmounted during a parent component's update, its update\n//    can be skipped.\n// A pre watcher will have the same id as its component's update job. The\n// watcher should be inserted immediately before the update job. This allows\n// watchers to be skipped if the component is unmounted by the parent update.\nfunction findInsertionIndex(id: number) {\n  let start = flushIndex + 1\n  let end = queue.length\n\n  while (start < end) {\n    const middle = (start + end) >>> 1\n    const middleJob = queue[middle]\n    const middleJobId = getId(middleJob)\n    if (\n      middleJobId < id ||\n      (middleJobId === id && middleJob.flags! & SchedulerJobFlags.PRE)\n    ) {\n      start = middle + 1\n    } else {\n      end = middle\n    }\n  }\n\n  return start\n}\n\nexport function queueJob(job: SchedulerJob): void {\n  if (!(job.flags! & SchedulerJobFlags.QUEUED)) {\n    const jobId = getId(job)\n    const lastJob = queue[queue.length - 1]\n    if (\n      !lastJob ||\n      // fast path when the job id is larger than the tail\n      (!(job.flags! & SchedulerJobFlags.PRE) && jobId >= getId(lastJob))\n    ) {\n      queue.push(job)\n    } else {\n      queue.splice(findInsertionIndex(jobId), 0, job)\n    }\n\n    job.flags! |= SchedulerJobFlags.QUEUED\n\n    queueFlush()\n  }\n}\n\nfunction queueFlush() {\n  if (!currentFlushPromise) {\n    currentFlushPromise = resolvedPromise.then(flushJobs)\n  }\n}\n\nexport function queuePostFlushCb(cb: SchedulerJobs): void {\n  if (!isArray(cb)) {\n    if (activePostFlushCbs && cb.id === -1) {\n      activePostFlushCbs.splice(postFlushIndex + 1, 0, cb)\n    } else if (!(cb.flags! & SchedulerJobFlags.QUEUED)) {\n      pendingPostFlushCbs.push(cb)\n      cb.flags! |= SchedulerJobFlags.QUEUED\n    }\n  } else {\n    // if cb is an array, it is a component lifecycle hook which can only be\n    // triggered by a job, which is already deduped in the main queue, so\n    // we can skip duplicate check here to improve perf\n    pendingPostFlushCbs.push(...cb)\n  }\n  queueFlush()\n}\n\nexport function flushPreFlushCbs(\n  instance?: ComponentInternalInstance,\n  seen?: CountMap,\n  // skip the current job\n  i: number = flushIndex + 1,\n): void {\n  if (__DEV__) {\n    seen = seen || new Map()\n  }\n  for (; i < queue.length; i++) {\n    const cb = queue[i]\n    if (cb && cb.flags! & SchedulerJobFlags.PRE) {\n      if (instance && cb.id !== instance.uid) {\n        continue\n      }\n      if (__DEV__ && checkRecursiveUpdates(seen!, cb)) {\n        continue\n      }\n      queue.splice(i, 1)\n      i--\n      if (cb.flags! & SchedulerJobFlags.ALLOW_RECURSE) {\n        cb.flags! &= ~SchedulerJobFlags.QUEUED\n      }\n      cb()\n      if (!(cb.flags! & SchedulerJobFlags.ALLOW_RECURSE)) {\n        cb.flags! &= ~SchedulerJobFlags.QUEUED\n      }\n    }\n  }\n}\n\nexport function flushPostFlushCbs(seen?: CountMap): void {\n  if (pendingPostFlushCbs.length) {\n    const deduped = [...new Set(pendingPostFlushCbs)].sort(\n      (a, b) => getId(a) - getId(b),\n    )\n    pendingPostFlushCbs.length = 0\n\n    // #1947 already has active queue, nested flushPostFlushCbs call\n    if (activePostFlushCbs) {\n      activePostFlushCbs.push(...deduped)\n      return\n    }\n\n    activePostFlushCbs = deduped\n    if (__DEV__) {\n      seen = seen || new Map()\n    }\n\n    for (\n      postFlushIndex = 0;\n      postFlushIndex < activePostFlushCbs.length;\n      postFlushIndex++\n    ) {\n      const cb = activePostFlushCbs[postFlushIndex]\n      if (__DEV__ && checkRecursiveUpdates(seen!, cb)) {\n        continue\n      }\n      if (cb.flags! & SchedulerJobFlags.ALLOW_RECURSE) {\n        cb.flags! &= ~SchedulerJobFlags.QUEUED\n      }\n      if (!(cb.flags! & SchedulerJobFlags.DISPOSED)) cb()\n      cb.flags! &= ~SchedulerJobFlags.QUEUED\n    }\n    activePostFlushCbs = null\n    postFlushIndex = 0\n  }\n}\n\nconst getId = (job: SchedulerJob): number =>\n  job.id == null ? (job.flags! & SchedulerJobFlags.PRE ? -1 : Infinity) : job.id\n\nfunction flushJobs(seen?: CountMap) {\n  if (__DEV__) {\n    seen = seen || new Map()\n  }\n\n  // conditional usage of checkRecursiveUpdate must be determined out of\n  // try ... catch block since Rollup by default de-optimizes treeshaking\n  // inside try-catch. This can leave all warning code unshaked. Although\n  // they would get eventually shaken by a minifier like terser, some minifiers\n  // would fail to do that (e.g. https://github.com/evanw/esbuild/issues/1610)\n  const check = __DEV__\n    ? (job: SchedulerJob) => checkRecursiveUpdates(seen!, job)\n    : NOOP\n\n  try {\n    for (flushIndex = 0; flushIndex < queue.length; flushIndex++) {\n      const job = queue[flushIndex]\n      if (job && !(job.flags! & SchedulerJobFlags.DISPOSED)) {\n        if (__DEV__ && check(job)) {\n          continue\n        }\n        if (job.flags! & SchedulerJobFlags.ALLOW_RECURSE) {\n          job.flags! &= ~SchedulerJobFlags.QUEUED\n        }\n        callWithErrorHandling(\n          job,\n          job.i,\n          job.i ? ErrorCodes.COMPONENT_UPDATE : ErrorCodes.SCHEDULER,\n        )\n        if (!(job.flags! & SchedulerJobFlags.ALLOW_RECURSE)) {\n          job.flags! &= ~SchedulerJobFlags.QUEUED\n        }\n      }\n    }\n  } finally {\n    // If there was an error we still need to clear the QUEUED flags\n    for (; flushIndex < queue.length; flushIndex++) {\n      const job = queue[flushIndex]\n      if (job) {\n        job.flags! &= ~SchedulerJobFlags.QUEUED\n      }\n    }\n\n    flushIndex = -1\n    queue.length = 0\n\n    flushPostFlushCbs(seen)\n\n    currentFlushPromise = null\n    // If new jobs have been added to either queue, keep flushing\n    if (queue.length || pendingPostFlushCbs.length) {\n      flushJobs(seen)\n    }\n  }\n}\n\nfunction checkRecursiveUpdates(seen: CountMap, fn: SchedulerJob) {\n  const count = seen.get(fn) || 0\n  if (count > RECURSION_LIMIT) {\n    const instance = fn.i\n    const componentName = instance && getComponentName(instance.type)\n    handleError(\n      `Maximum recursive updates exceeded${\n        componentName ? ` in component <${componentName}>` : ``\n      }. ` +\n        `This means you have a reactive effect that is mutating its own ` +\n        `dependencies and thus recursively triggering itself. Possible sources ` +\n        `include component template, render function, updated hook or ` +\n        `watcher source function.`,\n      null,\n      ErrorCodes.APP_ERROR_HANDLER,\n    )\n    return true\n  }\n  seen.set(fn, count + 1)\n  return false\n}\n"
  },
  {
    "path": "packages/runtime-core/src/vnode.ts",
    "content": "import {\n  EMPTY_ARR,\n  PatchFlags,\n  ShapeFlags,\n  SlotFlags,\n  extend,\n  isArray,\n  isFunction,\n  isObject,\n  isOn,\n  isString,\n  normalizeClass,\n  normalizeStyle,\n} from '@vue/shared'\nimport {\n  type ClassComponent,\n  type Component,\n  type ComponentInternalInstance,\n  type ConcreteComponent,\n  type Data,\n  isClassComponent,\n} from './component'\nimport type { RawSlots } from './componentSlots'\nimport {\n  type ReactiveFlags,\n  type Ref,\n  isProxy,\n  isRef,\n  toRaw,\n} from '@vue/reactivity'\nimport type { AppContext } from './apiCreateApp'\nimport {\n  type Suspense,\n  type SuspenseBoundary,\n  type SuspenseImpl,\n  isSuspense,\n} from './components/Suspense'\nimport type { DirectiveBinding } from './directives'\nimport {\n  type TransitionHooks,\n  setTransitionHooks,\n} from './components/BaseTransition'\nimport { warn } from './warning'\nimport {\n  type Teleport,\n  type TeleportImpl,\n  isTeleport,\n} from './components/Teleport'\nimport {\n  currentRenderingInstance,\n  currentScopeId,\n} from './componentRenderContext'\nimport type { RendererElement, RendererNode } from './renderer'\nimport { NULL_DYNAMIC_COMPONENT } from './helpers/resolveAssets'\nimport { hmrDirtyComponents } from './hmr'\nimport { convertLegacyComponent } from './compat/component'\nimport { convertLegacyVModelProps } from './compat/componentVModel'\nimport { defineLegacyVNodeProperties } from './compat/renderFn'\nimport { ErrorCodes, callWithAsyncErrorHandling } from './errorHandling'\nimport type { ComponentPublicInstance } from './componentPublicInstance'\nimport { isInternalObject } from './internalObject'\n\nexport const Fragment = Symbol.for('v-fgt') as any as {\n  __isFragment: true\n  new (): {\n    $props: VNodeProps\n  }\n}\nexport const Text: unique symbol = Symbol.for('v-txt')\nexport const Comment: unique symbol = Symbol.for('v-cmt')\nexport const Static: unique symbol = Symbol.for('v-stc')\n\nexport type VNodeTypes =\n  | string\n  | VNode\n  | Component\n  | typeof Text\n  | typeof Static\n  | typeof Comment\n  | typeof Fragment\n  | typeof Teleport\n  | typeof TeleportImpl\n  | typeof Suspense\n  | typeof SuspenseImpl\n\nexport type VNodeRef =\n  | string\n  | Ref\n  | ((\n      ref: Element | ComponentPublicInstance | null,\n      refs: Record<string, any>,\n    ) => void)\n\nexport type VNodeNormalizedRefAtom = {\n  /**\n   * component instance\n   */\n  i: ComponentInternalInstance\n  /**\n   * Actual ref\n   */\n  r: VNodeRef\n  /**\n   * setup ref key\n   */\n  k?: string\n  /**\n   * refInFor marker\n   */\n  f?: boolean\n}\n\nexport type VNodeNormalizedRef =\n  | VNodeNormalizedRefAtom\n  | VNodeNormalizedRefAtom[]\n\ntype VNodeMountHook = (vnode: VNode) => void\ntype VNodeUpdateHook = (vnode: VNode, oldVNode: VNode) => void\nexport type VNodeHook =\n  | VNodeMountHook\n  | VNodeUpdateHook\n  | VNodeMountHook[]\n  | VNodeUpdateHook[]\n\n// https://github.com/microsoft/TypeScript/issues/33099\nexport type VNodeProps = {\n  key?: PropertyKey\n  ref?: VNodeRef\n  ref_for?: boolean\n  ref_key?: string\n\n  // vnode hooks\n  onVnodeBeforeMount?: VNodeMountHook | VNodeMountHook[]\n  onVnodeMounted?: VNodeMountHook | VNodeMountHook[]\n  onVnodeBeforeUpdate?: VNodeUpdateHook | VNodeUpdateHook[]\n  onVnodeUpdated?: VNodeUpdateHook | VNodeUpdateHook[]\n  onVnodeBeforeUnmount?: VNodeMountHook | VNodeMountHook[]\n  onVnodeUnmounted?: VNodeMountHook | VNodeMountHook[]\n}\n\ntype VNodeChildAtom =\n  | VNode\n  | string\n  | number\n  | boolean\n  | null\n  | undefined\n  | void\n\nexport type VNodeArrayChildren = Array<VNodeArrayChildren | VNodeChildAtom>\n\nexport type VNodeChild = VNodeChildAtom | VNodeArrayChildren\n\nexport type VNodeNormalizedChildren =\n  | string\n  | VNodeArrayChildren\n  | RawSlots\n  | null\n\nexport interface VNode<\n  HostNode = RendererNode,\n  HostElement = RendererElement,\n  ExtraProps = { [key: string]: any },\n> {\n  /**\n   * @internal\n   */\n  __v_isVNode: true\n\n  /**\n   * @internal\n   */\n  [ReactiveFlags.SKIP]: true\n\n  type: VNodeTypes\n  props: (VNodeProps & ExtraProps) | null\n  key: PropertyKey | null\n  ref: VNodeNormalizedRef | null\n  /**\n   * SFC only. This is assigned on vnode creation using currentScopeId\n   * which is set alongside currentRenderingInstance.\n   */\n  scopeId: string | null\n  /**\n   * SFC only. This is assigned to:\n   * - Slot fragment vnodes with :slotted SFC styles.\n   * - Component vnodes (during patch/hydration) so that its root node can\n   *   inherit the component's slotScopeIds\n   * @internal\n   */\n  slotScopeIds: string[] | null\n  children: VNodeNormalizedChildren\n  component: ComponentInternalInstance | null\n  dirs: DirectiveBinding[] | null\n  transition: TransitionHooks<HostElement> | null\n\n  // DOM\n  el: HostNode | null\n  placeholder: HostNode | null // async component el placeholder\n  anchor: HostNode | null // fragment anchor\n  target: HostElement | null // teleport target\n  targetStart: HostNode | null // teleport target start anchor\n  targetAnchor: HostNode | null // teleport target anchor\n  /**\n   * number of elements contained in a static vnode\n   * @internal\n   */\n  staticCount: number\n\n  // suspense\n  suspense: SuspenseBoundary | null\n  /**\n   * @internal\n   */\n  ssContent: VNode | null\n  /**\n   * @internal\n   */\n  ssFallback: VNode | null\n\n  // optimization only\n  shapeFlag: number\n  patchFlag: number\n  /**\n   * @internal\n   */\n  dynamicProps: string[] | null\n  /**\n   * @internal\n   */\n  dynamicChildren: (VNode[] & { hasOnce?: boolean }) | null\n\n  // application root node only\n  appContext: AppContext | null\n\n  /**\n   * @internal lexical scope owner instance\n   */\n  ctx: ComponentInternalInstance | null\n\n  /**\n   * @internal attached by v-memo\n   */\n  memo?: any[]\n  /**\n   * @internal index for cleaning v-memo cache\n   */\n  cacheIndex?: number\n  /**\n   * @internal __COMPAT__ only\n   */\n  isCompatRoot?: true\n  /**\n   * @internal custom element interception hook\n   */\n  ce?: (instance: ComponentInternalInstance) => void\n}\n\n// Since v-if and v-for are the two possible ways node structure can dynamically\n// change, once we consider v-if branches and each v-for fragment a block, we\n// can divide a template into nested blocks, and within each block the node\n// structure would be stable. This allows us to skip most children diffing\n// and only worry about the dynamic nodes (indicated by patch flags).\nexport const blockStack: VNode['dynamicChildren'][] = []\nexport let currentBlock: VNode['dynamicChildren'] = null\n\n/**\n * Open a block.\n * This must be called before `createBlock`. It cannot be part of `createBlock`\n * because the children of the block are evaluated before `createBlock` itself\n * is called. The generated code typically looks like this:\n *\n * ```js\n * function render() {\n *   return (openBlock(),createBlock('div', null, [...]))\n * }\n * ```\n * disableTracking is true when creating a v-for fragment block, since a v-for\n * fragment always diffs its children.\n *\n * @private\n */\nexport function openBlock(disableTracking = false): void {\n  blockStack.push((currentBlock = disableTracking ? null : []))\n}\n\nexport function closeBlock(): void {\n  blockStack.pop()\n  currentBlock = blockStack[blockStack.length - 1] || null\n}\n\n// Whether we should be tracking dynamic child nodes inside a block.\n// Only tracks when this value is > 0\n// We are not using a simple boolean because this value may need to be\n// incremented/decremented by nested usage of v-once (see below)\nexport let isBlockTreeEnabled = 1\n\n/**\n * Block tracking sometimes needs to be disabled, for example during the\n * creation of a tree that needs to be cached by v-once. The compiler generates\n * code like this:\n *\n * ``` js\n * _cache[1] || (\n *   setBlockTracking(-1, true),\n *   _cache[1] = createVNode(...),\n *   setBlockTracking(1),\n *   _cache[1]\n * )\n * ```\n *\n * @private\n */\nexport function setBlockTracking(value: number, inVOnce = false): void {\n  isBlockTreeEnabled += value\n  if (value < 0 && currentBlock && inVOnce) {\n    // mark current block so it doesn't take fast path and skip possible\n    // nested components during unmount\n    currentBlock.hasOnce = true\n  }\n}\n\nfunction setupBlock(vnode: VNode) {\n  // save current block children on the block vnode\n  vnode.dynamicChildren =\n    isBlockTreeEnabled > 0 ? currentBlock || (EMPTY_ARR as any) : null\n  // close block\n  closeBlock()\n  // a block is always going to be patched, so track it as a child of its\n  // parent block\n  if (isBlockTreeEnabled > 0 && currentBlock) {\n    currentBlock.push(vnode)\n  }\n  return vnode\n}\n\n/**\n * @private\n */\nexport function createElementBlock(\n  type: string | typeof Fragment,\n  props?: Record<string, any> | null,\n  children?: any,\n  patchFlag?: number,\n  dynamicProps?: string[],\n  shapeFlag?: number,\n): VNode {\n  return setupBlock(\n    createBaseVNode(\n      type,\n      props,\n      children,\n      patchFlag,\n      dynamicProps,\n      shapeFlag,\n      true /* isBlock */,\n    ),\n  )\n}\n\n/**\n * Create a block root vnode. Takes the same exact arguments as `createVNode`.\n * A block root keeps track of dynamic nodes within the block in the\n * `dynamicChildren` array.\n *\n * @private\n */\nexport function createBlock(\n  type: VNodeTypes | ClassComponent,\n  props?: Record<string, any> | null,\n  children?: any,\n  patchFlag?: number,\n  dynamicProps?: string[],\n): VNode {\n  return setupBlock(\n    createVNode(\n      type,\n      props,\n      children,\n      patchFlag,\n      dynamicProps,\n      true /* isBlock: prevent a block from tracking itself */,\n    ),\n  )\n}\n\nexport function isVNode(value: any): value is VNode {\n  return value ? value.__v_isVNode === true : false\n}\n\nexport function isSameVNodeType(n1: VNode, n2: VNode): boolean {\n  if (__DEV__ && n2.shapeFlag & ShapeFlags.COMPONENT && n1.component) {\n    const dirtyInstances = hmrDirtyComponents.get(n2.type as ConcreteComponent)\n    if (dirtyInstances && dirtyInstances.has(n1.component)) {\n      // #7042, ensure the vnode being unmounted during HMR\n      // bitwise operations to remove keep alive flags\n      n1.shapeFlag &= ~ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE\n      n2.shapeFlag &= ~ShapeFlags.COMPONENT_KEPT_ALIVE\n      // HMR only: if the component has been hot-updated, force a reload.\n      return false\n    }\n  }\n  return n1.type === n2.type && n1.key === n2.key\n}\n\nlet vnodeArgsTransformer:\n  | ((\n      args: Parameters<typeof _createVNode>,\n      instance: ComponentInternalInstance | null,\n    ) => Parameters<typeof _createVNode>)\n  | undefined\n\n/**\n * Internal API for registering an arguments transform for createVNode\n * used for creating stubs in the test-utils\n * It is *internal* but needs to be exposed for test-utils to pick up proper\n * typings\n */\nexport function transformVNodeArgs(\n  transformer?: typeof vnodeArgsTransformer,\n): void {\n  vnodeArgsTransformer = transformer\n}\n\nconst createVNodeWithArgsTransform = (\n  ...args: Parameters<typeof _createVNode>\n): VNode => {\n  return _createVNode(\n    ...(vnodeArgsTransformer\n      ? vnodeArgsTransformer(args, currentRenderingInstance)\n      : args),\n  )\n}\n\nconst normalizeKey = ({ key }: VNodeProps): VNode['key'] =>\n  key != null ? key : null\n\nconst normalizeRef = ({\n  ref,\n  ref_key,\n  ref_for,\n}: VNodeProps): VNodeNormalizedRefAtom | null => {\n  if (typeof ref === 'number') {\n    ref = '' + ref\n  }\n  return (\n    ref != null\n      ? isString(ref) || isRef(ref) || isFunction(ref)\n        ? { i: currentRenderingInstance, r: ref, k: ref_key, f: !!ref_for }\n        : ref\n      : null\n  ) as any\n}\n\nfunction createBaseVNode(\n  type: VNodeTypes | ClassComponent | typeof NULL_DYNAMIC_COMPONENT,\n  props: (Data & VNodeProps) | null = null,\n  children: unknown = null,\n  patchFlag = 0,\n  dynamicProps: string[] | null = null,\n  shapeFlag: number = type === Fragment ? 0 : ShapeFlags.ELEMENT,\n  isBlockNode = false,\n  needFullChildrenNormalization = false,\n): VNode {\n  const vnode = {\n    __v_isVNode: true,\n    __v_skip: true,\n    type,\n    props,\n    key: props && normalizeKey(props),\n    ref: props && normalizeRef(props),\n    scopeId: currentScopeId,\n    slotScopeIds: null,\n    children,\n    component: null,\n    suspense: null,\n    ssContent: null,\n    ssFallback: null,\n    dirs: null,\n    transition: null,\n    el: null,\n    anchor: null,\n    target: null,\n    targetStart: null,\n    targetAnchor: null,\n    staticCount: 0,\n    shapeFlag,\n    patchFlag,\n    dynamicProps,\n    dynamicChildren: null,\n    appContext: null,\n    ctx: currentRenderingInstance,\n  } as VNode\n\n  if (needFullChildrenNormalization) {\n    normalizeChildren(vnode, children)\n    // normalize suspense children\n    if (__FEATURE_SUSPENSE__ && shapeFlag & ShapeFlags.SUSPENSE) {\n      ;(type as typeof SuspenseImpl).normalize(vnode)\n    }\n  } else if (children) {\n    // compiled element vnode - if children is passed, only possible types are\n    // string or Array.\n    vnode.shapeFlag |= isString(children)\n      ? ShapeFlags.TEXT_CHILDREN\n      : ShapeFlags.ARRAY_CHILDREN\n  }\n\n  // validate key\n  if (__DEV__ && vnode.key !== vnode.key) {\n    warn(`VNode created with invalid key (NaN). VNode type:`, vnode.type)\n  }\n\n  // track vnode for block tree\n  if (\n    isBlockTreeEnabled > 0 &&\n    // avoid a block node from tracking itself\n    !isBlockNode &&\n    // has current parent block\n    currentBlock &&\n    // presence of a patch flag indicates this node needs patching on updates.\n    // component nodes also should always be patched, because even if the\n    // component doesn't need to update, it needs to persist the instance on to\n    // the next vnode so that it can be properly unmounted later.\n    (vnode.patchFlag > 0 || shapeFlag & ShapeFlags.COMPONENT) &&\n    // the EVENTS flag is only for hydration and if it is the only flag, the\n    // vnode should not be considered dynamic due to handler caching.\n    vnode.patchFlag !== PatchFlags.NEED_HYDRATION\n  ) {\n    currentBlock.push(vnode)\n  }\n\n  if (__COMPAT__) {\n    convertLegacyVModelProps(vnode)\n    defineLegacyVNodeProperties(vnode)\n  }\n\n  return vnode\n}\n\nexport { createBaseVNode as createElementVNode }\n\nexport const createVNode = (\n  __DEV__ ? createVNodeWithArgsTransform : _createVNode\n) as typeof _createVNode\n\nfunction _createVNode(\n  type: VNodeTypes | ClassComponent | typeof NULL_DYNAMIC_COMPONENT,\n  props: (Data & VNodeProps) | null = null,\n  children: unknown = null,\n  patchFlag: number = 0,\n  dynamicProps: string[] | null = null,\n  isBlockNode = false,\n): VNode {\n  if (!type || type === NULL_DYNAMIC_COMPONENT) {\n    if (__DEV__ && !type) {\n      warn(`Invalid vnode type when creating vnode: ${type}.`)\n    }\n    type = Comment\n  }\n\n  if (isVNode(type)) {\n    // createVNode receiving an existing vnode. This happens in cases like\n    // <component :is=\"vnode\"/>\n    // #2078 make sure to merge refs during the clone instead of overwriting it\n    const cloned = cloneVNode(type, props, true /* mergeRef: true */)\n    if (children) {\n      normalizeChildren(cloned, children)\n    }\n    if (isBlockTreeEnabled > 0 && !isBlockNode && currentBlock) {\n      if (cloned.shapeFlag & ShapeFlags.COMPONENT) {\n        currentBlock[currentBlock.indexOf(type)] = cloned\n      } else {\n        currentBlock.push(cloned)\n      }\n    }\n    cloned.patchFlag = PatchFlags.BAIL\n    return cloned\n  }\n\n  // class component normalization.\n  if (isClassComponent(type)) {\n    type = type.__vccOpts\n  }\n\n  // 2.x async/functional component compat\n  if (__COMPAT__) {\n    type = convertLegacyComponent(type, currentRenderingInstance)\n  }\n\n  // class & style normalization.\n  if (props) {\n    // for reactive or proxy objects, we need to clone it to enable mutation.\n    props = guardReactiveProps(props)!\n    let { class: klass, style } = props\n    if (klass && !isString(klass)) {\n      props.class = normalizeClass(klass)\n    }\n    if (isObject(style)) {\n      // reactive state objects need to be cloned since they are likely to be\n      // mutated\n      if (isProxy(style) && !isArray(style)) {\n        style = extend({}, style)\n      }\n      props.style = normalizeStyle(style)\n    }\n  }\n\n  // encode the vnode type information into a bitmap\n  const shapeFlag = isString(type)\n    ? ShapeFlags.ELEMENT\n    : __FEATURE_SUSPENSE__ && isSuspense(type)\n      ? ShapeFlags.SUSPENSE\n      : isTeleport(type)\n        ? ShapeFlags.TELEPORT\n        : isObject(type)\n          ? ShapeFlags.STATEFUL_COMPONENT\n          : isFunction(type)\n            ? ShapeFlags.FUNCTIONAL_COMPONENT\n            : 0\n\n  if (__DEV__ && shapeFlag & ShapeFlags.STATEFUL_COMPONENT && isProxy(type)) {\n    type = toRaw(type)\n    warn(\n      `Vue received a Component that was made a reactive object. This can ` +\n        `lead to unnecessary performance overhead and should be avoided by ` +\n        `marking the component with \\`markRaw\\` or using \\`shallowRef\\` ` +\n        `instead of \\`ref\\`.`,\n      `\\nComponent that was made reactive: `,\n      type,\n    )\n  }\n\n  return createBaseVNode(\n    type,\n    props,\n    children,\n    patchFlag,\n    dynamicProps,\n    shapeFlag,\n    isBlockNode,\n    true,\n  )\n}\n\nexport function guardReactiveProps(\n  props: (Data & VNodeProps) | null,\n): (Data & VNodeProps) | null {\n  if (!props) return null\n  return isProxy(props) || isInternalObject(props) ? extend({}, props) : props\n}\n\nexport function cloneVNode<T, U>(\n  vnode: VNode<T, U>,\n  extraProps?: (Data & VNodeProps) | null,\n  mergeRef = false,\n  cloneTransition = false,\n): VNode<T, U> {\n  // This is intentionally NOT using spread or extend to avoid the runtime\n  // key enumeration cost.\n  const { props, ref, patchFlag, children, transition } = vnode\n  const mergedProps = extraProps ? mergeProps(props || {}, extraProps) : props\n  const cloned: VNode<T, U> = {\n    __v_isVNode: true,\n    __v_skip: true,\n    type: vnode.type,\n    props: mergedProps,\n    key: mergedProps && normalizeKey(mergedProps),\n    ref:\n      extraProps && extraProps.ref\n        ? // #2078 in the case of <component :is=\"vnode\" ref=\"extra\"/>\n          // if the vnode itself already has a ref, cloneVNode will need to merge\n          // the refs so the single vnode can be set on multiple refs\n          mergeRef && ref\n          ? isArray(ref)\n            ? ref.concat(normalizeRef(extraProps)!)\n            : [ref, normalizeRef(extraProps)!]\n          : normalizeRef(extraProps)\n        : ref,\n    scopeId: vnode.scopeId,\n    slotScopeIds: vnode.slotScopeIds,\n    children:\n      __DEV__ && patchFlag === PatchFlags.CACHED && isArray(children)\n        ? (children as VNode[]).map(deepCloneVNode)\n        : children,\n    target: vnode.target,\n    targetStart: vnode.targetStart,\n    targetAnchor: vnode.targetAnchor,\n    staticCount: vnode.staticCount,\n    shapeFlag: vnode.shapeFlag,\n    // if the vnode is cloned with extra props, we can no longer assume its\n    // existing patch flag to be reliable and need to add the FULL_PROPS flag.\n    // note: preserve flag for fragments since they use the flag for children\n    // fast paths only.\n    patchFlag:\n      extraProps && vnode.type !== Fragment\n        ? patchFlag === PatchFlags.CACHED // hoisted node\n          ? PatchFlags.FULL_PROPS\n          : patchFlag | PatchFlags.FULL_PROPS\n        : patchFlag,\n    dynamicProps: vnode.dynamicProps,\n    dynamicChildren: vnode.dynamicChildren,\n    appContext: vnode.appContext,\n    dirs: vnode.dirs,\n    transition,\n\n    // These should technically only be non-null on mounted VNodes. However,\n    // they *should* be copied for kept-alive vnodes. So we just always copy\n    // them since them being non-null during a mount doesn't affect the logic as\n    // they will simply be overwritten.\n    component: vnode.component,\n    suspense: vnode.suspense,\n    ssContent: vnode.ssContent && cloneVNode(vnode.ssContent),\n    ssFallback: vnode.ssFallback && cloneVNode(vnode.ssFallback),\n    placeholder: vnode.placeholder,\n\n    el: vnode.el,\n    anchor: vnode.anchor,\n    ctx: vnode.ctx,\n    ce: vnode.ce,\n  }\n\n  // if the vnode will be replaced by the cloned one, it is necessary\n  // to clone the transition to ensure that the vnode referenced within\n  // the transition hooks is fresh.\n  if (transition && cloneTransition) {\n    setTransitionHooks(\n      cloned as VNode,\n      transition.clone(cloned as VNode) as TransitionHooks,\n    )\n  }\n\n  if (__COMPAT__) {\n    defineLegacyVNodeProperties(cloned as VNode)\n  }\n\n  return cloned\n}\n\n/**\n * Dev only, for HMR of hoisted vnodes reused in v-for\n * https://github.com/vitejs/vite/issues/2022\n */\nfunction deepCloneVNode(vnode: VNode): VNode {\n  const cloned = cloneVNode(vnode)\n  if (isArray(vnode.children)) {\n    cloned.children = (vnode.children as VNode[]).map(deepCloneVNode)\n  }\n  return cloned\n}\n\n/**\n * @private\n */\nexport function createTextVNode(text: string = ' ', flag: number = 0): VNode {\n  return createVNode(Text, null, text, flag)\n}\n\n/**\n * @private\n */\nexport function createStaticVNode(\n  content: string,\n  numberOfNodes: number,\n): VNode {\n  // A static vnode can contain multiple stringified elements, and the number\n  // of elements is necessary for hydration.\n  const vnode = createVNode(Static, null, content)\n  vnode.staticCount = numberOfNodes\n  return vnode\n}\n\n/**\n * @private\n */\nexport function createCommentVNode(\n  text: string = '',\n  // when used as the v-else branch, the comment node must be created as a\n  // block to ensure correct updates.\n  asBlock: boolean = false,\n): VNode {\n  return asBlock\n    ? (openBlock(), createBlock(Comment, null, text))\n    : createVNode(Comment, null, text)\n}\n\nexport function normalizeVNode(child: VNodeChild): VNode {\n  if (child == null || typeof child === 'boolean') {\n    // empty placeholder\n    return createVNode(Comment)\n  } else if (isArray(child)) {\n    // fragment\n    return createVNode(\n      Fragment,\n      null,\n      // #3666, avoid reference pollution when reusing vnode\n      child.slice(),\n    )\n  } else if (isVNode(child)) {\n    // already vnode, this should be the most common since compiled templates\n    // always produce all-vnode children arrays\n    return cloneIfMounted(child)\n  } else {\n    // strings and numbers\n    return createVNode(Text, null, String(child))\n  }\n}\n\n// optimized normalization for template-compiled render fns\nexport function cloneIfMounted(child: VNode): VNode {\n  return (child.el === null && child.patchFlag !== PatchFlags.CACHED) ||\n    child.memo\n    ? child\n    : cloneVNode(child)\n}\n\nexport function normalizeChildren(vnode: VNode, children: unknown): void {\n  let type = 0\n  const { shapeFlag } = vnode\n  if (children == null) {\n    children = null\n  } else if (isArray(children)) {\n    type = ShapeFlags.ARRAY_CHILDREN\n  } else if (typeof children === 'object') {\n    if (shapeFlag & (ShapeFlags.ELEMENT | ShapeFlags.TELEPORT)) {\n      // Normalize slot to plain children for plain element and Teleport\n      const slot = (children as any).default\n      if (slot) {\n        // _c marker is added by withCtx() indicating this is a compiled slot\n        slot._c && (slot._d = false)\n        normalizeChildren(vnode, slot())\n        slot._c && (slot._d = true)\n      }\n      return\n    } else {\n      type = ShapeFlags.SLOTS_CHILDREN\n      const slotFlag = (children as RawSlots)._\n      if (!slotFlag && !isInternalObject(children)) {\n        // if slots are not normalized, attach context instance\n        // (compiled / normalized slots already have context)\n        ;(children as RawSlots)._ctx = currentRenderingInstance\n      } else if (slotFlag === SlotFlags.FORWARDED && currentRenderingInstance) {\n        // a child component receives forwarded slots from the parent.\n        // its slot type is determined by its parent's slot type.\n        if (\n          (currentRenderingInstance.slots as RawSlots)._ === SlotFlags.STABLE\n        ) {\n          ;(children as RawSlots)._ = SlotFlags.STABLE\n        } else {\n          ;(children as RawSlots)._ = SlotFlags.DYNAMIC\n          vnode.patchFlag |= PatchFlags.DYNAMIC_SLOTS\n        }\n      }\n    }\n  } else if (isFunction(children)) {\n    children = { default: children, _ctx: currentRenderingInstance }\n    type = ShapeFlags.SLOTS_CHILDREN\n  } else {\n    children = String(children)\n    // force teleport children to array so it can be moved around\n    if (shapeFlag & ShapeFlags.TELEPORT) {\n      type = ShapeFlags.ARRAY_CHILDREN\n      children = [createTextVNode(children as string)]\n    } else {\n      type = ShapeFlags.TEXT_CHILDREN\n    }\n  }\n  vnode.children = children as VNodeNormalizedChildren\n  vnode.shapeFlag |= type\n}\n\nexport function mergeProps(...args: (Data & VNodeProps)[]): Data {\n  const ret: Data = {}\n  for (let i = 0; i < args.length; i++) {\n    const toMerge = args[i]\n    for (const key in toMerge) {\n      if (key === 'class') {\n        if (ret.class !== toMerge.class) {\n          ret.class = normalizeClass([ret.class, toMerge.class])\n        }\n      } else if (key === 'style') {\n        ret.style = normalizeStyle([ret.style, toMerge.style])\n      } else if (isOn(key)) {\n        const existing = ret[key]\n        const incoming = toMerge[key]\n        if (\n          incoming &&\n          existing !== incoming &&\n          !(isArray(existing) && existing.includes(incoming))\n        ) {\n          ret[key] = existing\n            ? [].concat(existing as any, incoming as any)\n            : incoming\n        }\n      } else if (key !== '') {\n        ret[key] = toMerge[key]\n      }\n    }\n  }\n  return ret\n}\n\nexport function invokeVNodeHook(\n  hook: VNodeHook,\n  instance: ComponentInternalInstance | null,\n  vnode: VNode,\n  prevVNode: VNode | null = null,\n): void {\n  callWithAsyncErrorHandling(hook, instance, ErrorCodes.VNODE_HOOK, [\n    vnode,\n    prevVNode,\n  ])\n}\n"
  },
  {
    "path": "packages/runtime-core/src/warning.ts",
    "content": "import type { VNode } from './vnode'\nimport {\n  type ComponentInternalInstance,\n  type ConcreteComponent,\n  type Data,\n  formatComponentName,\n} from './component'\nimport { isFunction, isString } from '@vue/shared'\nimport { isRef, pauseTracking, resetTracking, toRaw } from '@vue/reactivity'\nimport { ErrorCodes, callWithErrorHandling } from './errorHandling'\n\ntype ComponentVNode = VNode & {\n  type: ConcreteComponent\n}\n\nconst stack: VNode[] = []\n\ntype TraceEntry = {\n  vnode: ComponentVNode\n  recurseCount: number\n}\n\ntype ComponentTraceStack = TraceEntry[]\n\nexport function pushWarningContext(vnode: VNode): void {\n  stack.push(vnode)\n}\n\nexport function popWarningContext(): void {\n  stack.pop()\n}\n\nlet isWarning = false\n\nexport function warn(msg: string, ...args: any[]): void {\n  if (isWarning) return\n  isWarning = true\n\n  // avoid props formatting or warn handler tracking deps that might be mutated\n  // during patch, leading to infinite recursion.\n  pauseTracking()\n\n  const instance = stack.length ? stack[stack.length - 1].component : null\n  const appWarnHandler = instance && instance.appContext.config.warnHandler\n  const trace = getComponentTrace()\n\n  if (appWarnHandler) {\n    callWithErrorHandling(\n      appWarnHandler,\n      instance,\n      ErrorCodes.APP_WARN_HANDLER,\n      [\n        // eslint-disable-next-line no-restricted-syntax\n        msg + args.map(a => a.toString?.() ?? JSON.stringify(a)).join(''),\n        instance && instance.proxy,\n        trace\n          .map(\n            ({ vnode }) => `at <${formatComponentName(instance, vnode.type)}>`,\n          )\n          .join('\\n'),\n        trace,\n      ],\n    )\n  } else {\n    const warnArgs = [`[Vue warn]: ${msg}`, ...args]\n    if (\n      trace.length &&\n      // avoid spamming console during tests\n      !__TEST__\n    ) {\n      /* v8 ignore next 2 */\n      warnArgs.push(`\\n`, ...formatTrace(trace))\n    }\n    console.warn(...warnArgs)\n  }\n\n  resetTracking()\n  isWarning = false\n}\n\nexport function getComponentTrace(): ComponentTraceStack {\n  let currentVNode: VNode | null = stack[stack.length - 1]\n  if (!currentVNode) {\n    return []\n  }\n\n  // we can't just use the stack because it will be incomplete during updates\n  // that did not start from the root. Re-construct the parent chain using\n  // instance parent pointers.\n  const normalizedStack: ComponentTraceStack = []\n\n  while (currentVNode) {\n    const last = normalizedStack[0]\n    if (last && last.vnode === currentVNode) {\n      last.recurseCount++\n    } else {\n      normalizedStack.push({\n        vnode: currentVNode as ComponentVNode,\n        recurseCount: 0,\n      })\n    }\n    const parentInstance: ComponentInternalInstance | null =\n      currentVNode.component && currentVNode.component.parent\n    currentVNode = parentInstance && parentInstance.vnode\n  }\n\n  return normalizedStack\n}\n\n/* v8 ignore start */\nfunction formatTrace(trace: ComponentTraceStack): any[] {\n  const logs: any[] = []\n  trace.forEach((entry, i) => {\n    logs.push(...(i === 0 ? [] : [`\\n`]), ...formatTraceEntry(entry))\n  })\n  return logs\n}\n\nfunction formatTraceEntry({ vnode, recurseCount }: TraceEntry): any[] {\n  const postfix =\n    recurseCount > 0 ? `... (${recurseCount} recursive calls)` : ``\n  const isRoot = vnode.component ? vnode.component.parent == null : false\n  const open = ` at <${formatComponentName(\n    vnode.component,\n    vnode.type,\n    isRoot,\n  )}`\n  const close = `>` + postfix\n  return vnode.props\n    ? [open, ...formatProps(vnode.props), close]\n    : [open + close]\n}\n\nfunction formatProps(props: Data): any[] {\n  const res: any[] = []\n  const keys = Object.keys(props)\n  keys.slice(0, 3).forEach(key => {\n    res.push(...formatProp(key, props[key]))\n  })\n  if (keys.length > 3) {\n    res.push(` ...`)\n  }\n  return res\n}\n\nfunction formatProp(key: string, value: unknown): any[]\nfunction formatProp(key: string, value: unknown, raw: true): any\nfunction formatProp(key: string, value: unknown, raw?: boolean): any {\n  if (isString(value)) {\n    value = JSON.stringify(value)\n    return raw ? value : [`${key}=${value}`]\n  } else if (\n    typeof value === 'number' ||\n    typeof value === 'boolean' ||\n    value == null\n  ) {\n    return raw ? value : [`${key}=${value}`]\n  } else if (isRef(value)) {\n    value = formatProp(key, toRaw(value.value), true)\n    return raw ? value : [`${key}=Ref<`, value, `>`]\n  } else if (isFunction(value)) {\n    return [`${key}=fn${value.name ? `<${value.name}>` : ``}`]\n  } else {\n    value = toRaw(value)\n    return raw ? value : [`${key}=`, value]\n  }\n}\n\n/**\n * @internal\n */\nexport function assertNumber(val: unknown, type: string): void {\n  if (!__DEV__) return\n  if (val === undefined) {\n    return\n  } else if (typeof val !== 'number') {\n    warn(`${type} is not a valid number - ` + `got ${JSON.stringify(val)}.`)\n  } else if (isNaN(val)) {\n    warn(`${type} is NaN - ` + 'the duration expression might be incorrect.')\n  }\n}\n/* v8 ignore stop */\n"
  },
  {
    "path": "packages/runtime-core/types/globalComponents.d.ts",
    "content": "// Note: this file is auto concatenated to the end of the bundled d.ts during\n// build.\n\ndeclare module '@vue/runtime-core' {\n  export interface GlobalComponents {\n    Teleport: DefineComponent<TeleportProps>\n    Suspense: DefineComponent<SuspenseProps>\n    KeepAlive: DefineComponent<KeepAliveProps>\n    BaseTransition: DefineComponent<BaseTransitionProps>\n  }\n}\n"
  },
  {
    "path": "packages/runtime-core/types/scriptSetupHelpers.d.ts",
    "content": "// Note: this file is auto concatenated to the end of the bundled d.ts during\n// build.\ntype _defineProps = typeof defineProps\ntype _defineEmits = typeof defineEmits\ntype _defineExpose = typeof defineExpose\ntype _defineOptions = typeof defineOptions\ntype _defineSlots = typeof defineSlots\ntype _defineModel = typeof defineModel\ntype _withDefaults = typeof withDefaults\n\ndeclare global {\n  const defineProps: _defineProps\n  const defineEmits: _defineEmits\n  const defineExpose: _defineExpose\n  const defineOptions: _defineOptions\n  const defineSlots: _defineSlots\n  const defineModel: _defineModel\n  const withDefaults: _withDefaults\n}\n"
  },
  {
    "path": "packages/runtime-dom/LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2018-present, Yuxi (Evan) You\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "packages/runtime-dom/README.md",
    "content": "# @vue/runtime-dom\n\n```js\nimport { h, createApp } from '@vue/runtime-dom'\n\nconst RootComponent = {\n  render() {\n    return h('div', 'hello world')\n  },\n}\n\ncreateApp(RootComponent).mount('#app')\n```\n"
  },
  {
    "path": "packages/runtime-dom/__tests__/createApp.spec.ts",
    "content": "import { createApp, h } from '../src'\n\ndescribe('createApp for dom', () => {\n  // #2926\n  test('mount to SVG container', () => {\n    const root = document.createElementNS('http://www.w3.org/2000/svg', 'svg')\n    createApp({\n      render() {\n        return h('g')\n      },\n    }).mount(root)\n    expect(root.children.length).toBe(1)\n    expect(root.children[0]).toBeInstanceOf(SVGElement)\n  })\n\n  // #4398\n  test('should not mutate original root component options object', () => {\n    const originalObj = {\n      data() {\n        return {\n          counter: 0,\n        }\n      },\n    }\n\n    const handler = vi.fn(msg => {\n      expect(msg).toMatch(`Component is missing template or render function`)\n    })\n\n    const Root = { ...originalObj }\n\n    const app = createApp(Root)\n    app.config.warnHandler = handler\n    app.mount(document.createElement('div'))\n\n    // ensure mount is based on a copy of Root object rather than Root object itself\n    expect(app._component).not.toBe(Root)\n\n    // ensure no mutation happened to Root object\n    expect(originalObj).toMatchObject(Root)\n  })\n})\n"
  },
  {
    "path": "packages/runtime-dom/__tests__/customElement.spec.ts",
    "content": "import type { MockedFunction } from 'vitest'\nimport {\n  type HMRRuntime,\n  type Ref,\n  Teleport,\n  type VueElement,\n  createApp,\n  defineAsyncComponent,\n  defineComponent,\n  defineCustomElement,\n  h,\n  inject,\n  nextTick,\n  onMounted,\n  provide,\n  ref,\n  render,\n  renderSlot,\n  useHost,\n  useShadowRoot,\n} from '../src'\n\ndeclare var __VUE_HMR_RUNTIME__: HMRRuntime\n\ndescribe('defineCustomElement', () => {\n  const container = document.createElement('div')\n  document.body.appendChild(container)\n\n  beforeEach(() => {\n    container.innerHTML = ''\n  })\n\n  describe('mounting/unmount', () => {\n    const E = defineCustomElement({\n      props: {\n        msg: {\n          type: String,\n          default: 'hello',\n        },\n      },\n      render() {\n        return h('div', this.msg)\n      },\n    })\n    customElements.define('my-element', E)\n\n    test('should work', () => {\n      container.innerHTML = `<my-element></my-element>`\n      const e = container.childNodes[0] as VueElement\n      expect(e).toBeInstanceOf(E)\n      expect(e._instance).toBeTruthy()\n      expect(e.shadowRoot!.innerHTML).toBe(`<div>hello</div>`)\n    })\n\n    test('should work w/ manual instantiation', () => {\n      const e = new E({ msg: 'inline' })\n      // should lazy init\n      expect(e._instance).toBe(null)\n      // should initialize on connect\n      container.appendChild(e)\n      expect(e._instance).toBeTruthy()\n      expect(e.shadowRoot!.innerHTML).toBe(`<div>inline</div>`)\n    })\n\n    test('should unmount on remove', async () => {\n      container.innerHTML = `<my-element></my-element>`\n      const e = container.childNodes[0] as VueElement\n      container.removeChild(e)\n      await nextTick()\n      expect(e._instance).toBe(null)\n      expect(e.shadowRoot!.innerHTML).toBe('')\n    })\n\n    // #10610\n    test('When elements move, avoid prematurely disconnecting MutationObserver', async () => {\n      const CustomInput = defineCustomElement({\n        props: ['value'],\n        emits: ['update'],\n        setup(props, { emit }) {\n          return () =>\n            h('input', {\n              type: 'number',\n              value: props.value,\n              onInput: (e: InputEvent) => {\n                const num = (e.target! as HTMLInputElement).valueAsNumber\n                emit('update', Number.isNaN(num) ? null : num)\n              },\n            })\n        },\n      })\n      customElements.define('my-el-input', CustomInput)\n      const num = ref('12')\n      const containerComp = defineComponent({\n        setup() {\n          return () => {\n            return h('div', [\n              h('my-el-input', {\n                value: num.value,\n                onUpdate: ($event: CustomEvent) => {\n                  num.value = $event.detail[0]\n                },\n              }),\n              h('div', { id: 'move' }),\n            ])\n          }\n        },\n      })\n      const app = createApp(containerComp)\n      const container = document.createElement('div')\n      document.body.appendChild(container)\n      app.mount(container)\n      const myInputEl = container.querySelector('my-el-input')!\n      const inputEl = myInputEl.shadowRoot!.querySelector('input')!\n      await nextTick()\n      expect(inputEl.value).toBe('12')\n      const moveEl = container.querySelector('#move')!\n      moveEl.append(myInputEl)\n      await nextTick()\n      myInputEl.removeAttribute('value')\n      await nextTick()\n      expect(inputEl.value).toBe('')\n    })\n\n    test('should not unmount on move', async () => {\n      container.innerHTML = `<div><my-element></my-element></div>`\n      const e = container.childNodes[0].childNodes[0] as VueElement\n      const i = e._instance\n      // moving from one parent to another - this will trigger both disconnect\n      // and connected callbacks synchronously\n      container.appendChild(e)\n      await nextTick()\n      // should be the same instance\n      expect(e._instance).toBe(i)\n      expect(e.shadowRoot!.innerHTML).toBe('<div>hello</div>')\n    })\n\n    test('remove then insert again', async () => {\n      container.innerHTML = `<my-element></my-element>`\n      const e = container.childNodes[0] as VueElement\n      container.removeChild(e)\n      await nextTick()\n      expect(e._instance).toBe(null)\n      expect(e.shadowRoot!.innerHTML).toBe('')\n      container.appendChild(e)\n      expect(e._instance).toBeTruthy()\n      expect(e.shadowRoot!.innerHTML).toBe('<div>hello</div>')\n    })\n  })\n\n  describe('props', () => {\n    const E = defineCustomElement({\n      props: {\n        foo: [String, null],\n        bar: Object,\n        bazQux: null,\n        value: null,\n      },\n      render() {\n        return [\n          h('div', null, this.foo || ''),\n          h('div', null, this.bazQux || (this.bar && this.bar.x)),\n        ]\n      },\n    })\n    customElements.define('my-el-props', E)\n\n    test('renders custom element w/ correct object prop value', () => {\n      render(h('my-el-props', { value: { x: 1 } }), container)\n      const el = container.children[0]\n      expect((el as any).value).toEqual({ x: 1 })\n    })\n\n    test('props via attribute', async () => {\n      // bazQux should map to `baz-qux` attribute\n      container.innerHTML = `<my-el-props foo=\"hello\" baz-qux=\"bye\"></my-el-props>`\n      const e = container.childNodes[0] as VueElement\n      expect(e.shadowRoot!.innerHTML).toBe('<div>hello</div><div>bye</div>')\n\n      // change attr\n      e.setAttribute('foo', 'changed')\n      await nextTick()\n      expect(e.shadowRoot!.innerHTML).toBe('<div>changed</div><div>bye</div>')\n\n      e.setAttribute('baz-qux', 'changed')\n      await nextTick()\n      expect(e.shadowRoot!.innerHTML).toBe(\n        '<div>changed</div><div>changed</div>',\n      )\n    })\n\n    test('props via properties', async () => {\n      const e = new E()\n      e.foo = 'one'\n      e.bar = { x: 'two' }\n      container.appendChild(e)\n      expect(e.shadowRoot!.innerHTML).toBe('<div>one</div><div>two</div>')\n\n      // reflect\n      // should reflect primitive value\n      expect(e.getAttribute('foo')).toBe('one')\n      // should not reflect rich data\n      expect(e.hasAttribute('bar')).toBe(false)\n\n      e.foo = 'three'\n      await nextTick()\n      expect(e.shadowRoot!.innerHTML).toBe('<div>three</div><div>two</div>')\n      expect(e.getAttribute('foo')).toBe('three')\n\n      e.foo = null\n      await nextTick()\n      expect(e.shadowRoot!.innerHTML).toBe('<div></div><div>two</div>')\n      expect(e.hasAttribute('foo')).toBe(false)\n\n      e.foo = undefined\n      await nextTick()\n      expect(e.shadowRoot!.innerHTML).toBe('<div></div><div>two</div>')\n      expect(e.hasAttribute('foo')).toBe(false)\n      expect(e.foo).toBe(undefined)\n\n      e.bazQux = 'four'\n      await nextTick()\n      expect(e.shadowRoot!.innerHTML).toBe('<div></div><div>four</div>')\n      expect(e.getAttribute('baz-qux')).toBe('four')\n    })\n\n    test('props via attributes and properties changed together', async () => {\n      const e = new E()\n      e.foo = 'foo1'\n      e.bar = { x: 'bar1' }\n      container.appendChild(e)\n      await nextTick()\n      expect(e.shadowRoot!.innerHTML).toBe('<div>foo1</div><div>bar1</div>')\n\n      // change attr then property\n      e.setAttribute('foo', 'foo2')\n      e.bar = { x: 'bar2' }\n      await nextTick()\n      expect(e.shadowRoot!.innerHTML).toBe('<div>foo2</div><div>bar2</div>')\n      expect(e.getAttribute('foo')).toBe('foo2')\n      expect(e.hasAttribute('bar')).toBe(false)\n\n      // change prop then attr\n      e.bar = { x: 'bar3' }\n      e.setAttribute('foo', 'foo3')\n      await nextTick()\n      expect(e.shadowRoot!.innerHTML).toBe('<div>foo3</div><div>bar3</div>')\n      expect(e.getAttribute('foo')).toBe('foo3')\n      expect(e.hasAttribute('bar')).toBe(false)\n    })\n\n    test('props via hyphen property', async () => {\n      const Comp = defineCustomElement({\n        props: {\n          fooBar: Boolean,\n        },\n        render() {\n          return 'Comp'\n        },\n      })\n      customElements.define('my-el-comp', Comp)\n      render(h('my-el-comp', { 'foo-bar': true }), container)\n      const el = container.children[0]\n      expect((el as any).outerHTML).toBe('<my-el-comp foo-bar=\"\"></my-el-comp>')\n    })\n\n    test('attribute -> prop type casting', async () => {\n      const E = defineCustomElement({\n        props: {\n          fooBar: Number, // test casting of camelCase prop names\n          bar: Boolean,\n          baz: String,\n        },\n        render() {\n          return [\n            this.fooBar,\n            typeof this.fooBar,\n            this.bar,\n            typeof this.bar,\n            this.baz,\n            typeof this.baz,\n          ].join(' ')\n        },\n      })\n      customElements.define('my-el-props-cast', E)\n      container.innerHTML = `<my-el-props-cast foo-bar=\"1\" baz=\"12345\"></my-el-props-cast>`\n      const e = container.childNodes[0] as VueElement\n      expect(e.shadowRoot!.innerHTML).toBe(\n        `1 number false boolean 12345 string`,\n      )\n\n      e.setAttribute('bar', '')\n      await nextTick()\n      expect(e.shadowRoot!.innerHTML).toBe(`1 number true boolean 12345 string`)\n\n      e.setAttribute('foo-bar', '2e1')\n      await nextTick()\n      expect(e.shadowRoot!.innerHTML).toBe(\n        `20 number true boolean 12345 string`,\n      )\n\n      e.setAttribute('baz', '2e1')\n      await nextTick()\n      expect(e.shadowRoot!.innerHTML).toBe(`20 number true boolean 2e1 string`)\n    })\n\n    // #4772\n    test('attr casting w/ programmatic creation', () => {\n      const E = defineCustomElement({\n        props: {\n          foo: Number,\n        },\n        render() {\n          return `foo type: ${typeof this.foo}`\n        },\n      })\n      customElements.define('my-element-programmatic', E)\n      const el = document.createElement('my-element-programmatic') as any\n      el.setAttribute('foo', '123')\n      container.appendChild(el)\n      expect(el.shadowRoot.innerHTML).toBe(`foo type: number`)\n    })\n\n    test('handling properties set before upgrading', () => {\n      const E = defineCustomElement({\n        props: {\n          foo: String,\n          dataAge: Number,\n        },\n        setup(props) {\n          expect(props.foo).toBe('hello')\n          expect(props.dataAge).toBe(5)\n        },\n        render() {\n          return h('div', `foo: ${this.foo}`)\n        },\n      })\n      const el = document.createElement('my-el-upgrade') as any\n      el.foo = 'hello'\n      el.dataset.age = 5\n      el.notProp = 1\n      container.appendChild(el)\n      customElements.define('my-el-upgrade', E)\n      expect(el.shadowRoot.firstChild.innerHTML).toBe(`foo: hello`)\n      // should not reflect if not declared as a prop\n      expect(el.hasAttribute('not-prop')).toBe(false)\n    })\n\n    test('handle properties set before connecting', () => {\n      const obj = { a: 1 }\n      const E = defineCustomElement({\n        props: {\n          foo: String,\n          post: Object,\n        },\n        setup(props) {\n          expect(props.foo).toBe('hello')\n          expect(props.post).toBe(obj)\n        },\n        render() {\n          return JSON.stringify(this.post)\n        },\n      })\n      customElements.define('my-el-preconnect', E)\n      const el = document.createElement('my-el-preconnect') as any\n      el.foo = 'hello'\n      el.post = obj\n\n      container.appendChild(el)\n      expect(el.shadowRoot.innerHTML).toBe(JSON.stringify(obj))\n    })\n\n    // https://github.com/vuejs/core/issues/6163\n    test('handle components with no props', async () => {\n      const E = defineCustomElement({\n        render() {\n          return h('div', 'foo')\n        },\n      })\n      customElements.define('my-element-noprops', E)\n      const el = document.createElement('my-element-noprops')\n      container.appendChild(el)\n      await nextTick()\n      expect(el.shadowRoot!.innerHTML).toMatchInlineSnapshot('\"<div>foo</div>\"')\n    })\n\n    // #5793\n    test('set number value in dom property', () => {\n      const E = defineCustomElement({\n        props: {\n          'max-age': Number,\n        },\n        render() {\n          // @ts-expect-error\n          return `max age: ${this.maxAge}/type: ${typeof this.maxAge}`\n        },\n      })\n      customElements.define('my-element-number-property', E)\n      const el = document.createElement('my-element-number-property') as any\n      container.appendChild(el)\n      el.maxAge = 50\n      expect(el.maxAge).toBe(50)\n      expect(el.shadowRoot.innerHTML).toBe('max age: 50/type: number')\n    })\n\n    // #9006\n    test('should reflect default value', () => {\n      const E = defineCustomElement({\n        props: {\n          value: {\n            type: String,\n            default: 'hi',\n          },\n        },\n        render() {\n          return this.value\n        },\n      })\n      customElements.define('my-el-default-val', E)\n      container.innerHTML = `<my-el-default-val></my-el-default-val>`\n      const e = container.childNodes[0] as any\n      expect(e.value).toBe('hi')\n    })\n\n    // #12214\n    test('Boolean prop with default true', async () => {\n      const E = defineCustomElement({\n        props: {\n          foo: {\n            type: Boolean,\n            default: true,\n          },\n        },\n        render() {\n          return String(this.foo)\n        },\n      })\n      customElements.define('my-el-default-true', E)\n      container.innerHTML = `<my-el-default-true></my-el-default-true>`\n      const e = container.childNodes[0] as HTMLElement & { foo: any },\n        shadowRoot = e.shadowRoot as ShadowRoot\n      expect(shadowRoot.innerHTML).toBe('true')\n      e.foo = undefined\n      await nextTick()\n      expect(shadowRoot.innerHTML).toBe('true')\n      e.foo = false\n      await nextTick()\n      expect(shadowRoot.innerHTML).toBe('false')\n      e.foo = null\n      await nextTick()\n      expect(shadowRoot.innerHTML).toBe('null')\n      e.foo = ''\n      await nextTick()\n      expect(shadowRoot.innerHTML).toBe('true')\n    })\n\n    test('support direct setup function syntax with extra options', () => {\n      const E = defineCustomElement(\n        props => {\n          return () => props.text\n        },\n        {\n          props: {\n            text: String,\n          },\n        },\n      )\n      customElements.define('my-el-setup-with-props', E)\n      container.innerHTML = `<my-el-setup-with-props text=\"hello\"></my-el-setup-with-props>`\n      const e = container.childNodes[0] as VueElement\n      expect(e.shadowRoot!.innerHTML).toBe('hello')\n    })\n\n    test('prop types validation', async () => {\n      const E = defineCustomElement({\n        props: {\n          num: {\n            type: [Number, String],\n          },\n          bool: {\n            type: Boolean,\n          },\n        },\n        render() {\n          return h('div', [\n            h('span', [`${this.num} is ${typeof this.num}`]),\n            h('span', [`${this.bool} is ${typeof this.bool}`]),\n          ])\n        },\n      })\n\n      customElements.define('my-el-with-type-props', E)\n      render(h('my-el-with-type-props', { num: 1, bool: true }), container)\n      const e = container.childNodes[0] as VueElement\n      // @ts-expect-error\n      expect(e.num).toBe(1)\n      // @ts-expect-error\n      expect(e.bool).toBe(true)\n      expect(e.shadowRoot!.innerHTML).toBe(\n        '<div><span>1 is number</span><span>true is boolean</span></div>',\n      )\n    })\n\n    test('should patch all props together', async () => {\n      let prop1Calls = 0\n      let prop2Calls = 0\n      const E = defineCustomElement({\n        props: {\n          prop1: {\n            type: String,\n            default: 'default1',\n          },\n          prop2: {\n            type: String,\n            default: 'default2',\n          },\n        },\n        data() {\n          return {\n            data1: 'defaultData1',\n            data2: 'defaultData2',\n          }\n        },\n        watch: {\n          prop1(_) {\n            prop1Calls++\n            this.data2 = this.prop2\n          },\n          prop2(_) {\n            prop2Calls++\n            this.data1 = this.prop1\n          },\n        },\n        render() {\n          return h('div', [\n            h('h1', this.prop1),\n            h('h1', this.prop2),\n            h('h2', this.data1),\n            h('h2', this.data2),\n          ])\n        },\n      })\n      customElements.define('my-watch-element', E)\n\n      render(h('my-watch-element'), container)\n      const e = container.childNodes[0] as VueElement\n      expect(e).toBeInstanceOf(E)\n      expect(e._instance).toBeTruthy()\n      expect(e.shadowRoot!.innerHTML).toBe(\n        `<div><h1>default1</h1><h1>default2</h1><h2>defaultData1</h2><h2>defaultData2</h2></div>`,\n      )\n      expect(prop1Calls).toBe(0)\n      expect(prop2Calls).toBe(0)\n\n      // patch props\n      render(\n        h('my-watch-element', { prop1: 'newValue1', prop2: 'newValue2' }),\n        container,\n      )\n      await nextTick()\n      expect(e.shadowRoot!.innerHTML).toBe(\n        `<div><h1>newValue1</h1><h1>newValue2</h1><h2>newValue1</h2><h2>newValue2</h2></div>`,\n      )\n      expect(prop1Calls).toBe(1)\n      expect(prop2Calls).toBe(1)\n\n      // same prop values\n      render(\n        h('my-watch-element', { prop1: 'newValue1', prop2: 'newValue2' }),\n        container,\n      )\n      await nextTick()\n      expect(e.shadowRoot!.innerHTML).toBe(\n        `<div><h1>newValue1</h1><h1>newValue2</h1><h2>newValue1</h2><h2>newValue2</h2></div>`,\n      )\n      expect(prop1Calls).toBe(1)\n      expect(prop2Calls).toBe(1)\n\n      // update only prop1\n      render(\n        h('my-watch-element', { prop1: 'newValue3', prop2: 'newValue2' }),\n        container,\n      )\n      await nextTick()\n      expect(e.shadowRoot!.innerHTML).toBe(\n        `<div><h1>newValue3</h1><h1>newValue2</h1><h2>newValue1</h2><h2>newValue2</h2></div>`,\n      )\n      expect(prop1Calls).toBe(2)\n      expect(prop2Calls).toBe(1)\n    })\n\n    test('should patch all props together (async)', async () => {\n      let prop1Calls = 0\n      let prop2Calls = 0\n      const E = defineCustomElement(\n        defineAsyncComponent(() =>\n          Promise.resolve(\n            defineComponent({\n              props: {\n                prop1: {\n                  type: String,\n                  default: 'default1',\n                },\n                prop2: {\n                  type: String,\n                  default: 'default2',\n                },\n              },\n              data() {\n                return {\n                  data1: 'defaultData1',\n                  data2: 'defaultData2',\n                }\n              },\n              watch: {\n                prop1(_) {\n                  prop1Calls++\n                  this.data2 = this.prop2\n                },\n                prop2(_) {\n                  prop2Calls++\n                  this.data1 = this.prop1\n                },\n              },\n              render() {\n                return h('div', [\n                  h('h1', this.prop1),\n                  h('h1', this.prop2),\n                  h('h2', this.data1),\n                  h('h2', this.data2),\n                ])\n              },\n            }),\n          ),\n        ),\n      )\n      customElements.define('my-async-watch-element', E)\n\n      render(h('my-async-watch-element'), container)\n\n      await new Promise(r => setTimeout(r))\n      const e = container.childNodes[0] as VueElement\n      expect(e).toBeInstanceOf(E)\n      expect(e._instance).toBeTruthy()\n      expect(e.shadowRoot!.innerHTML).toBe(\n        `<div><h1>default1</h1><h1>default2</h1><h2>defaultData1</h2><h2>defaultData2</h2></div>`,\n      )\n      expect(prop1Calls).toBe(0)\n      expect(prop2Calls).toBe(0)\n\n      // patch props\n      render(\n        h('my-async-watch-element', { prop1: 'newValue1', prop2: 'newValue2' }),\n        container,\n      )\n      await nextTick()\n      expect(e.shadowRoot!.innerHTML).toBe(\n        `<div><h1>newValue1</h1><h1>newValue2</h1><h2>newValue1</h2><h2>newValue2</h2></div>`,\n      )\n      expect(prop1Calls).toBe(1)\n      expect(prop2Calls).toBe(1)\n\n      // same prop values\n      render(\n        h('my-async-watch-element', { prop1: 'newValue1', prop2: 'newValue2' }),\n        container,\n      )\n      await nextTick()\n      expect(e.shadowRoot!.innerHTML).toBe(\n        `<div><h1>newValue1</h1><h1>newValue2</h1><h2>newValue1</h2><h2>newValue2</h2></div>`,\n      )\n      expect(prop1Calls).toBe(1)\n      expect(prop2Calls).toBe(1)\n\n      // update only prop1\n      render(\n        h('my-async-watch-element', { prop1: 'newValue3', prop2: 'newValue2' }),\n        container,\n      )\n      await nextTick()\n      expect(e.shadowRoot!.innerHTML).toBe(\n        `<div><h1>newValue3</h1><h1>newValue2</h1><h2>newValue1</h2><h2>newValue2</h2></div>`,\n      )\n      expect(prop1Calls).toBe(2)\n      expect(prop2Calls).toBe(1)\n    })\n  })\n\n  describe('attrs', () => {\n    const E = defineCustomElement({\n      render() {\n        return [h('div', null, this.$attrs.foo as string)]\n      },\n    })\n    customElements.define('my-el-attrs', E)\n\n    test('attrs via attribute', async () => {\n      container.innerHTML = `<my-el-attrs foo=\"hello\"></my-el-attrs>`\n      const e = container.childNodes[0] as VueElement\n      expect(e.shadowRoot!.innerHTML).toBe('<div>hello</div>')\n\n      e.setAttribute('foo', 'changed')\n      await nextTick()\n      expect(e.shadowRoot!.innerHTML).toBe('<div>changed</div>')\n    })\n\n    test('non-declared properties should not show up in $attrs', () => {\n      const e = new E()\n      // @ts-expect-error\n      e.foo = '123'\n      container.appendChild(e)\n      expect(e.shadowRoot!.innerHTML).toBe('<div></div>')\n    })\n\n    // #12408\n    test('should set number tabindex as attribute', () => {\n      render(h('my-el-attrs', { tabindex: 1, 'data-test': true }), container)\n      const el = container.children[0] as HTMLElement\n      expect(el.getAttribute('tabindex')).toBe('1')\n      expect(el.getAttribute('data-test')).toBe('true')\n    })\n\n    test('should keep undeclared native attrs as attrs', () => {\n      const root = document.createElement('div')\n      document.body.appendChild(root)\n\n      render(h('my-el-attrs', { translate: 'no' }), root)\n      const el = root.children[0] as HTMLElement\n      expect(el.getAttribute('translate')).toBe('no')\n      expect(el.translate).toBe(false)\n\n      render(null, root)\n      root.remove()\n    })\n\n    // https://github.com/vuejs/core/issues/12964\n    // Disabled because of missing support for `delegatesFocus` in jsdom\n    // https://github.com/jsdom/jsdom/issues/3418\n    // eslint-disable-next-line vitest/no-disabled-tests\n    test.skip('shadowRoot should be initialized with delegatesFocus', () => {\n      const E = defineCustomElement(\n        {\n          render() {\n            return [h('input', { tabindex: 1 })]\n          },\n        },\n        { shadowRootOptions: { delegatesFocus: true } },\n      )\n      customElements.define('my-el-with-delegate-focus', E)\n\n      const e = new E()\n      container.appendChild(e)\n      expect(e.shadowRoot!.delegatesFocus).toBe(true)\n    })\n  })\n\n  describe('emits', () => {\n    const CompDef = defineComponent({\n      setup(_, { emit }) {\n        emit('created')\n        return () =>\n          h('div', {\n            onClick: () => {\n              emit('my-click', 1)\n            },\n            onMousedown: () => {\n              emit('myEvent', 1) // validate hyphenation\n            },\n            onWheel: () => {\n              emit('my-wheel', { bubbles: true }, 1)\n            },\n          })\n      },\n    })\n    const E = defineCustomElement(CompDef)\n    customElements.define('my-el-emits', E)\n\n    test('emit on connect', () => {\n      const e = new E()\n      const spy = vi.fn()\n      e.addEventListener('created', spy)\n      container.appendChild(e)\n      expect(spy).toHaveBeenCalled()\n    })\n\n    test('emit on interaction', () => {\n      container.innerHTML = `<my-el-emits></my-el-emits>`\n      const e = container.childNodes[0] as VueElement\n      const spy = vi.fn()\n      e.addEventListener('my-click', spy)\n      e.shadowRoot!.childNodes[0].dispatchEvent(new CustomEvent('click'))\n      expect(spy).toHaveBeenCalledTimes(1)\n      expect(spy.mock.calls[0][0]).toMatchObject({\n        detail: [1],\n      })\n    })\n\n    // #5373\n    test('case transform for camelCase event', () => {\n      container.innerHTML = `<my-el-emits></my-el-emits>`\n      const e = container.childNodes[0] as VueElement\n      const spy1 = vi.fn()\n      e.addEventListener('myEvent', spy1)\n      const spy2 = vi.fn()\n      // emitting myEvent, but listening for my-event. This happens when\n      // using the custom element in a Vue template\n      e.addEventListener('my-event', spy2)\n      e.shadowRoot!.childNodes[0].dispatchEvent(new CustomEvent('mousedown'))\n      expect(spy1).toHaveBeenCalledTimes(1)\n      expect(spy2).toHaveBeenCalledTimes(1)\n    })\n\n    test('emit from within async component wrapper', async () => {\n      const p = new Promise<typeof CompDef>(res => res(CompDef as any))\n      const E = defineCustomElement(defineAsyncComponent(() => p))\n      customElements.define('my-async-el-emits', E)\n      container.innerHTML = `<my-async-el-emits></my-async-el-emits>`\n      const e = container.childNodes[0] as VueElement\n      const spy = vi.fn()\n      e.addEventListener('my-click', spy)\n      // this feels brittle but seems necessary to reach the node in the DOM.\n      await customElements.whenDefined('my-async-el-emits')\n      await nextTick()\n      await nextTick()\n      e.shadowRoot!.childNodes[0].dispatchEvent(new CustomEvent('click'))\n      expect(spy).toHaveBeenCalled()\n      expect(spy.mock.calls[0][0]).toMatchObject({\n        detail: [1],\n      })\n    })\n\n    // #7293\n    test('emit in an async component wrapper with properties bound', async () => {\n      const E = defineCustomElement(\n        defineAsyncComponent(\n          () => new Promise<typeof CompDef>(res => res(CompDef as any)),\n        ),\n      )\n      customElements.define('my-async-el-props-emits', E)\n      container.innerHTML = `<my-async-el-props-emits id=\"my_async_el_props_emits\"></my-async-el-props-emits>`\n      const e = container.childNodes[0] as VueElement\n      const spy = vi.fn()\n      e.addEventListener('my-click', spy)\n      await customElements.whenDefined('my-async-el-props-emits')\n      await nextTick()\n      await nextTick()\n      e.shadowRoot!.childNodes[0].dispatchEvent(new CustomEvent('click'))\n      expect(spy).toHaveBeenCalled()\n      expect(spy.mock.calls[0][0]).toMatchObject({\n        detail: [1],\n      })\n    })\n\n    test('emit with options', async () => {\n      container.innerHTML = `<my-el-emits></my-el-emits>`\n      const e = container.childNodes[0] as VueElement\n      const spy = vi.fn()\n      e.addEventListener('my-wheel', spy)\n      e.shadowRoot!.childNodes[0].dispatchEvent(new CustomEvent('wheel'))\n      expect(spy).toHaveBeenCalledTimes(1)\n      expect(spy.mock.calls[0][0]).toMatchObject({\n        bubbles: true,\n        detail: [{ bubbles: true }, 1],\n      })\n    })\n  })\n\n  describe('slots', () => {\n    const E = defineCustomElement({\n      render() {\n        return [\n          h('div', null, [\n            renderSlot(this.$slots, 'default', undefined, () => [\n              h('div', 'fallback'),\n            ]),\n          ]),\n          h('div', null, renderSlot(this.$slots, 'named')),\n        ]\n      },\n    })\n    customElements.define('my-el-slots', E)\n\n    test('render slots correctly', () => {\n      container.innerHTML = `<my-el-slots><span>hi</span></my-el-slots>`\n      const e = container.childNodes[0] as VueElement\n      // native slots allocation does not affect innerHTML, so we just\n      // verify that we've rendered the correct native slots here...\n      expect(e.shadowRoot!.innerHTML).toBe(\n        `<div><slot><div>fallback</div></slot></div><div><slot name=\"named\"></slot></div>`,\n      )\n    })\n\n    test('render slot props', async () => {\n      const foo = ref('foo')\n      const E = defineCustomElement({\n        render() {\n          return [\n            h(\n              'div',\n              null,\n              renderSlot(this.$slots, 'default', { class: foo.value }),\n            ),\n          ]\n        },\n      })\n      customElements.define('my-el-slot-props', E)\n      container.innerHTML = `<my-el-slot-props><span>hi</span></my-el-slot-props>`\n      const e = container.childNodes[0] as VueElement\n      expect(e.shadowRoot!.innerHTML).toBe(\n        `<div><slot class=\"foo\"></slot></div>`,\n      )\n\n      foo.value = 'bar'\n      await nextTick()\n      expect(e.shadowRoot!.innerHTML).toBe(\n        `<div><slot class=\"bar\"></slot></div>`,\n      )\n    })\n  })\n\n  describe('provide/inject', () => {\n    const Consumer = defineCustomElement({\n      setup() {\n        const foo = inject<Ref>('foo')!\n        return () => h('div', foo.value)\n      },\n    })\n    customElements.define('my-consumer', Consumer)\n\n    test('over nested usage', async () => {\n      const foo = ref('injected!')\n      const Provider = defineCustomElement({\n        provide: {\n          foo,\n        },\n        render() {\n          return h('my-consumer')\n        },\n      })\n      customElements.define('my-provider', Provider)\n      container.innerHTML = `<my-provider><my-provider>`\n      const provider = container.childNodes[0] as VueElement\n      const consumer = provider.shadowRoot!.childNodes[0] as VueElement\n\n      expect(consumer.shadowRoot!.innerHTML).toBe(`<div>injected!</div>`)\n\n      foo.value = 'changed!'\n      await nextTick()\n      expect(consumer.shadowRoot!.innerHTML).toBe(`<div>changed!</div>`)\n    })\n\n    test('over slot composition', async () => {\n      const foo = ref('injected!')\n      const Provider = defineCustomElement({\n        provide: {\n          foo,\n        },\n        render() {\n          return renderSlot(this.$slots, 'default')\n        },\n      })\n      customElements.define('my-provider-2', Provider)\n\n      container.innerHTML = `<my-provider-2><my-consumer></my-consumer><my-provider-2>`\n      const provider = container.childNodes[0]\n      const consumer = provider.childNodes[0] as VueElement\n      expect(consumer.shadowRoot!.innerHTML).toBe(`<div>injected!</div>`)\n\n      foo.value = 'changed!'\n      await nextTick()\n      expect(consumer.shadowRoot!.innerHTML).toBe(`<div>changed!</div>`)\n    })\n\n    test('inherited from ancestors', async () => {\n      const fooA = ref('FooA!')\n      const fooB = ref('FooB!')\n      const ProviderA = defineCustomElement({\n        provide: {\n          fooA,\n        },\n        render() {\n          return h('provider-b')\n        },\n      })\n      const ProviderB = defineCustomElement({\n        provide: {\n          fooB,\n        },\n        render() {\n          return h('my-multi-consumer')\n        },\n      })\n\n      const Consumer = defineCustomElement({\n        setup() {\n          const fooA = inject<Ref>('fooA')!\n          const fooB = inject<Ref>('fooB')!\n          return () => h('div', `${fooA.value} ${fooB.value}`)\n        },\n      })\n\n      customElements.define('provider-a', ProviderA)\n      customElements.define('provider-b', ProviderB)\n      customElements.define('my-multi-consumer', Consumer)\n      container.innerHTML = `<provider-a><provider-a>`\n      const providerA = container.childNodes[0] as VueElement\n      const providerB = providerA.shadowRoot!.childNodes[0] as VueElement\n      const consumer = providerB.shadowRoot!.childNodes[0] as VueElement\n\n      expect(consumer.shadowRoot!.innerHTML).toBe(`<div>FooA! FooB!</div>`)\n\n      fooA.value = 'changedA!'\n      fooB.value = 'changedB!'\n      await nextTick()\n      expect(consumer.shadowRoot!.innerHTML).toBe(\n        `<div>changedA! changedB!</div>`,\n      )\n    })\n\n    test('should resolve correct parent when element is slotted in shadow DOM', async () => {\n      const GrandParent = defineCustomElement({\n        provide: {\n          foo: ref('GrandParent'),\n        },\n        render() {\n          return h('my-parent-in-shadow', h('slot'))\n        },\n      })\n      const Parent = defineCustomElement({\n        provide: {\n          foo: ref('Parent'),\n        },\n        render() {\n          return h('slot')\n        },\n      })\n      customElements.define('my-grand-parent', GrandParent)\n      customElements.define('my-parent-in-shadow', Parent)\n      container.innerHTML = `<my-grand-parent><my-consumer></my-consumer></my-grand-parent>`\n      const grandParent = container.childNodes[0] as VueElement,\n        consumer = grandParent.firstElementChild as VueElement\n      expect(consumer.shadowRoot!.textContent).toBe('Parent')\n    })\n\n    // #13212\n    test('inherited from app context within nested elements', async () => {\n      const outerValues: (string | undefined)[] = []\n      const innerValues: (string | undefined)[] = []\n      const innerChildValues: (string | undefined)[] = []\n\n      const Outer = defineCustomElement(\n        {\n          setup() {\n            outerValues.push(\n              inject<string>('shared'),\n              inject<string>('outer'),\n              inject<string>('inner'),\n            )\n          },\n          render() {\n            return h('div', [renderSlot(this.$slots, 'default')])\n          },\n        },\n        {\n          configureApp(app) {\n            app.provide('shared', 'shared')\n            app.provide('outer', 'outer')\n          },\n        },\n      )\n\n      const Inner = defineCustomElement(\n        {\n          setup() {\n            // ensure values are not self-injected\n            provide('inner', 'inner-child')\n\n            innerValues.push(\n              inject<string>('shared'),\n              inject<string>('outer'),\n              inject<string>('inner'),\n            )\n          },\n          render() {\n            return h('div', [renderSlot(this.$slots, 'default')])\n          },\n        },\n        {\n          configureApp(app) {\n            app.provide('outer', 'override-outer')\n            app.provide('inner', 'inner')\n          },\n        },\n      )\n\n      const InnerChild = defineCustomElement({\n        setup() {\n          innerChildValues.push(\n            inject<string>('shared'),\n            inject<string>('outer'),\n            inject<string>('inner'),\n          )\n        },\n        render() {\n          return h('div')\n        },\n      })\n\n      customElements.define('provide-from-app-outer', Outer)\n      customElements.define('provide-from-app-inner', Inner)\n      customElements.define('provide-from-app-inner-child', InnerChild)\n\n      container.innerHTML =\n        '<provide-from-app-outer>' +\n        '<provide-from-app-inner>' +\n        '<provide-from-app-inner-child></provide-from-app-inner-child>' +\n        '</provide-from-app-inner>' +\n        '</provide-from-app-outer>'\n\n      const outer = container.childNodes[0] as VueElement\n      expect(outer.shadowRoot!.innerHTML).toBe('<div><slot></slot></div>')\n\n      expect('[Vue warn]: injection \"inner\" not found.').toHaveBeenWarnedTimes(\n        1,\n      )\n      expect(\n        '[Vue warn]: App already provides property with key \"outer\" inherited from its parent element. ' +\n          'It will be overwritten with the new value.',\n      ).toHaveBeenWarnedTimes(1)\n\n      expect(outerValues).toEqual(['shared', 'outer', undefined])\n      expect(innerValues).toEqual(['shared', 'override-outer', 'inner'])\n      expect(innerChildValues).toEqual([\n        'shared',\n        'override-outer',\n        'inner-child',\n      ])\n    })\n  })\n\n  describe('styles', () => {\n    function assertStyles(el: VueElement, css: string[]) {\n      const styles = el.shadowRoot?.querySelectorAll('style')!\n      expect(styles.length).toBe(css.length) // should not duplicate multiple copies from Bar\n      for (let i = 0; i < css.length; i++) {\n        expect(styles[i].textContent).toBe(css[i])\n      }\n    }\n\n    test('should attach styles to shadow dom', async () => {\n      const def = defineComponent({\n        __hmrId: 'foo',\n        styles: [`div { color: red; }`],\n        render() {\n          return h('div', 'hello')\n        },\n      })\n      const Foo = defineCustomElement(def)\n      customElements.define('my-el-with-styles', Foo)\n      container.innerHTML = `<my-el-with-styles></my-el-with-styles>`\n      const el = container.childNodes[0] as VueElement\n      const style = el.shadowRoot?.querySelector('style')!\n      expect(style.textContent).toBe(`div { color: red; }`)\n\n      // hmr\n      __VUE_HMR_RUNTIME__.reload('foo', {\n        ...def,\n        styles: [`div { color: blue; }`, `div { color: yellow; }`],\n      } as any)\n\n      await nextTick()\n      assertStyles(el, [`div { color: blue; }`, `div { color: yellow; }`])\n    })\n\n    test(\"child components should inject styles to root element's shadow root\", async () => {\n      const Baz = () => h(Bar)\n      const Bar = defineComponent({\n        __hmrId: 'bar',\n        styles: [`div { color: green; }`, `div { color: blue; }`],\n        render() {\n          return 'bar'\n        },\n      })\n      const Foo = defineCustomElement({\n        styles: [`div { color: red; }`],\n        render() {\n          return [h(Baz), h(Baz)]\n        },\n      })\n      customElements.define('my-el-with-child-styles', Foo)\n      container.innerHTML = `<my-el-with-child-styles></my-el-with-child-styles>`\n      const el = container.childNodes[0] as VueElement\n\n      // inject order should be child -> parent\n      assertStyles(el, [\n        `div { color: green; }`,\n        `div { color: blue; }`,\n        `div { color: red; }`,\n      ])\n\n      // hmr\n      __VUE_HMR_RUNTIME__.reload(Bar.__hmrId!, {\n        ...Bar,\n        styles: [`div { color: red; }`, `div { color: yellow; }`],\n      } as any)\n\n      await nextTick()\n      assertStyles(el, [\n        `div { color: red; }`,\n        `div { color: yellow; }`,\n        `div { color: red; }`,\n      ])\n\n      __VUE_HMR_RUNTIME__.reload(Bar.__hmrId!, {\n        ...Bar,\n        styles: [`div { color: blue; }`],\n      } as any)\n      await nextTick()\n      assertStyles(el, [`div { color: blue; }`, `div { color: red; }`])\n    })\n\n    test('root custom element HMR should preserve child-first style order', async () => {\n      const Child = defineComponent({\n        styles: [`div { color: green; }`],\n        render() {\n          return 'child'\n        },\n      })\n      const def = defineComponent({\n        __hmrId: 'root-child-style-order',\n        styles: [`div { color: red; }`],\n        render() {\n          return h(Child)\n        },\n      })\n      const Foo = defineCustomElement(def)\n      customElements.define('my-el-root-hmr-style-order', Foo)\n      container.innerHTML = `<my-el-root-hmr-style-order></my-el-root-hmr-style-order>`\n      const el = container.childNodes[0] as VueElement\n\n      assertStyles(el, [`div { color: green; }`, `div { color: red; }`])\n\n      __VUE_HMR_RUNTIME__.reload(def.__hmrId!, {\n        ...def,\n        styles: [`div { color: blue; }`, `div { color: yellow; }`],\n      } as any)\n\n      await nextTick()\n      assertStyles(el, [\n        `div { color: green; }`,\n        `div { color: blue; }`,\n        `div { color: yellow; }`,\n      ])\n    })\n\n    test('inject child component styles before parent styles', async () => {\n      const Baz = () => h(Bar)\n      const Bar = defineComponent({\n        styles: [`div { color: green; }`],\n        render() {\n          return 'bar'\n        },\n      })\n      const WrapperBar = defineComponent({\n        styles: [`div { color: blue; }`],\n        render() {\n          return h(Baz)\n        },\n      })\n      const WBaz = () => h(WrapperBar)\n      const Foo = defineCustomElement({\n        styles: [`div { color: red; }`],\n        render() {\n          return [h(Baz), h(WBaz)]\n        },\n      })\n      customElements.define('my-el-with-wrapper-child-styles', Foo)\n      container.innerHTML = `<my-el-with-wrapper-child-styles></my-el-with-wrapper-child-styles>`\n      const el = container.childNodes[0] as VueElement\n\n      // inject order should be child -> parent\n      assertStyles(el, [\n        `div { color: green; }`,\n        `div { color: blue; }`,\n        `div { color: red; }`,\n      ])\n    })\n\n    test('inject nested child component styles after HMR removes parent styles', async () => {\n      const Bar = defineComponent({\n        __hmrId: 'nested-child-style-hmr-bar',\n        styles: [`div { color: green; }`],\n        render() {\n          return 'bar'\n        },\n      })\n      const WrapperBar = defineComponent({\n        __hmrId: 'nested-child-style-hmr-wrapper',\n        styles: [`div { color: blue; }`],\n        render() {\n          return h(Bar)\n        },\n      })\n      const Foo = defineCustomElement({\n        styles: [`div { color: red; }`],\n        render() {\n          return h(WrapperBar)\n        },\n      })\n      customElements.define('my-el-with-hmr-nested-child-styles', Foo)\n      container.innerHTML = `<my-el-with-hmr-nested-child-styles></my-el-with-hmr-nested-child-styles>`\n      const el = container.childNodes[0] as VueElement\n\n      assertStyles(el, [\n        `div { color: green; }`,\n        `div { color: blue; }`,\n        `div { color: red; }`,\n      ])\n\n      __VUE_HMR_RUNTIME__.reload(WrapperBar.__hmrId!, {\n        ...WrapperBar,\n        styles: undefined,\n      } as any)\n      await nextTick()\n      assertStyles(el, [`div { color: green; }`, `div { color: red; }`])\n\n      __VUE_HMR_RUNTIME__.reload(Bar.__hmrId!, {\n        ...Bar,\n        styles: [`div { color: yellow; }`],\n      } as any)\n      await nextTick()\n      assertStyles(el, [`div { color: yellow; }`, `div { color: red; }`])\n    })\n\n    test('inject child component styles when parent has no styles', async () => {\n      const Baz = () => h(Bar)\n      const Bar = defineComponent({\n        styles: [`div { color: green; }`],\n        render() {\n          return 'bar'\n        },\n      })\n      const WrapperBar = defineComponent({\n        styles: [`div { color: blue; }`],\n        render() {\n          return h(Baz)\n        },\n      })\n      const WBaz = () => h(WrapperBar)\n      // without styles\n      const Foo = defineCustomElement({\n        render() {\n          return [h(Baz), h(WBaz)]\n        },\n      })\n      customElements.define('my-el-with-inject-child-styles', Foo)\n      container.innerHTML = `<my-el-with-inject-child-styles></my-el-with-inject-child-styles>`\n      const el = container.childNodes[0] as VueElement\n\n      assertStyles(el, [`div { color: green; }`, `div { color: blue; }`])\n    })\n\n    test('inject nested child component styles', async () => {\n      const Baz = defineComponent({\n        styles: [`div { color: yellow; }`],\n        render() {\n          return h(Bar)\n        },\n      })\n      const Bar = defineComponent({\n        styles: [`div { color: green; }`],\n        render() {\n          return 'bar'\n        },\n      })\n      const WrapperBar = defineComponent({\n        styles: [`div { color: blue; }`],\n        render() {\n          return h(Baz)\n        },\n      })\n      const WBaz = defineComponent({\n        styles: [`div { color: black; }`],\n        render() {\n          return h(WrapperBar)\n        },\n      })\n      const Foo = defineCustomElement({\n        styles: [`div { color: red; }`],\n        render() {\n          return [h(Baz), h(WBaz)]\n        },\n      })\n      customElements.define('my-el-with-inject-nested-child-styles', Foo)\n      container.innerHTML = `<my-el-with-inject-nested-child-styles></my-el-with-inject-nested-child-styles>`\n      const el = container.childNodes[0] as VueElement\n      assertStyles(el, [\n        `div { color: green; }`,\n        `div { color: yellow; }`,\n        `div { color: blue; }`,\n        `div { color: black; }`,\n        `div { color: red; }`,\n      ])\n    })\n\n    test(\"child components should not inject styles to root element's shadow root w/ shadowRoot false\", async () => {\n      const Bar = defineComponent({\n        styles: [`div { color: green; }`],\n        render() {\n          return 'bar'\n        },\n      })\n      const Baz = () => h(Bar)\n      const Foo = defineCustomElement(\n        {\n          render() {\n            return [h(Baz)]\n          },\n        },\n        { shadowRoot: false },\n      )\n\n      customElements.define('my-foo-with-shadowroot-false', Foo)\n      container.innerHTML = `<my-foo-with-shadowroot-false></my-foo-with-shadowroot-false>`\n      const el = container.childNodes[0] as VueElement\n      const style = el.shadowRoot?.querySelector('style')\n      expect(style).toBeUndefined()\n    })\n\n    test('with nonce', () => {\n      const Foo = defineCustomElement(\n        {\n          styles: [`div { color: red; }`],\n          render() {\n            return h('div', 'hello')\n          },\n        },\n        { nonce: 'xxx' },\n      )\n      customElements.define('my-el-with-nonce', Foo)\n      container.innerHTML = `<my-el-with-nonce></my-el-with-nonce>`\n      const el = container.childNodes[0] as VueElement\n      const style = el.shadowRoot?.querySelector('style')!\n      expect(style.getAttribute('nonce')).toBe('xxx')\n    })\n  })\n\n  describe('async', () => {\n    test('should work', async () => {\n      const loaderSpy = vi.fn()\n      const E = defineCustomElement(\n        defineAsyncComponent(() => {\n          loaderSpy()\n          return Promise.resolve({\n            props: ['msg'],\n            styles: [`div { color: red }`],\n            render(this: any) {\n              return h('div', null, this.msg)\n            },\n          })\n        }),\n      )\n      customElements.define('my-el-async', E)\n      container.innerHTML =\n        `<my-el-async msg=\"hello\"></my-el-async>` +\n        `<my-el-async msg=\"world\"></my-el-async>`\n\n      await new Promise(r => setTimeout(r))\n\n      // loader should be called only once\n      expect(loaderSpy).toHaveBeenCalledTimes(1)\n\n      const e1 = container.childNodes[0] as VueElement\n      const e2 = container.childNodes[1] as VueElement\n\n      // should inject styles\n      expect(e1.shadowRoot!.innerHTML).toBe(\n        `<style>div { color: red }</style><div>hello</div>`,\n      )\n      expect(e2.shadowRoot!.innerHTML).toBe(\n        `<style>div { color: red }</style><div>world</div>`,\n      )\n\n      // attr\n      e1.setAttribute('msg', 'attr')\n      await nextTick()\n      expect((e1 as any).msg).toBe('attr')\n      expect(e1.shadowRoot!.innerHTML).toBe(\n        `<style>div { color: red }</style><div>attr</div>`,\n      )\n\n      // props\n      expect(`msg` in e1).toBe(true)\n      ;(e1 as any).msg = 'prop'\n      expect(e1.getAttribute('msg')).toBe('prop')\n      expect(e1.shadowRoot!.innerHTML).toBe(\n        `<style>div { color: red }</style><div>prop</div>`,\n      )\n    })\n\n    test('set DOM property before resolve', async () => {\n      const E = defineCustomElement(\n        defineAsyncComponent(() => {\n          return Promise.resolve({\n            props: ['msg'],\n            setup(props) {\n              expect(typeof props.msg).toBe('string')\n            },\n            render(this: any) {\n              return h('div', this.msg)\n            },\n          })\n        }),\n      )\n      customElements.define('my-el-async-2', E)\n\n      const e1 = new E()\n\n      // set property before connect\n      e1.msg = 'hello'\n\n      const e2 = new E()\n\n      container.appendChild(e1)\n      container.appendChild(e2)\n\n      // set property after connect but before resolve\n      e2.msg = 'world'\n\n      await new Promise(r => setTimeout(r))\n\n      expect(e1.shadowRoot!.innerHTML).toBe(`<div>hello</div>`)\n      expect(e2.shadowRoot!.innerHTML).toBe(`<div>world</div>`)\n\n      e1.msg = 'world'\n      expect(e1.shadowRoot!.innerHTML).toBe(`<div>world</div>`)\n\n      e2.msg = 'hello'\n      expect(e2.shadowRoot!.innerHTML).toBe(`<div>hello</div>`)\n    })\n\n    test('render object prop before resolve', async () => {\n      const AsyncComp = defineComponent({\n        props: { value: Object },\n        render(this: any) {\n          return h('div', this.value.x)\n        },\n      })\n      let resolve!: (comp: typeof AsyncComp) => void\n      const p = new Promise<typeof AsyncComp>(res => {\n        resolve = res\n      })\n      const E = defineCustomElement(defineAsyncComponent(() => p))\n      customElements.define('my-el-async-object-prop', E)\n\n      const root = document.createElement('div')\n      document.body.appendChild(root)\n      const value = { x: 1 }\n\n      render(h('my-el-async-object-prop', { value }), root)\n\n      const el = root.children[0] as VueElement & { value: typeof value }\n      expect(el.value).toBe(value)\n      expect(el.getAttribute('value')).toBe(null)\n\n      resolve(AsyncComp)\n\n      await new Promise(r => setTimeout(r))\n\n      expect(el.value).toBe(value)\n      expect(el.getAttribute('value')).toBe(null)\n      expect(el.shadowRoot!.innerHTML).toBe(`<div>1</div>`)\n\n      render(null, root)\n      root.remove()\n    })\n\n    test('Number prop casting before resolve', async () => {\n      const E = defineCustomElement(\n        defineAsyncComponent(() => {\n          return Promise.resolve({\n            props: { n: Number },\n            setup(props) {\n              expect(props.n).toBe(20)\n            },\n            render(this: any) {\n              return h('div', this.n + ',' + typeof this.n)\n            },\n          })\n        }),\n      )\n      customElements.define('my-el-async-3', E)\n      container.innerHTML = `<my-el-async-3 n=\"2e1\"></my-el-async-3>`\n\n      await new Promise(r => setTimeout(r))\n\n      const e = container.childNodes[0] as VueElement\n      expect(e.shadowRoot!.innerHTML).toBe(`<div>20,number</div>`)\n    })\n\n    test('with slots', async () => {\n      const E = defineCustomElement(\n        defineAsyncComponent(() => {\n          return Promise.resolve({\n            render(this: any) {\n              return [\n                h('div', null, [\n                  renderSlot(this.$slots, 'default', undefined, () => [\n                    h('div', 'fallback'),\n                  ]),\n                ]),\n                h('div', null, renderSlot(this.$slots, 'named')),\n              ]\n            },\n          })\n        }),\n      )\n      customElements.define('my-el-async-slots', E)\n      container.innerHTML = `<my-el-async-slots><span>hi</span></my-el-async-slots>`\n\n      await new Promise(r => setTimeout(r))\n\n      const e = container.childNodes[0] as VueElement\n      expect(e.shadowRoot!.innerHTML).toBe(\n        `<div><slot><div>fallback</div></slot></div><div><slot name=\"named\"></slot></div>`,\n      )\n    })\n  })\n\n  describe('shadowRoot: false', () => {\n    const E = defineCustomElement({\n      shadowRoot: false,\n      props: {\n        msg: {\n          type: String,\n          default: 'hello',\n        },\n      },\n      render() {\n        return h('div', this.msg)\n      },\n    })\n    customElements.define('my-el-shadowroot-false', E)\n\n    test('should work', async () => {\n      function raf() {\n        return new Promise(resolve => {\n          requestAnimationFrame(resolve)\n        })\n      }\n\n      container.innerHTML = `<my-el-shadowroot-false></my-el-shadowroot-false>`\n      const e = container.childNodes[0] as VueElement\n      await raf()\n      expect(e).toBeInstanceOf(E)\n      expect(e._instance).toBeTruthy()\n      expect(e.innerHTML).toBe(`<div>hello</div>`)\n      expect(e.shadowRoot).toBe(null)\n    })\n\n    const toggle = ref(true)\n    const ES = defineCustomElement(\n      {\n        render() {\n          return [\n            renderSlot(this.$slots, 'default'),\n            toggle.value ? renderSlot(this.$slots, 'named') : null,\n            renderSlot(this.$slots, 'omitted', {}, () => [\n              h('div', 'fallback'),\n            ]),\n          ]\n        },\n      },\n      { shadowRoot: false },\n    )\n    customElements.define('my-el-shadowroot-false-slots', ES)\n\n    test('should render slots', async () => {\n      container.innerHTML =\n        `<my-el-shadowroot-false-slots>` +\n        `<span>default</span>text` +\n        `<div slot=\"named\">named</div>` +\n        `</my-el-shadowroot-false-slots>`\n      const e = container.childNodes[0] as VueElement\n      // native slots allocation does not affect innerHTML, so we just\n      // verify that we've rendered the correct native slots here...\n      expect(e.innerHTML).toBe(\n        `<span>default</span>text` +\n          `<div slot=\"named\">named</div>` +\n          `<div>fallback</div>`,\n      )\n\n      toggle.value = false\n      await nextTick()\n      expect(e.innerHTML).toBe(\n        `<span>default</span>text` + `<!---->` + `<div>fallback</div>`,\n      )\n    })\n\n    test('render nested customElement w/ shadowRoot false', async () => {\n      const calls: string[] = []\n\n      const Child = defineCustomElement(\n        {\n          setup() {\n            calls.push('child rendering')\n            onMounted(() => {\n              calls.push('child mounted')\n            })\n          },\n          render() {\n            return renderSlot(this.$slots, 'default')\n          },\n        },\n        { shadowRoot: false },\n      )\n      customElements.define('my-child', Child)\n\n      const Parent = defineCustomElement(\n        {\n          setup() {\n            calls.push('parent rendering')\n            onMounted(() => {\n              calls.push('parent mounted')\n            })\n          },\n          render() {\n            return renderSlot(this.$slots, 'default')\n          },\n        },\n        { shadowRoot: false },\n      )\n      customElements.define('my-parent', Parent)\n\n      const App = {\n        render() {\n          return h('my-parent', null, {\n            default: () => [\n              h('my-child', null, {\n                default: () => [h('span', null, 'default')],\n              }),\n            ],\n          })\n        },\n      }\n      const app = createApp(App)\n      app.mount(container)\n      await nextTick()\n      const e = container.childNodes[0] as VueElement\n      expect(e.innerHTML).toBe(\n        `<my-child data-v-app=\"\"><span>default</span></my-child>`,\n      )\n      expect(calls).toEqual([\n        'parent rendering',\n        'parent mounted',\n        'child rendering',\n        'child mounted',\n      ])\n      app.unmount()\n    })\n\n    test('render nested Teleport w/ shadowRoot false', async () => {\n      const target = document.createElement('div')\n      const Child = defineCustomElement(\n        {\n          render() {\n            return h(\n              Teleport,\n              { to: target },\n              {\n                default: () => [renderSlot(this.$slots, 'default')],\n              },\n            )\n          },\n        },\n        { shadowRoot: false },\n      )\n      customElements.define('my-el-teleport-child', Child)\n      const Parent = defineCustomElement(\n        {\n          render() {\n            return renderSlot(this.$slots, 'default')\n          },\n        },\n        { shadowRoot: false },\n      )\n      customElements.define('my-el-teleport-parent', Parent)\n\n      const App = {\n        render() {\n          return h('my-el-teleport-parent', null, {\n            default: () => [\n              h('my-el-teleport-child', null, {\n                default: () => [h('span', null, 'default')],\n              }),\n            ],\n          })\n        },\n      }\n      const app = createApp(App)\n      app.mount(container)\n      await nextTick()\n      expect(target.innerHTML).toBe(`<span>default</span>`)\n      app.unmount()\n    })\n\n    test('render two Teleports w/ shadowRoot false', async () => {\n      const target1 = document.createElement('div')\n      const target2 = document.createElement('span')\n      const Child = defineCustomElement(\n        {\n          render() {\n            return [\n              h(Teleport, { to: target1 }, [renderSlot(this.$slots, 'header')]),\n              h(Teleport, { to: target2 }, [renderSlot(this.$slots, 'body')]),\n            ]\n          },\n        },\n        { shadowRoot: false },\n      )\n      customElements.define('my-el-two-teleport-child', Child)\n\n      const App = {\n        render() {\n          return h('my-el-two-teleport-child', null, {\n            default: () => [\n              h('div', { slot: 'header' }, 'header'),\n              h('span', { slot: 'body' }, 'body'),\n            ],\n          })\n        },\n      }\n      const app = createApp(App)\n      app.mount(container)\n      await nextTick()\n      expect(target1.outerHTML).toBe(\n        `<div><div slot=\"header\">header</div></div>`,\n      )\n      expect(target2.outerHTML).toBe(\n        `<span><span slot=\"body\">body</span></span>`,\n      )\n      app.unmount()\n    })\n\n    test('render two Teleports w/ shadowRoot false (with disabled)', async () => {\n      const target1 = document.createElement('div')\n      const target2 = document.createElement('span')\n      const Child = defineCustomElement(\n        {\n          render() {\n            return [\n              // with disabled: true\n              h(Teleport, { to: target1, disabled: true }, [\n                renderSlot(this.$slots, 'header'),\n              ]),\n              h(Teleport, { to: target2 }, [renderSlot(this.$slots, 'body')]),\n            ]\n          },\n        },\n        { shadowRoot: false },\n      )\n      customElements.define('my-el-two-teleport-child-0', Child)\n\n      const App = {\n        render() {\n          return h('my-el-two-teleport-child-0', null, {\n            default: () => [\n              h('div', { slot: 'header' }, 'header'),\n              h('span', { slot: 'body' }, 'body'),\n            ],\n          })\n        },\n      }\n      const app = createApp(App)\n      app.mount(container)\n      await nextTick()\n      expect(target1.outerHTML).toBe(`<div></div>`)\n      expect(target2.outerHTML).toBe(\n        `<span><span slot=\"body\">body</span></span>`,\n      )\n      app.unmount()\n    })\n\n    test('teleport target is ancestor of custom element host', async () => {\n      const Child = defineCustomElement(\n        {\n          render() {\n            return [\n              h(Teleport, { to: '#t1' }, [renderSlot(this.$slots, 'header')]),\n            ]\n          },\n        },\n        { shadowRoot: false },\n      )\n      customElements.define('my-el-teleport-child-target', Child)\n\n      const App = {\n        render() {\n          return h('div', { id: 't1' }, [\n            h('my-el-teleport-child-target', null, {\n              default: () => [h('div', { slot: 'header' }, 'header')],\n            }),\n          ])\n        },\n      }\n      const app = createApp(App)\n      app.mount(container)\n\n      const target1 = document.getElementById('t1')!\n      expect(target1.outerHTML).toBe(\n        `<div id=\"t1\">` +\n          `<my-el-teleport-child-target data-v-app=\"\">` +\n          `<!--teleport start--><!--teleport end-->` +\n          `</my-el-teleport-child-target>` +\n          `<div slot=\"header\">header</div>` +\n          `</div>`,\n      )\n\n      app.unmount()\n    })\n\n    test('toggle nested custom element with shadowRoot: false', async () => {\n      customElements.define(\n        'my-el-child-shadow-false',\n        defineCustomElement(\n          {\n            render(ctx: any) {\n              return h('div', null, [renderSlot(ctx.$slots, 'default')])\n            },\n          },\n          { shadowRoot: false },\n        ),\n      )\n      const ChildWrapper = {\n        render() {\n          return h('my-el-child-shadow-false', null, 'child')\n        },\n      }\n\n      customElements.define(\n        'my-el-parent-shadow-false',\n        defineCustomElement(\n          {\n            props: {\n              isShown: { type: Boolean, required: true },\n            },\n            render(ctx: any, _: any, $props: any) {\n              return $props.isShown\n                ? h('div', { key: 0 }, [renderSlot(ctx.$slots, 'default')])\n                : null\n            },\n          },\n          { shadowRoot: false },\n        ),\n      )\n      const ParentWrapper = {\n        props: {\n          isShown: { type: Boolean, required: true },\n        },\n        render(ctx: any, _: any, $props: any) {\n          return h('my-el-parent-shadow-false', { isShown: $props.isShown }, [\n            renderSlot(ctx.$slots, 'default'),\n          ])\n        },\n      }\n\n      const isShown = ref(true)\n      const App = {\n        render() {\n          return h(ParentWrapper, { isShown: isShown.value } as any, {\n            default: () => [h(ChildWrapper)],\n          })\n        },\n      }\n      const container = document.createElement('div')\n      document.body.appendChild(container)\n      const app = createApp(App)\n      app.mount(container)\n      expect(container.innerHTML).toBe(\n        `<my-el-parent-shadow-false is-shown=\"\" data-v-app=\"\">` +\n          `<div>` +\n          `<my-el-child-shadow-false data-v-app=\"\">` +\n          `<div>child</div>` +\n          `</my-el-child-shadow-false>` +\n          `</div>` +\n          `</my-el-parent-shadow-false>`,\n      )\n\n      isShown.value = false\n      await nextTick()\n      expect(container.innerHTML).toBe(\n        `<my-el-parent-shadow-false data-v-app=\"\"><!----></my-el-parent-shadow-false>`,\n      )\n\n      isShown.value = true\n      await nextTick()\n      expect(container.innerHTML).toBe(\n        `<my-el-parent-shadow-false data-v-app=\"\" is-shown=\"\">` +\n          `<div>` +\n          `<my-el-child-shadow-false data-v-app=\"\">` +\n          `<div>child</div>` +\n          `</my-el-child-shadow-false>` +\n          `</div>` +\n          `</my-el-parent-shadow-false>`,\n      )\n    })\n  })\n\n  describe('helpers', () => {\n    test('useHost', () => {\n      const Foo = defineCustomElement({\n        setup() {\n          const host = useHost()!\n          host.setAttribute('id', 'host')\n          return () => h('div', 'hello')\n        },\n      })\n      customElements.define('my-el-use-host', Foo)\n      container.innerHTML = `<my-el-use-host>`\n      const el = container.childNodes[0] as VueElement\n      expect(el.id).toBe('host')\n    })\n\n    test('useShadowRoot for style injection', () => {\n      const Foo = defineCustomElement({\n        setup() {\n          const root = useShadowRoot()!\n          const style = document.createElement('style')\n          style.innerHTML = `div { color: red; }`\n          root.appendChild(style)\n          return () => h('div', 'hello')\n        },\n      })\n      customElements.define('my-el-use-shadow-root', Foo)\n      container.innerHTML = `<my-el-use-shadow-root>`\n      const el = container.childNodes[0] as VueElement\n      const style = el.shadowRoot?.querySelector('style')!\n      expect(style.textContent).toBe(`div { color: red; }`)\n    })\n  })\n\n  describe('expose', () => {\n    test('expose w/ options api', async () => {\n      const E = defineCustomElement({\n        data() {\n          return {\n            value: 0,\n          }\n        },\n        methods: {\n          foo() {\n            ;(this as any).value++\n          },\n        },\n        expose: ['foo'],\n        render(_ctx: any) {\n          return h('div', null, _ctx.value)\n        },\n      })\n      customElements.define('my-el-expose-options-api', E)\n\n      container.innerHTML = `<my-el-expose-options-api></my-el-expose-options-api>`\n      const e = container.childNodes[0] as VueElement & {\n        foo: () => void\n      }\n      expect(e.shadowRoot!.innerHTML).toBe(`<div>0</div>`)\n      e.foo()\n      await nextTick()\n      expect(e.shadowRoot!.innerHTML).toBe(`<div>1</div>`)\n    })\n    test('expose attributes and callback', async () => {\n      type SetValue = (value: string) => void\n      let fn: MockedFunction<SetValue>\n\n      const E = defineCustomElement({\n        setup(_, { expose }) {\n          const value = ref('hello')\n\n          const setValue = (fn = vi.fn((_value: string) => {\n            value.value = _value\n          }))\n\n          expose({\n            setValue,\n            value,\n          })\n\n          return () => h('div', null, [value.value])\n        },\n      })\n      customElements.define('my-el-expose', E)\n\n      container.innerHTML = `<my-el-expose></my-el-expose>`\n      const e = container.childNodes[0] as VueElement & {\n        value: string\n        setValue: MockedFunction<SetValue>\n      }\n      expect(e.shadowRoot!.innerHTML).toBe(`<div>hello</div>`)\n      expect(e.value).toBe('hello')\n      expect(e.setValue).toBe(fn!)\n      e.setValue('world')\n      expect(e.value).toBe('world')\n      await nextTick()\n      expect(e.shadowRoot!.innerHTML).toBe(`<div>world</div>`)\n    })\n\n    test('warning when exposing an existing property', () => {\n      const E = defineCustomElement({\n        props: {\n          value: String,\n        },\n        setup(props, { expose }) {\n          expose({\n            value: 'hello',\n          })\n\n          return () => h('div', null, [props.value])\n        },\n      })\n      customElements.define('my-el-expose-two', E)\n\n      container.innerHTML = `<my-el-expose-two value=\"world\"></my-el-expose-two>`\n\n      expect(\n        `[Vue warn]: Exposed property \"value\" already exists on custom element.`,\n      ).toHaveBeenWarned()\n    })\n  })\n\n  test('async & nested custom elements', async () => {\n    let fooVal: string | undefined = ''\n    const E = defineCustomElement(\n      defineAsyncComponent(() => {\n        return Promise.resolve({\n          setup(props) {\n            provide('foo', 'foo')\n          },\n          render(this: any) {\n            return h('div', null, [renderSlot(this.$slots, 'default')])\n          },\n        })\n      }),\n    )\n\n    const EChild = defineCustomElement({\n      setup(props) {\n        fooVal = inject('foo')\n      },\n      render(this: any) {\n        return h('div', null, 'child')\n      },\n    })\n    customElements.define('my-el-async-nested-ce', E)\n    customElements.define('slotted-child', EChild)\n    container.innerHTML = `<my-el-async-nested-ce><div><slotted-child></slotted-child></div></my-el-async-nested-ce>`\n\n    await new Promise(r => setTimeout(r))\n    const e = container.childNodes[0] as VueElement\n    expect(e.shadowRoot!.innerHTML).toBe(`<div><slot></slot></div>`)\n    expect(fooVal).toBe('foo')\n  })\n\n  test('async & multiple levels of nested custom elements', async () => {\n    let fooVal: string | undefined = ''\n    let barVal: string | undefined = ''\n    const E = defineCustomElement(\n      defineAsyncComponent(() => {\n        return Promise.resolve({\n          setup(props) {\n            provide('foo', 'foo')\n          },\n          render(this: any) {\n            return h('div', null, [renderSlot(this.$slots, 'default')])\n          },\n        })\n      }),\n    )\n\n    const EChild = defineCustomElement({\n      setup(props) {\n        provide('bar', 'bar')\n      },\n      render(this: any) {\n        return h('div', null, [renderSlot(this.$slots, 'default')])\n      },\n    })\n\n    const EChild2 = defineCustomElement({\n      setup(props) {\n        fooVal = inject('foo')\n        barVal = inject('bar')\n      },\n      render(this: any) {\n        return h('div', null, 'child')\n      },\n    })\n    customElements.define('my-el-async-nested-m-ce', E)\n    customElements.define('slotted-child-m', EChild)\n    customElements.define('slotted-child2-m', EChild2)\n    container.innerHTML =\n      `<my-el-async-nested-m-ce>` +\n      `<div><slotted-child-m>` +\n      `<slotted-child2-m></slotted-child2-m>` +\n      `</slotted-child-m></div>` +\n      `</my-el-async-nested-m-ce>`\n\n    await new Promise(r => setTimeout(r))\n    const e = container.childNodes[0] as VueElement\n    expect(e.shadowRoot!.innerHTML).toBe(`<div><slot></slot></div>`)\n    expect(fooVal).toBe('foo')\n    expect(barVal).toBe('bar')\n  })\n\n  describe('configureApp', () => {\n    test('should work', () => {\n      const E = defineCustomElement(\n        () => {\n          const msg = inject('msg')\n          return () => h('div', msg!)\n        },\n        {\n          configureApp(app) {\n            app.provide('msg', 'app-injected')\n          },\n        },\n      )\n      customElements.define('my-element-with-app', E)\n\n      container.innerHTML = `<my-element-with-app></my-element-with-app>`\n      const e = container.childNodes[0] as VueElement\n\n      expect(e.shadowRoot?.innerHTML).toBe('<div>app-injected</div>')\n    })\n\n    // #12448\n    test('work with async component', async () => {\n      const AsyncComp = defineAsyncComponent(() => {\n        return Promise.resolve({\n          render() {\n            const msg: string | undefined = inject('msg')\n            return h('div', {}, msg)\n          },\n        } as any)\n      })\n      const E = defineCustomElement(AsyncComp, {\n        configureApp(app) {\n          app.provide('msg', 'app-injected')\n        },\n      })\n      customElements.define('my-async-element-with-app', E)\n\n      container.innerHTML = `<my-async-element-with-app></my-async-element-with-app>`\n      const e = container.childNodes[0] as VueElement\n      await new Promise(r => setTimeout(r))\n      expect(e.shadowRoot?.innerHTML).toBe('<div>app-injected</div>')\n    })\n\n    test('with hmr reload', async () => {\n      const __hmrId = '__hmrWithApp'\n      const def = defineComponent({\n        __hmrId,\n        setup() {\n          const msg = inject('msg')\n          return { msg }\n        },\n        render(this: any) {\n          return h('div', [h('span', this.msg), h('span', this.$foo)])\n        },\n      })\n      const E = defineCustomElement(def, {\n        configureApp(app) {\n          app.provide('msg', 'app-injected')\n          app.config.globalProperties.$foo = 'foo'\n        },\n      })\n      customElements.define('my-element-with-app-hmr', E)\n\n      container.innerHTML = `<my-element-with-app-hmr></my-element-with-app-hmr>`\n      const el = container.childNodes[0] as VueElement\n      expect(el.shadowRoot?.innerHTML).toBe(\n        `<div><span>app-injected</span><span>foo</span></div>`,\n      )\n\n      // hmr\n      __VUE_HMR_RUNTIME__.reload(__hmrId, def as any)\n\n      await nextTick()\n      expect(el.shadowRoot?.innerHTML).toBe(\n        `<div><span>app-injected</span><span>foo</span></div>`,\n      )\n    })\n  })\n\n  // #9885\n  test('avoid double mount when prop is set immediately after mount', () => {\n    customElements.define(\n      'my-input-dupe',\n      defineCustomElement({\n        props: {\n          value: String,\n        },\n        render() {\n          return 'hello'\n        },\n      }),\n    )\n    const container = document.createElement('div')\n    document.body.appendChild(container)\n    createApp({\n      render() {\n        return h('div', [\n          h('my-input-dupe', {\n            onVnodeMounted(vnode) {\n              vnode.el!.value = 'fesfes'\n            },\n          }),\n        ])\n      },\n    }).mount(container)\n    expect(container.children[0].children[0].shadowRoot?.innerHTML).toBe(\n      'hello',\n    )\n  })\n\n  // #11081\n  test('Props can be casted when mounting custom elements in component rendering functions', async () => {\n    const E = defineCustomElement(\n      defineAsyncComponent(() =>\n        Promise.resolve({\n          props: ['fooValue'],\n          setup(props) {\n            expect(props.fooValue).toBe('fooValue')\n            return () => h('div', props.fooValue)\n          },\n        }),\n      ),\n    )\n    customElements.define('my-el-async-4', E)\n    const R = defineComponent({\n      setup() {\n        const fooValue = ref('fooValue')\n        return () => {\n          return h('div', null, [\n            h('my-el-async-4', {\n              fooValue: fooValue.value,\n            }),\n          ])\n        }\n      },\n    })\n\n    const app = createApp(R)\n    app.mount(container)\n    await new Promise(r => setTimeout(r))\n    const e = container.querySelector('my-el-async-4') as VueElement\n    expect(e.shadowRoot!.innerHTML).toBe(`<div>fooValue</div>`)\n    app.unmount()\n  })\n\n  // #11276\n  test('delete prop on attr removal', async () => {\n    const E = defineCustomElement({\n      props: {\n        boo: {\n          type: Boolean,\n        },\n      },\n      render() {\n        return this.boo + ',' + typeof this.boo\n      },\n    })\n    customElements.define('el-attr-removal', E)\n    container.innerHTML = '<el-attr-removal boo>'\n    const e = container.childNodes[0] as VueElement\n    expect(e.shadowRoot!.innerHTML).toBe(`true,boolean`)\n    e.removeAttribute('boo')\n    await nextTick()\n    expect(e.shadowRoot!.innerHTML).toBe(`false,boolean`)\n  })\n\n  test('hyphenated attr removal', async () => {\n    const E = defineCustomElement({\n      props: {\n        fooBar: {\n          type: Boolean,\n        },\n      },\n      render() {\n        return this.fooBar\n      },\n    })\n    customElements.define('el-hyphenated-attr-removal', E)\n    const toggle = ref(true)\n    const Comp = {\n      render() {\n        return h('el-hyphenated-attr-removal', {\n          'foo-bar': toggle.value ? '' : null,\n        })\n      },\n    }\n    render(h(Comp), container)\n    const el = container.children[0]\n    expect(el.hasAttribute('foo-bar')).toBe(true)\n    expect((el as any).outerHTML).toBe(\n      `<el-hyphenated-attr-removal foo-bar=\"\"></el-hyphenated-attr-removal>`,\n    )\n\n    toggle.value = false\n    await nextTick()\n    expect(el.hasAttribute('foo-bar')).toBe(false)\n    expect((el as any).outerHTML).toBe(\n      `<el-hyphenated-attr-removal></el-hyphenated-attr-removal>`,\n    )\n  })\n\n  test('no unexpected mutation of the 1st argument', () => {\n    const Foo = {\n      name: 'Foo',\n    }\n\n    defineCustomElement(Foo, { shadowRoot: false })\n\n    expect(Foo).toEqual({\n      name: 'Foo',\n    })\n  })\n})\n"
  },
  {
    "path": "packages/runtime-dom/__tests__/customizedBuiltIn.spec.ts",
    "content": "import type { MockInstance } from 'vitest'\nimport { h, render } from '@vue/runtime-dom'\n\ndescribe('customized built-in elements support', () => {\n  let createElement: MockInstance\n  afterEach(() => {\n    createElement.mockRestore()\n  })\n\n  test('should created element with is option', () => {\n    const root = document.createElement('div')\n    createElement = vi.spyOn(document, 'createElement')\n    render(h('button', { is: 'plastic-button' }), root)\n    expect(createElement.mock.calls[0]).toMatchObject([\n      'button',\n      { is: 'plastic-button' },\n    ])\n    // should also render the attribute\n    expect(root.innerHTML).toBe(`<button is=\"plastic-button\"></button>`)\n  })\n})\n"
  },
  {
    "path": "packages/runtime-dom/__tests__/directives/vCloak.spec.ts",
    "content": "import { createApp } from '@vue/runtime-dom'\n\ndescribe('vCloak', () => {\n  test('should be removed after compile', () => {\n    const root = document.createElement('div')\n    root.setAttribute('v-cloak', '')\n    createApp({\n      render() {},\n    }).mount(root)\n    expect(root.hasAttribute('v-cloak')).toBe(false)\n  })\n})\n"
  },
  {
    "path": "packages/runtime-dom/__tests__/directives/vModel.spec.ts",
    "content": "import {\n  type VNode,\n  defineComponent,\n  h,\n  nextTick,\n  ref,\n  render,\n  vModelCheckbox,\n  vModelDynamic,\n  withDirectives,\n} from '@vue/runtime-dom'\n\nconst triggerEvent = (type: string, el: Element) => {\n  const event = new Event(type)\n  el.dispatchEvent(event)\n}\n\nconst withVModel = (node: VNode, arg: any, mods?: any) =>\n  withDirectives(node, [[vModelDynamic, arg, '', mods]])\n\nconst setValue = function (this: any, value: any) {\n  this.value = value\n}\n\nlet root: any\n\nbeforeEach(() => {\n  root = document.createElement('div') as any\n})\n\ndescribe('vModel', () => {\n  it('should work with text input', async () => {\n    const manualListener = vi.fn()\n    const component = defineComponent({\n      data() {\n        return { value: null }\n      },\n      render() {\n        return [\n          withVModel(\n            h('input', {\n              'onUpdate:modelValue': setValue.bind(this),\n              onInput: () => {\n                manualListener(data.value)\n              },\n            }),\n            this.value,\n          ),\n        ]\n      },\n    })\n    render(h(component), root)\n\n    const input = root.querySelector('input')!\n    const data = root._vnode.component.data\n    expect(input.value).toEqual('')\n\n    input.value = 'foo'\n    triggerEvent('input', input)\n    await nextTick()\n    expect(data.value).toEqual('foo')\n    // #1931\n    expect(manualListener).toHaveBeenCalledWith('foo')\n\n    data.value = 'bar'\n    await nextTick()\n    expect(input.value).toEqual('bar')\n\n    data.value = undefined\n    await nextTick()\n    expect(input.value).toEqual('')\n  })\n\n  it('should work with number input', async () => {\n    const component = defineComponent({\n      data() {\n        return { value: null }\n      },\n      render() {\n        return [\n          withVModel(\n            h('input', {\n              type: 'number',\n              'onUpdate:modelValue': setValue.bind(this),\n            }),\n            this.value,\n          ),\n        ]\n      },\n    })\n    render(h(component), root)\n\n    const input = root.querySelector('input')!\n    const data = root._vnode.component.data\n    expect(input.value).toEqual('')\n    expect(input.type).toEqual('number')\n\n    input.value = 1\n    triggerEvent('input', input)\n    await nextTick()\n    expect(typeof data.value).toEqual('number')\n    expect(data.value).toEqual(1)\n  })\n\n  // #7003\n  it('should work with number input and be able to update rendering correctly', async () => {\n    const setValue1 = function (this: any, value: any) {\n      this.value1 = value\n    }\n    const setValue2 = function (this: any, value: any) {\n      this.value2 = value\n    }\n    const component = defineComponent({\n      data() {\n        return { value1: 1.002, value2: 1.002 }\n      },\n      render() {\n        return [\n          withVModel(\n            h('input', {\n              id: 'input_num1',\n              type: 'number',\n              'onUpdate:modelValue': setValue1.bind(this),\n            }),\n            this.value1,\n          ),\n          withVModel(\n            h('input', {\n              id: 'input_num2',\n              type: 'number',\n              'onUpdate:modelValue': setValue2.bind(this),\n            }),\n            this.value2,\n          ),\n        ]\n      },\n    })\n    render(h(component), root)\n    const data = root._vnode.component.data\n\n    const inputNum1 = root.querySelector('#input_num1')!\n    expect(inputNum1.value).toBe('1.002')\n\n    const inputNum2 = root.querySelector('#input_num2')!\n    expect(inputNum2.value).toBe('1.002')\n\n    inputNum1.value = '1.00'\n    triggerEvent('input', inputNum1)\n    await nextTick()\n    expect(data.value1).toBe(1)\n\n    inputNum2.value = '1.00'\n    triggerEvent('input', inputNum2)\n    await nextTick()\n    expect(data.value2).toBe(1)\n\n    expect(inputNum1.value).toBe('1.00')\n  })\n\n  it('should work with multiple listeners', async () => {\n    const spy = vi.fn()\n    const component = defineComponent({\n      data() {\n        return { value: null }\n      },\n      render() {\n        return [\n          withVModel(\n            h('input', {\n              'onUpdate:modelValue': [setValue.bind(this), spy],\n            }),\n            this.value,\n          ),\n        ]\n      },\n    })\n    render(h(component), root)\n\n    const input = root.querySelector('input')!\n    const data = root._vnode.component.data\n\n    input.value = 'foo'\n    triggerEvent('input', input)\n    await nextTick()\n    expect(data.value).toEqual('foo')\n    expect(spy).toHaveBeenCalledWith('foo')\n  })\n\n  it('should work with updated listeners', async () => {\n    const spy1 = vi.fn()\n    const spy2 = vi.fn()\n    const toggle = ref(true)\n\n    const component = defineComponent({\n      render() {\n        return [\n          withVModel(\n            h('input', {\n              'onUpdate:modelValue': toggle.value ? spy1 : spy2,\n            }),\n            'foo',\n          ),\n        ]\n      },\n    })\n    render(h(component), root)\n\n    const input = root.querySelector('input')!\n\n    input.value = 'foo'\n    triggerEvent('input', input)\n    await nextTick()\n    expect(spy1).toHaveBeenCalledWith('foo')\n\n    // update listener\n    toggle.value = false\n    await nextTick()\n\n    input.value = 'bar'\n    triggerEvent('input', input)\n    await nextTick()\n    expect(spy1).not.toHaveBeenCalledWith('bar')\n    expect(spy2).toHaveBeenCalledWith('bar')\n  })\n\n  it('should work with textarea', async () => {\n    const component = defineComponent({\n      data() {\n        return { value: null }\n      },\n      render() {\n        return [\n          withVModel(\n            h('textarea', {\n              'onUpdate:modelValue': setValue.bind(this),\n            }),\n            this.value,\n          ),\n        ]\n      },\n    })\n    render(h(component), root)\n\n    const input = root.querySelector('textarea')\n    const data = root._vnode.component.data\n\n    input.value = 'foo'\n    triggerEvent('input', input)\n    await nextTick()\n    expect(data.value).toEqual('foo')\n\n    data.value = 'bar'\n    await nextTick()\n    expect(input.value).toEqual('bar')\n  })\n\n  it('should support modifiers', async () => {\n    const component = defineComponent({\n      data() {\n        return {\n          number: null,\n          trim: null,\n          lazy: null,\n          trimNumber: null,\n          trimLazy: null,\n        }\n      },\n      render() {\n        return [\n          withVModel(\n            h('input', {\n              class: 'number',\n              'onUpdate:modelValue': (val: any) => {\n                this.number = val\n              },\n            }),\n            this.number,\n            {\n              number: true,\n            },\n          ),\n          withVModel(\n            h('input', {\n              class: 'trim',\n              'onUpdate:modelValue': (val: any) => {\n                this.trim = val\n              },\n            }),\n            this.trim,\n            {\n              trim: true,\n            },\n          ),\n          withVModel(\n            h('input', {\n              class: 'trim-lazy',\n              'onUpdate:modelValue': (val: any) => {\n                this.trimLazy = val\n              },\n            }),\n            this.trim,\n            {\n              trim: true,\n              lazy: true,\n            },\n          ),\n          withVModel(\n            h('input', {\n              class: 'trim-number',\n              'onUpdate:modelValue': (val: any) => {\n                this.trimNumber = val\n              },\n            }),\n            this.trimNumber,\n            {\n              trim: true,\n              number: true,\n            },\n          ),\n          withVModel(\n            h('input', {\n              class: 'lazy',\n              'onUpdate:modelValue': (val: any) => {\n                this.lazy = val\n              },\n            }),\n            this.lazy,\n            {\n              lazy: true,\n            },\n          ),\n        ]\n      },\n    })\n    render(h(component), root)\n\n    const number = root.querySelector('.number')\n    const trim = root.querySelector('.trim')\n    const trimNumber = root.querySelector('.trim-number')\n    const trimLazy = root.querySelector('.trim-lazy')\n    const lazy = root.querySelector('.lazy')\n    const data = root._vnode.component.data\n\n    number.value = '+01.2'\n    triggerEvent('input', number)\n    await nextTick()\n    expect(data.number).toEqual(1.2)\n    triggerEvent('change', number)\n    await nextTick()\n    expect(number.value).toEqual('1.2')\n\n    trim.value = '    hello, world    '\n    triggerEvent('input', trim)\n    await nextTick()\n    expect(data.trim).toEqual('hello, world')\n\n    trimNumber.value = '    1    '\n    triggerEvent('input', trimNumber)\n    await nextTick()\n    expect(data.trimNumber).toEqual(1)\n\n    trimNumber.value = '    +01.2    '\n    triggerEvent('input', trimNumber)\n    await nextTick()\n    expect(data.trimNumber).toEqual(1.2)\n\n    trimLazy.value = '   ddd    '\n    triggerEvent('change', trimLazy)\n    await nextTick()\n    expect(data.trimLazy).toEqual('ddd')\n\n    lazy.value = 'foo'\n    triggerEvent('change', lazy)\n    await nextTick()\n    expect(data.lazy).toEqual('foo')\n  })\n\n  it('should work with range', async () => {\n    const component = defineComponent({\n      data() {\n        return { value: 25 }\n      },\n      render() {\n        return [\n          withVModel(\n            h('input', {\n              type: 'range',\n              min: 1,\n              max: 100,\n              class: 'foo',\n              'onUpdate:modelValue': setValue.bind(this),\n            }),\n            this.value,\n            {\n              number: true,\n            },\n          ),\n          withVModel(\n            h('input', {\n              type: 'range',\n              min: 1,\n              max: 100,\n              class: 'bar',\n              'onUpdate:modelValue': setValue.bind(this),\n            }),\n            this.value,\n            {\n              lazy: true,\n            },\n          ),\n        ]\n      },\n    })\n    render(h(component), root)\n\n    const foo = root.querySelector('.foo')\n    const bar = root.querySelector('.bar')\n    const data = root._vnode.component.data\n\n    foo.value = 20\n    triggerEvent('input', foo)\n    await nextTick()\n    expect(data.value).toEqual(20)\n\n    foo.value = 200\n    triggerEvent('input', foo)\n    await nextTick()\n    expect(data.value).toEqual(100)\n\n    foo.value = -1\n    triggerEvent('input', foo)\n    await nextTick()\n    expect(data.value).toEqual(1)\n\n    bar.value = 30\n    triggerEvent('change', bar)\n    await nextTick()\n    expect(data.value).toEqual('30')\n\n    bar.value = 200\n    triggerEvent('change', bar)\n    await nextTick()\n    expect(data.value).toEqual('100')\n\n    bar.value = -1\n    triggerEvent('change', bar)\n    await nextTick()\n    expect(data.value).toEqual('1')\n\n    data.value = 60\n    await nextTick()\n    expect(foo.value).toEqual('60')\n    expect(bar.value).toEqual('60')\n\n    data.value = -1\n    await nextTick()\n    expect(foo.value).toEqual('1')\n    expect(bar.value).toEqual('1')\n\n    data.value = 200\n    await nextTick()\n    expect(foo.value).toEqual('100')\n    expect(bar.value).toEqual('100')\n  })\n\n  it('should work with checkbox', async () => {\n    const component = defineComponent({\n      data() {\n        return { value: null }\n      },\n      render() {\n        return [\n          withVModel(\n            h('input', {\n              type: 'checkbox',\n              'onUpdate:modelValue': setValue.bind(this),\n            }),\n            this.value,\n          ),\n        ]\n      },\n    })\n    render(h(component), root)\n\n    const input = root.querySelector('input')\n    const data = root._vnode.component.data\n\n    input.checked = true\n    triggerEvent('change', input)\n    await nextTick()\n    expect(data.value).toEqual(true)\n\n    data.value = false\n    await nextTick()\n    expect(input.checked).toEqual(false)\n\n    data.value = true\n    await nextTick()\n    expect(input.checked).toEqual(true)\n\n    input.checked = false\n    triggerEvent('change', input)\n    await nextTick()\n    expect(data.value).toEqual(false)\n  })\n\n  it('should work with checkbox and true-value/false-value', async () => {\n    const component = defineComponent({\n      data() {\n        return { value: 'yes' }\n      },\n      render() {\n        return [\n          withVModel(\n            h('input', {\n              type: 'checkbox',\n              'true-value': 'yes',\n              'false-value': 'no',\n              'onUpdate:modelValue': setValue.bind(this),\n            }),\n            this.value,\n          ),\n        ]\n      },\n    })\n    render(h(component), root)\n\n    const input = root.querySelector('input')\n    const data = root._vnode.component.data\n\n    // DOM checked state should respect initial true-value/false-value\n    expect(input.checked).toEqual(true)\n\n    input.checked = false\n    triggerEvent('change', input)\n    await nextTick()\n    expect(data.value).toEqual('no')\n\n    data.value = 'yes'\n    await nextTick()\n    expect(input.checked).toEqual(true)\n\n    data.value = 'no'\n    await nextTick()\n    expect(input.checked).toEqual(false)\n\n    input.checked = true\n    triggerEvent('change', input)\n    await nextTick()\n    expect(data.value).toEqual('yes')\n  })\n\n  it('should work with checkbox and true-value/false-value with object values', async () => {\n    const component = defineComponent({\n      data() {\n        return { value: null }\n      },\n      render() {\n        return [\n          withVModel(\n            h('input', {\n              type: 'checkbox',\n              'true-value': { yes: 'yes' },\n              'false-value': { no: 'no' },\n              'onUpdate:modelValue': setValue.bind(this),\n            }),\n            this.value,\n          ),\n        ]\n      },\n    })\n    render(h(component), root)\n\n    const input = root.querySelector('input')\n    const data = root._vnode.component.data\n\n    input.checked = true\n    triggerEvent('change', input)\n    await nextTick()\n    expect(data.value).toEqual({ yes: 'yes' })\n\n    data.value = { no: 'no' }\n    await nextTick()\n    expect(input.checked).toEqual(false)\n\n    data.value = { yes: 'yes' }\n    await nextTick()\n    expect(input.checked).toEqual(true)\n\n    input.checked = false\n    triggerEvent('change', input)\n    await nextTick()\n    expect(data.value).toEqual({ no: 'no' })\n  })\n\n  it(`should support array as a checkbox model`, async () => {\n    const component = defineComponent({\n      data() {\n        return { value: [] }\n      },\n      render() {\n        return [\n          withVModel(\n            h('input', {\n              type: 'checkbox',\n              class: 'foo',\n              value: 'foo',\n              'onUpdate:modelValue': setValue.bind(this),\n            }),\n            this.value,\n          ),\n          withVModel(\n            h('input', {\n              type: 'checkbox',\n              class: 'bar',\n              value: 'bar',\n              'onUpdate:modelValue': setValue.bind(this),\n            }),\n            this.value,\n          ),\n        ]\n      },\n    })\n    render(h(component), root)\n\n    const foo = root.querySelector('.foo')\n    const bar = root.querySelector('.bar')\n    const data = root._vnode.component.data\n\n    foo.checked = true\n    triggerEvent('change', foo)\n    await nextTick()\n    expect(data.value).toMatchObject(['foo'])\n\n    bar.checked = true\n    triggerEvent('change', bar)\n    await nextTick()\n    expect(data.value).toMatchObject(['foo', 'bar'])\n\n    bar.checked = false\n    triggerEvent('change', bar)\n    await nextTick()\n    expect(data.value).toMatchObject(['foo'])\n\n    foo.checked = false\n    triggerEvent('change', foo)\n    await nextTick()\n    expect(data.value).toMatchObject([])\n\n    data.value = ['foo']\n    await nextTick()\n    expect(bar.checked).toEqual(false)\n    expect(foo.checked).toEqual(true)\n\n    data.value = ['bar']\n    await nextTick()\n    expect(foo.checked).toEqual(false)\n    expect(bar.checked).toEqual(true)\n\n    data.value = []\n    await nextTick()\n    expect(foo.checked).toEqual(false)\n    expect(bar.checked).toEqual(false)\n  })\n\n  it(`should support Set as a checkbox model`, async () => {\n    const component = defineComponent({\n      data() {\n        return { value: new Set() }\n      },\n      render() {\n        return [\n          withVModel(\n            h('input', {\n              type: 'checkbox',\n              class: 'foo',\n              value: 'foo',\n              'onUpdate:modelValue': setValue.bind(this),\n            }),\n            this.value,\n          ),\n          withVModel(\n            h('input', {\n              type: 'checkbox',\n              class: 'bar',\n              value: 'bar',\n              'onUpdate:modelValue': setValue.bind(this),\n            }),\n            this.value,\n          ),\n        ]\n      },\n    })\n    render(h(component), root)\n\n    const foo = root.querySelector('.foo')\n    const bar = root.querySelector('.bar')\n    const data = root._vnode.component.data\n\n    foo.checked = true\n    triggerEvent('change', foo)\n    await nextTick()\n    expect(data.value).toMatchObject(new Set(['foo']))\n\n    bar.checked = true\n    triggerEvent('change', bar)\n    await nextTick()\n    expect(data.value).toMatchObject(new Set(['foo', 'bar']))\n\n    bar.checked = false\n    triggerEvent('change', bar)\n    await nextTick()\n    expect(data.value).toMatchObject(new Set(['foo']))\n\n    foo.checked = false\n    triggerEvent('change', foo)\n    await nextTick()\n    expect(data.value).toMatchObject(new Set())\n\n    data.value = new Set(['foo'])\n    await nextTick()\n    expect(bar.checked).toEqual(false)\n    expect(foo.checked).toEqual(true)\n\n    data.value = new Set(['bar'])\n    await nextTick()\n    expect(foo.checked).toEqual(false)\n    expect(bar.checked).toEqual(true)\n\n    data.value = new Set()\n    await nextTick()\n    expect(foo.checked).toEqual(false)\n    expect(bar.checked).toEqual(false)\n  })\n\n  it('should not update DOM unnecessarily', async () => {\n    const component = defineComponent({\n      data() {\n        return { value: true }\n      },\n      render() {\n        return [\n          withVModel(\n            h('input', {\n              type: 'checkbox',\n              'onUpdate:modelValue': setValue.bind(this),\n            }),\n            this.value,\n          ),\n        ]\n      },\n    })\n    render(h(component), root)\n\n    const input = root.querySelector('input')\n    const data = root._vnode.component.data\n\n    const setCheckedSpy = vi.spyOn(input, 'checked', 'set')\n\n    // Trigger a change event without actually changing the value\n    triggerEvent('change', input)\n    await nextTick()\n    expect(data.value).toEqual(true)\n    expect(setCheckedSpy).not.toHaveBeenCalled()\n\n    // Change the value and trigger a change event\n    input.checked = false\n    triggerEvent('change', input)\n    await nextTick()\n    expect(data.value).toEqual(false)\n    expect(setCheckedSpy).toHaveBeenCalledTimes(1)\n\n    setCheckedSpy.mockClear()\n\n    data.value = false\n    await nextTick()\n    expect(input.checked).toEqual(false)\n    expect(setCheckedSpy).not.toHaveBeenCalled()\n\n    data.value = true\n    await nextTick()\n    expect(input.checked).toEqual(true)\n    expect(setCheckedSpy).toHaveBeenCalledTimes(1)\n  })\n\n  it('should handle array values correctly without unnecessary updates', async () => {\n    const component = defineComponent({\n      data() {\n        return { value: ['foo'] }\n      },\n      render() {\n        return [\n          withVModel(\n            h('input', {\n              type: 'checkbox',\n              value: 'foo',\n              'onUpdate:modelValue': setValue.bind(this),\n            }),\n            this.value,\n          ),\n          withVModel(\n            h('input', {\n              type: 'checkbox',\n              value: 'bar',\n              'onUpdate:modelValue': setValue.bind(this),\n            }),\n            this.value,\n          ),\n        ]\n      },\n    })\n    render(h(component), root)\n\n    const [foo, bar] = root.querySelectorAll('input')\n    const data = root._vnode.component.data\n\n    const setCheckedSpyFoo = vi.spyOn(foo, 'checked', 'set')\n    const setCheckedSpyBar = vi.spyOn(bar, 'checked', 'set')\n\n    expect(foo.checked).toEqual(true)\n    expect(bar.checked).toEqual(false)\n\n    triggerEvent('change', foo)\n    await nextTick()\n    expect(data.value).toEqual(['foo'])\n    expect(setCheckedSpyFoo).not.toHaveBeenCalled()\n\n    bar.checked = true\n    triggerEvent('change', bar)\n    await nextTick()\n    expect(data.value).toEqual(['foo', 'bar'])\n    expect(setCheckedSpyBar).toHaveBeenCalledTimes(1)\n\n    setCheckedSpyFoo.mockClear()\n    setCheckedSpyBar.mockClear()\n\n    data.value = ['foo', 'bar']\n    await nextTick()\n    expect(setCheckedSpyFoo).not.toHaveBeenCalled()\n    expect(setCheckedSpyBar).not.toHaveBeenCalled()\n\n    data.value = ['bar']\n    await nextTick()\n    expect(setCheckedSpyFoo).toHaveBeenCalledTimes(1)\n    expect(setCheckedSpyBar).not.toHaveBeenCalled()\n    expect(foo.checked).toEqual(false)\n    expect(bar.checked).toEqual(true)\n  })\n\n  it('should work with radio', async () => {\n    const component = defineComponent({\n      data() {\n        return { value: null }\n      },\n      render() {\n        return [\n          withVModel(\n            h('input', {\n              type: 'radio',\n              class: 'foo',\n              value: 'foo',\n              'onUpdate:modelValue': setValue.bind(this),\n            }),\n            this.value,\n          ),\n          withVModel(\n            h('input', {\n              type: 'radio',\n              class: 'bar',\n              value: 'bar',\n              'onUpdate:modelValue': setValue.bind(this),\n            }),\n            this.value,\n          ),\n        ]\n      },\n    })\n    render(h(component), root)\n\n    const foo = root.querySelector('.foo')\n    const bar = root.querySelector('.bar')\n    const data = root._vnode.component.data\n\n    foo.checked = true\n    triggerEvent('change', foo)\n    await nextTick()\n    expect(data.value).toEqual('foo')\n\n    bar.checked = true\n    triggerEvent('change', bar)\n    await nextTick()\n    expect(data.value).toEqual('bar')\n\n    data.value = null\n    await nextTick()\n    expect(foo.checked).toEqual(false)\n    expect(bar.checked).toEqual(false)\n\n    data.value = 'foo'\n    await nextTick()\n    expect(foo.checked).toEqual(true)\n    expect(bar.checked).toEqual(false)\n\n    data.value = 'bar'\n    await nextTick()\n    expect(foo.checked).toEqual(false)\n    expect(bar.checked).toEqual(true)\n  })\n\n  it('should work with single select', async () => {\n    const component = defineComponent({\n      data() {\n        return { value: null }\n      },\n      render() {\n        return [\n          withVModel(\n            h(\n              'select',\n              {\n                value: null,\n                'onUpdate:modelValue': setValue.bind(this),\n              },\n              [h('option', { value: 'foo' }), h('option', { value: 'bar' })],\n            ),\n            this.value,\n          ),\n        ]\n      },\n    })\n    render(h(component), root)\n\n    const input = root.querySelector('select')\n    const foo = root.querySelector('option[value=foo]')\n    const bar = root.querySelector('option[value=bar]')\n    const data = root._vnode.component.data\n\n    foo.selected = true\n    triggerEvent('change', input)\n    await nextTick()\n    expect(data.value).toEqual('foo')\n\n    foo.selected = false\n    bar.selected = true\n    triggerEvent('change', input)\n    await nextTick()\n    expect(data.value).toEqual('bar')\n\n    foo.selected = false\n    bar.selected = false\n    data.value = 'foo'\n    await nextTick()\n    expect(input.value).toEqual('foo')\n    expect(foo.selected).toEqual(true)\n    expect(bar.selected).toEqual(false)\n\n    foo.selected = true\n    bar.selected = false\n    data.value = 'bar'\n    await nextTick()\n    expect(input.value).toEqual('bar')\n    expect(foo.selected).toEqual(false)\n    expect(bar.selected).toEqual(true)\n  })\n\n  it('multiple select (model is Array)', async () => {\n    const component = defineComponent({\n      data() {\n        return { value: [] }\n      },\n      render() {\n        return [\n          withVModel(\n            h(\n              'select',\n              {\n                value: null,\n                multiple: true,\n                'onUpdate:modelValue': setValue.bind(this),\n              },\n              [h('option', { value: 'foo' }), h('option', { value: 'bar' })],\n            ),\n            this.value,\n          ),\n        ]\n      },\n    })\n    render(h(component), root)\n\n    const input = root.querySelector('select')\n    const foo = root.querySelector('option[value=foo]')\n    const bar = root.querySelector('option[value=bar]')\n    const data = root._vnode.component.data\n\n    foo.selected = true\n    triggerEvent('change', input)\n    await nextTick()\n    expect(data.value).toMatchObject(['foo'])\n\n    foo.selected = false\n    bar.selected = true\n    triggerEvent('change', input)\n    await nextTick()\n    expect(data.value).toMatchObject(['bar'])\n\n    foo.selected = true\n    bar.selected = true\n    triggerEvent('change', input)\n    await nextTick()\n    expect(data.value).toMatchObject(['foo', 'bar'])\n\n    foo.selected = false\n    bar.selected = false\n    data.value = ['foo']\n    await nextTick()\n    expect(input.value).toEqual('foo')\n    expect(foo.selected).toEqual(true)\n    expect(bar.selected).toEqual(false)\n\n    foo.selected = false\n    bar.selected = false\n    data.value = ['foo', 'bar']\n    await nextTick()\n    expect(foo.selected).toEqual(true)\n    expect(bar.selected).toEqual(true)\n  })\n\n  it('v-model.number should work with select tag', async () => {\n    const component = defineComponent({\n      data() {\n        return { value: null }\n      },\n      render() {\n        return [\n          withVModel(\n            h(\n              'select',\n              {\n                value: null,\n                'onUpdate:modelValue': setValue.bind(this),\n              },\n              [h('option', { value: '1' }), h('option', { value: '2' })],\n            ),\n            this.value,\n            {\n              number: true,\n            },\n          ),\n        ]\n      },\n    })\n    render(h(component), root)\n\n    const input = root.querySelector('select')\n    const one = root.querySelector('option[value=\"1\"]')\n    const data = root._vnode.component.data\n\n    one.selected = true\n    triggerEvent('change', input)\n    await nextTick()\n    expect(typeof data.value).toEqual('number')\n    expect(data.value).toEqual(1)\n  })\n\n  it('v-model.number should work with multiple select', async () => {\n    const component = defineComponent({\n      data() {\n        return { value: [] }\n      },\n      render() {\n        return [\n          withVModel(\n            h(\n              'select',\n              {\n                value: null,\n                multiple: true,\n                'onUpdate:modelValue': setValue.bind(this),\n              },\n              [h('option', { value: '1' }), h('option', { value: '2' })],\n            ),\n            this.value,\n            {\n              number: true,\n            },\n          ),\n        ]\n      },\n    })\n    render(h(component), root)\n\n    const input = root.querySelector('select')\n    const one = root.querySelector('option[value=\"1\"]')\n    const two = root.querySelector('option[value=\"2\"]')\n    const data = root._vnode.component.data\n\n    one.selected = true\n    two.selected = false\n    triggerEvent('change', input)\n    await nextTick()\n    expect(data.value).toMatchObject([1])\n\n    one.selected = false\n    two.selected = true\n    triggerEvent('change', input)\n    await nextTick()\n    expect(data.value).toMatchObject([2])\n\n    one.selected = true\n    two.selected = true\n    triggerEvent('change', input)\n    await nextTick()\n    expect(data.value).toMatchObject([1, 2])\n\n    one.selected = false\n    two.selected = false\n    data.value = [1]\n    await nextTick()\n    expect(one.selected).toEqual(true)\n    expect(two.selected).toEqual(false)\n\n    one.selected = false\n    two.selected = false\n    data.value = [1, 2]\n    await nextTick()\n    expect(one.selected).toEqual(true)\n    expect(two.selected).toEqual(true)\n  })\n\n  it('multiple select (model is Array, option value is object)', async () => {\n    const fooValue = { foo: 1 }\n    const barValue = { bar: 1 }\n\n    const component = defineComponent({\n      data() {\n        return { value: [] }\n      },\n      render() {\n        return [\n          withVModel(\n            h(\n              'select',\n              {\n                value: null,\n                multiple: true,\n                'onUpdate:modelValue': setValue.bind(this),\n              },\n              [\n                h('option', { value: fooValue }),\n                h('option', { value: barValue }),\n              ],\n            ),\n            this.value,\n          ),\n        ]\n      },\n    })\n    render(h(component), root)\n\n    await nextTick()\n\n    const input = root.querySelector('select')\n    const [foo, bar] = root.querySelectorAll('option')\n    const data = root._vnode.component.data\n\n    foo.selected = true\n    triggerEvent('change', input)\n    await nextTick()\n    expect(data.value).toMatchObject([fooValue])\n\n    foo.selected = false\n    bar.selected = true\n    triggerEvent('change', input)\n    await nextTick()\n    expect(data.value).toMatchObject([barValue])\n\n    foo.selected = true\n    bar.selected = true\n    triggerEvent('change', input)\n    await nextTick()\n    expect(data.value).toMatchObject([fooValue, barValue])\n\n    // reset\n    foo.selected = false\n    bar.selected = false\n    triggerEvent('change', input)\n    await nextTick()\n    expect(data.value).toMatchObject([])\n\n    data.value = [fooValue, barValue]\n    await nextTick()\n    expect(foo.selected).toEqual(true)\n    expect(bar.selected).toEqual(true)\n\n    // reset\n    foo.selected = false\n    bar.selected = false\n    triggerEvent('change', input)\n    await nextTick()\n    expect(data.value).toMatchObject([])\n\n    data.value = [{ foo: 1 }, { bar: 1 }]\n    await nextTick()\n    // looseEqual\n    expect(foo.selected).toEqual(true)\n    expect(bar.selected).toEqual(true)\n  })\n\n  it('multiple select (model is Set)', async () => {\n    const component = defineComponent({\n      data() {\n        return { value: new Set() }\n      },\n      render() {\n        return [\n          withVModel(\n            h(\n              'select',\n              {\n                value: null,\n                multiple: true,\n                'onUpdate:modelValue': setValue.bind(this),\n              },\n              [h('option', { value: 'foo' }), h('option', { value: 'bar' })],\n            ),\n            this.value,\n          ),\n        ]\n      },\n    })\n    render(h(component), root)\n\n    const input = root.querySelector('select')\n    const foo = root.querySelector('option[value=foo]')\n    const bar = root.querySelector('option[value=bar]')\n    const data = root._vnode.component.data\n\n    foo.selected = true\n    triggerEvent('change', input)\n    await nextTick()\n    expect(data.value).toBeInstanceOf(Set)\n    expect(data.value).toMatchObject(new Set(['foo']))\n\n    foo.selected = false\n    bar.selected = true\n    triggerEvent('change', input)\n    await nextTick()\n    expect(data.value).toBeInstanceOf(Set)\n    expect(data.value).toMatchObject(new Set(['bar']))\n\n    foo.selected = true\n    bar.selected = true\n    triggerEvent('change', input)\n    await nextTick()\n    expect(data.value).toBeInstanceOf(Set)\n    expect(data.value).toMatchObject(new Set(['foo', 'bar']))\n\n    foo.selected = false\n    bar.selected = false\n    data.value = new Set(['foo'])\n    await nextTick()\n    expect(input.value).toEqual('foo')\n    expect(foo.selected).toEqual(true)\n    expect(bar.selected).toEqual(false)\n\n    foo.selected = false\n    bar.selected = false\n    data.value = new Set(['foo', 'bar'])\n    await nextTick()\n    expect(foo.selected).toEqual(true)\n    expect(bar.selected).toEqual(true)\n  })\n\n  it('multiple select (model is Set, option value is object)', async () => {\n    const fooValue = { foo: 1 }\n    const barValue = { bar: 1 }\n\n    const component = defineComponent({\n      data() {\n        return { value: new Set() }\n      },\n      render() {\n        return [\n          withVModel(\n            h(\n              'select',\n              {\n                value: null,\n                multiple: true,\n                'onUpdate:modelValue': setValue.bind(this),\n              },\n              [\n                h('option', { value: fooValue }),\n                h('option', { value: barValue }),\n              ],\n            ),\n            this.value,\n          ),\n        ]\n      },\n    })\n    render(h(component), root)\n\n    await nextTick()\n\n    const input = root.querySelector('select')\n    const [foo, bar] = root.querySelectorAll('option')\n    const data = root._vnode.component.data\n\n    foo.selected = true\n    triggerEvent('change', input)\n    await nextTick()\n    expect(data.value).toMatchObject(new Set([fooValue]))\n\n    foo.selected = false\n    bar.selected = true\n    triggerEvent('change', input)\n    await nextTick()\n    expect(data.value).toMatchObject(new Set([barValue]))\n\n    foo.selected = true\n    bar.selected = true\n    triggerEvent('change', input)\n    await nextTick()\n    expect(data.value).toMatchObject(new Set([fooValue, barValue]))\n\n    foo.selected = false\n    bar.selected = false\n    data.value = new Set([fooValue, barValue])\n    await nextTick()\n    expect(foo.selected).toEqual(true)\n    expect(bar.selected).toEqual(true)\n\n    foo.selected = false\n    bar.selected = false\n    data.value = new Set([{ foo: 1 }, { bar: 1 }])\n    await nextTick()\n    // without looseEqual, here is different from Array\n    expect(foo.selected).toEqual(false)\n    expect(bar.selected).toEqual(false)\n  })\n\n  it('should work with composition session', async () => {\n    const component = defineComponent({\n      data() {\n        return { value: '' }\n      },\n      render() {\n        return [\n          withVModel(\n            h('input', {\n              'onUpdate:modelValue': setValue.bind(this),\n            }),\n            this.value,\n          ),\n        ]\n      },\n    })\n    render(h(component), root)\n\n    const input = root.querySelector('input')!\n    const data = root._vnode.component.data\n    expect(input.value).toEqual('')\n\n    //developer.mozilla.org/en-US/docs/Web/API/Element/compositionstart_event\n    //compositionstart event could be fired after a user starts entering a Chinese character using a Pinyin IME\n    input.value = '使用拼音'\n    triggerEvent('compositionstart', input)\n    await nextTick()\n    expect(data.value).toEqual('')\n\n    // input event has no effect during composition session\n    input.value = '使用拼音输入'\n    triggerEvent('input', input)\n    await nextTick()\n    expect(data.value).toEqual('')\n\n    // After compositionend event being fired, an input event will be automatically trigger\n    triggerEvent('compositionend', input)\n    await nextTick()\n    expect(data.value).toEqual('使用拼音输入')\n  })\n\n  it('multiple select (model is number, option value is string)', async () => {\n    const component = defineComponent({\n      data() {\n        return {\n          value: [1, 2],\n        }\n      },\n      render() {\n        return [\n          withVModel(\n            h(\n              'select',\n              {\n                multiple: true,\n                'onUpdate:modelValue': setValue.bind(this),\n              },\n              [h('option', { value: '1' }), h('option', { value: '2' })],\n            ),\n            this.value,\n          ),\n        ]\n      },\n    })\n    render(h(component), root)\n\n    await nextTick()\n    const [foo, bar] = root.querySelectorAll('option')\n\n    expect(foo.selected).toEqual(true)\n    expect(bar.selected).toEqual(true)\n  })\n\n  // #10503\n  test('equal value with a leading 0 should trigger update.', async () => {\n    const setNum = function (this: any, value: any) {\n      this.num = value\n    }\n    const component = defineComponent({\n      data() {\n        return { num: 0 }\n      },\n      render() {\n        return [\n          withVModel(\n            h('input', {\n              id: 'input_num1',\n              type: 'number',\n              'onUpdate:modelValue': setNum.bind(this),\n            }),\n            this.num,\n          ),\n        ]\n      },\n    })\n\n    render(h(component), root)\n    const data = root._vnode.component.data\n\n    const inputNum1 = root.querySelector('#input_num1')!\n    expect(inputNum1.value).toBe('0')\n\n    inputNum1.value = '01'\n    triggerEvent('input', inputNum1)\n    await nextTick()\n    expect(data.num).toBe(1)\n\n    expect(inputNum1.value).toBe('1')\n  })\n\n  it(`should support mutating an array or set value for a checkbox`, async () => {\n    const component = defineComponent({\n      data() {\n        return { value: [] }\n      },\n      render() {\n        return [\n          withDirectives(\n            h('input', {\n              type: 'checkbox',\n              class: 'foo',\n              value: 'foo',\n              'onUpdate:modelValue': setValue.bind(this),\n            }),\n            [[vModelCheckbox, this.value]],\n          ),\n        ]\n      },\n    })\n    render(h(component), root)\n\n    const foo = root.querySelector('.foo')\n    const data = root._vnode.component.data\n\n    expect(foo.checked).toEqual(false)\n\n    data.value.push('foo')\n    await nextTick()\n    expect(foo.checked).toEqual(true)\n\n    data.value[0] = 'bar'\n    await nextTick()\n    expect(foo.checked).toEqual(false)\n\n    data.value = new Set()\n    await nextTick()\n    expect(foo.checked).toEqual(false)\n\n    data.value.add('foo')\n    await nextTick()\n    expect(foo.checked).toEqual(true)\n\n    data.value.delete('foo')\n    await nextTick()\n    expect(foo.checked).toEqual(false)\n  })\n})\n"
  },
  {
    "path": "packages/runtime-dom/__tests__/directives/vOn.spec.ts",
    "content": "import { patchEvent } from '../../src/modules/events'\nimport { withKeys, withModifiers } from '@vue/runtime-dom'\n\nfunction triggerEvent(\n  target: Element,\n  event: string,\n  process?: (e: any) => any,\n) {\n  const e = new Event(event, {\n    bubbles: true,\n    cancelable: true,\n  })\n  if (event === 'click') {\n    ;(e as any).button = 0\n  }\n  if (process) process(e)\n  target.dispatchEvent(e)\n  return e\n}\n\ndescribe('runtime-dom: v-on directive', () => {\n  test('it should support \"stop\" and \"prevent\"', () => {\n    const parent = document.createElement('div')\n    const child = document.createElement('input')\n    parent.appendChild(child)\n    const childNextValue = withModifiers(vi.fn(), ['prevent', 'stop'])\n    patchEvent(child, 'onClick', null, childNextValue, null)\n    const parentNextValue = vi.fn()\n    patchEvent(parent, 'onClick', null, parentNextValue, null)\n    expect(triggerEvent(child, 'click').defaultPrevented).toBe(true)\n    expect(parentNextValue).not.toBeCalled()\n  })\n\n  test('it should support \"self\"', () => {\n    const parent = document.createElement('div')\n    const child = document.createElement('input')\n    parent.appendChild(child)\n    const fn = vi.fn()\n    const handler = withModifiers(fn, ['self'])\n    patchEvent(parent, 'onClick', null, handler, null)\n    triggerEvent(child, 'click')\n    expect(fn).not.toBeCalled()\n  })\n\n  test('it should support key modifiers and system modifiers', () => {\n    const keyNames = ['ctrl', 'shift', 'meta', 'alt'] as const\n\n    keyNames.forEach(keyName => {\n      const el = document.createElement('div')\n      const fn = vi.fn()\n      // <div @keyup[keyName].esc=\"test\"/>\n      const nextValue = withKeys(withModifiers(fn, [keyName]), [\n        'esc',\n        'arrow-left',\n      ])\n      patchEvent(el, 'onKeyup', null, nextValue, null)\n\n      triggerEvent(el, 'keyup', e => (e.key = 'a'))\n      expect(fn).not.toBeCalled()\n\n      triggerEvent(el, 'keyup', e => {\n        e[`${keyName}Key`] = false\n        e.key = 'esc'\n      })\n      expect(fn).not.toBeCalled()\n\n      triggerEvent(el, 'keyup', e => {\n        e[`${keyName}Key`] = true\n        e.key = 'Escape'\n      })\n      expect(fn).toBeCalledTimes(1)\n\n      triggerEvent(el, 'keyup', e => {\n        e[`${keyName}Key`] = true\n        e.key = 'ArrowLeft'\n      })\n      expect(fn).toBeCalledTimes(2)\n    })\n  })\n\n  test('it should support \"exact\" modifier', () => {\n    const el = document.createElement('div')\n    // Case 1: <div @keyup.exact=\"test\"/>\n    const fn1 = vi.fn()\n    const next1 = withModifiers(fn1, ['exact'])\n    patchEvent(el, 'onKeyup', null, next1, null)\n    triggerEvent(el, 'keyup')\n    expect(fn1.mock.calls.length).toBe(1)\n    triggerEvent(el, 'keyup', e => (e.ctrlKey = true))\n    expect(fn1.mock.calls.length).toBe(1)\n    // Case 2: <div @keyup.ctrl.a.exact=\"test\"/>\n    const fn2 = vi.fn()\n    const next2 = withKeys(withModifiers(fn2, ['ctrl', 'exact']), ['a'])\n    patchEvent(el, 'onKeyup', null, next2, null)\n    triggerEvent(el, 'keyup', e => (e.key = 'a'))\n    expect(fn2).not.toBeCalled()\n    triggerEvent(el, 'keyup', e => {\n      e.key = 'a'\n      e.ctrlKey = true\n    })\n    expect(fn2.mock.calls.length).toBe(1)\n    triggerEvent(el, 'keyup', e => {\n      // should not trigger if has other system modifiers\n      e.key = 'a'\n      e.ctrlKey = true\n      e.altKey = true\n    })\n    expect(fn2.mock.calls.length).toBe(1)\n  })\n\n  it('should support mouse modifiers', () => {\n    const buttons = ['left', 'middle', 'right'] as const\n    const buttonCodes = { left: 0, middle: 1, right: 2 }\n    buttons.forEach(button => {\n      const el = document.createElement('div')\n      const fn = vi.fn()\n      const handler = withModifiers(fn, [button])\n      patchEvent(el, 'onMousedown', null, handler, null)\n      buttons\n        .filter(b => b !== button)\n        .forEach(button => {\n          triggerEvent(el, 'mousedown', e => (e.button = buttonCodes[button]))\n        })\n      expect(fn).not.toBeCalled()\n      triggerEvent(el, 'mousedown', e => (e.button = buttonCodes[button]))\n      expect(fn).toBeCalled()\n    })\n  })\n\n  it('should handle multiple arguments when using modifiers', () => {\n    const el = document.createElement('div')\n    const fn = vi.fn()\n    const handler = withModifiers(fn, ['ctrl'])\n    const event = triggerEvent(el, 'click', e => (e.ctrlKey = true))\n    handler(event, 'value', true)\n    expect(fn).toBeCalledWith(event, 'value', true)\n  })\n\n  it('withKeys cache wrapped listener separately for different modifiers', () => {\n    const el1 = document.createElement('button')\n    const el2 = document.createElement('button')\n    const fn = vi.fn()\n    const handler1 = withKeys(fn, ['a'])\n    const handler2 = withKeys(fn, ['b'])\n    expect(handler1 === handler2).toBe(false)\n    patchEvent(el1, 'onKeyup', null, handler1, null)\n    patchEvent(el2, 'onKeyup', null, handler2, null)\n    triggerEvent(el1, 'keyup', e => (e.key = 'a'))\n    triggerEvent(el2, 'keyup', e => (e.key = 'b'))\n    expect(fn).toBeCalledTimes(2)\n  })\n\n  it('withModifiers cache wrapped listener separately for different modifiers', () => {\n    const el1 = document.createElement('button')\n    const el2 = document.createElement('button')\n    const fn = vi.fn()\n    const handler1 = withModifiers(fn, ['ctrl'])\n    const handler2 = withModifiers(fn, ['shift'])\n    expect(handler1 === handler2).toBe(false)\n    patchEvent(el1, 'onClick', null, handler1, null)\n    patchEvent(el2, 'onClick', null, handler2, null)\n    triggerEvent(el1, 'click', e => (e.ctrlKey = true))\n    triggerEvent(el2, 'click', e => (e.shiftKey = true))\n    expect(fn).toBeCalledTimes(2)\n  })\n\n  it('withModifiers should handle null or undefined handler', () => {\n    expect(() => {\n      const handler1 = withModifiers(null as any, ['ctrl'])\n      expect(handler1).toBe(null)\n    }).not.toThrow()\n\n    expect(() => {\n      const handler2 = withModifiers(undefined as any, ['shift'])\n      expect(handler2).toBe(undefined)\n    }).not.toThrow()\n  })\n})\n"
  },
  {
    "path": "packages/runtime-dom/__tests__/directives/vShow.spec.ts",
    "content": "import {\n  type VNode,\n  defineComponent,\n  h,\n  nextTick,\n  ref,\n  watch,\n  withDirectives,\n} from '@vue/runtime-core'\nimport { Transition, render, vShow } from '@vue/runtime-dom'\n\nconst withVShow = (node: VNode, exp: any) =>\n  withDirectives(node, [[vShow, exp]])\n\nlet root: any\n\nbeforeEach(() => {\n  root = document.createElement('div')\n})\n\ndescribe('runtime-dom: v-show directive', () => {\n  test('should check show value is truthy', async () => {\n    const component = defineComponent({\n      data() {\n        return { value: true }\n      },\n      render() {\n        return [withVShow(h('div'), this.value)]\n      },\n    })\n    render(h(component), root)\n\n    const $div = root.children[0]\n\n    expect($div.style.display).toEqual('')\n  })\n\n  test('should check show value is falsy', async () => {\n    const component = defineComponent({\n      data() {\n        return { value: false }\n      },\n      render() {\n        return [withVShow(h('div'), this.value)]\n      },\n    })\n    render(h(component), root)\n\n    const $div = root.children[0]\n\n    expect($div.style.display).toEqual('none')\n  })\n\n  it('should update show value changed', async () => {\n    const component = defineComponent({\n      data() {\n        return { value: true }\n      },\n      render() {\n        return [withVShow(h('div'), this.value)]\n      },\n    })\n    render(h(component), root)\n\n    const $div = root.children[0]\n    const data = root._vnode.component.data\n\n    expect($div.style.display).toEqual('')\n\n    data.value = false\n    await nextTick()\n    expect($div.style.display).toEqual('none')\n\n    data.value = {}\n    await nextTick()\n    expect($div.style.display).toEqual('')\n\n    data.value = 0\n    await nextTick()\n    expect($div.style.display).toEqual('none')\n\n    data.value = []\n    await nextTick()\n    expect($div.style.display).toEqual('')\n\n    data.value = null\n    await nextTick()\n    expect($div.style.display).toEqual('none')\n\n    data.value = '0'\n    await nextTick()\n    expect($div.style.display).toEqual('')\n\n    data.value = undefined\n    await nextTick()\n    expect($div.style.display).toEqual('none')\n\n    data.value = 1\n    await nextTick()\n    expect($div.style.display).toEqual('')\n  })\n\n  test('should respect display value in style attribute', async () => {\n    const component = defineComponent({\n      data() {\n        return { value: true }\n      },\n      render() {\n        return [\n          withVShow(h('div', { style: { display: 'block' } }), this.value),\n        ]\n      },\n    })\n    render(h(component), root)\n\n    const $div = root.children[0]\n    const data = root._vnode.component.data\n\n    expect($div.style.display).toEqual('block')\n\n    data.value = false\n    await nextTick()\n    expect($div.style.display).toEqual('none')\n\n    data.value = true\n    await nextTick()\n    expect($div.style.display).toEqual('block')\n  })\n\n  // #2583\n  test('the value of `display` set by v-show should not be overwritten by the style attribute when updated', async () => {\n    const style = ref('width: 100px')\n    const display = ref(false)\n    const component = defineComponent({\n      render() {\n        return withVShow(h('div', { style: style.value }), display.value)\n      },\n    })\n    render(h(component), root)\n\n    const $div = root.children[0]\n\n    expect($div.style.display).toEqual('none')\n\n    style.value = 'width: 50px'\n    await nextTick()\n    expect($div.style.display).toEqual('none')\n\n    display.value = true\n    await nextTick()\n    expect($div.style.display).toEqual('')\n  })\n\n  test('the value of `display` set by v-show should not be overwritten by the style attribute when updated (object value)', async () => {\n    const style = ref({\n      display: 'block',\n      width: '100px',\n    })\n    const display = ref(false)\n    const component = defineComponent({\n      render() {\n        return withVShow(h('div', { style: style.value }), display.value)\n      },\n    })\n    render(h(component), root)\n\n    const $div = root.children[0]\n\n    expect($div.style.display).toEqual('none')\n\n    style.value.width = '50px'\n    await nextTick()\n    expect($div.style.display).toEqual('none')\n\n    display.value = true\n    await nextTick()\n    expect($div.style.display).toEqual('block')\n  })\n\n  // #2583, #2757\n  test('the value of `display` set by v-show should not be overwritten by the style attribute when updated (with Transition)', async () => {\n    const style = ref('width: 100px')\n    const display = ref(false)\n    const component = defineComponent({\n      setup() {\n        const innerValue = ref(false)\n        watch(display, val => {\n          innerValue.value = val\n        })\n        return () => {\n          return h(Transition, () =>\n            withVShow(\n              h('div', { style: style.value }, innerValue.value),\n              display.value,\n            ),\n          )\n        }\n      },\n    })\n    render(h(component), root)\n\n    const $div = root.children[0]\n\n    expect($div.style.display).toEqual('none')\n\n    style.value = 'width: 50px'\n    await nextTick()\n    expect($div.style.display).toEqual('none')\n\n    display.value = true\n    await nextTick()\n    expect($div.style.display).toEqual('')\n  })\n\n  // #10151\n  test('should respect the display value when v-show value is true', async () => {\n    const isVisible = ref(false)\n    const useDisplayStyle = ref(true)\n    const compStyle = ref({\n      display: 'none',\n    })\n    const withoutDisplayStyle = {\n      margin: '10px',\n    }\n\n    const Component = {\n      setup() {\n        return () => {\n          return withVShow(\n            h('div', {\n              style: useDisplayStyle.value\n                ? compStyle.value\n                : withoutDisplayStyle,\n            }),\n            isVisible.value,\n          )\n        }\n      },\n    }\n    render(h(Component), root)\n\n    const $div = root.children[0]\n\n    expect($div.style.display).toEqual('none')\n\n    isVisible.value = true\n    await nextTick()\n    expect($div.style.display).toEqual('none')\n\n    compStyle.value.display = 'block'\n    await nextTick()\n    expect($div.style.display).toEqual('block')\n\n    compStyle.value.display = 'inline-block'\n    await nextTick()\n    expect($div.style.display).toEqual('inline-block')\n\n    isVisible.value = false\n    await nextTick()\n    expect($div.style.display).toEqual('none')\n\n    isVisible.value = true\n    await nextTick()\n    expect($div.style.display).toEqual('inline-block')\n\n    useDisplayStyle.value = false\n    await nextTick()\n    expect($div.style.display).toEqual('')\n    expect(getComputedStyle($div).display).toEqual('block')\n\n    isVisible.value = false\n    await nextTick()\n    expect($div.style.display).toEqual('none')\n\n    isVisible.value = true\n    await nextTick()\n    expect($div.style.display).toEqual('')\n  })\n\n  // #10294\n  test('should record display by vShowOldKey only when display exists in style', async () => {\n    const isVisible = ref(false)\n    const style = ref({\n      margin: '10px',\n    })\n\n    const Component = {\n      setup() {\n        return () => {\n          return withVShow(\n            h('div', {\n              style: style.value,\n            }),\n            isVisible.value,\n          )\n        }\n      },\n    }\n    render(h(Component), root)\n    const $div = root.children[0]\n\n    expect($div.style.display).toEqual('none')\n\n    style.value.margin = '20px'\n    await nextTick()\n    expect($div.style.display).toEqual('none')\n\n    isVisible.value = true\n    await nextTick()\n    expect($div.style.display).toEqual('')\n  })\n})\n"
  },
  {
    "path": "packages/runtime-dom/__tests__/helpers/useCssModule.spec.ts",
    "content": "import { h, nodeOps, render } from '@vue/runtime-test'\nimport { useCssModule } from '../../src/helpers/useCssModule'\n\ndescribe('useCssModule', () => {\n  function mountWithModule(modules: any, name?: string) {\n    let res\n    render(\n      h({\n        render() {},\n        __cssModules: modules,\n        setup() {\n          res = useCssModule(name)\n        },\n      }),\n      nodeOps.createElement('div'),\n    )\n    return res\n  }\n\n  test('basic usage', () => {\n    const modules = {\n      $style: {\n        red: 'red',\n      },\n    }\n    expect(mountWithModule(modules)).toMatchObject(modules.$style)\n  })\n\n  test('basic usage', () => {\n    const modules = {\n      foo: {\n        red: 'red',\n      },\n    }\n    expect(mountWithModule(modules, 'foo')).toMatchObject(modules.foo)\n  })\n\n  test('warn out of setup usage', () => {\n    useCssModule()\n    expect('must be called inside setup').toHaveBeenWarned()\n  })\n\n  test('warn missing injection', () => {\n    mountWithModule(undefined)\n    expect('instance does not have CSS modules').toHaveBeenWarned()\n  })\n\n  test('warn missing injection', () => {\n    mountWithModule({ $style: { red: 'red' } }, 'foo')\n    expect('instance does not have CSS module named \"foo\"').toHaveBeenWarned()\n  })\n})\n"
  },
  {
    "path": "packages/runtime-dom/__tests__/helpers/useCssVars.spec.ts",
    "content": "import {\n  type ComponentOptions,\n  type FunctionalComponent,\n  Suspense,\n  Teleport,\n  createStaticVNode,\n  defineCustomElement,\n  h,\n  nextTick,\n  onMounted,\n  reactive,\n  ref,\n  render,\n  useCssVars,\n} from '@vue/runtime-dom'\n\ndescribe('useCssVars', () => {\n  async function assertCssVars(getApp: (state: any) => ComponentOptions) {\n    const state = reactive({ color: 'red' })\n    const App = getApp(state)\n    const root = document.createElement('div')\n\n    render(h(App), root)\n    await nextTick()\n    for (const c of [].slice.call(root.children as any)) {\n      expect((c as HTMLElement).style.getPropertyValue(`--color`)).toBe(`red`)\n    }\n\n    state.color = 'green'\n    await nextTick()\n    for (const c of [].slice.call(root.children as any)) {\n      expect((c as HTMLElement).style.getPropertyValue(`--color`)).toBe('green')\n    }\n  }\n\n  test('basic', async () => {\n    await assertCssVars(state => ({\n      setup() {\n        // test receiving render context\n        useCssVars((ctx: any) => ({\n          color: ctx.color,\n        }))\n        return state\n      },\n      render() {\n        return h('div')\n      },\n    }))\n  })\n\n  test('on fragment root', async () => {\n    await assertCssVars(state => ({\n      setup() {\n        useCssVars(() => state)\n        return () => [h('div'), h('div')]\n      },\n    }))\n  })\n\n  test('on HOCs', async () => {\n    const Child = () => [h('div'), h('div')]\n\n    await assertCssVars(state => ({\n      setup() {\n        useCssVars(() => state)\n        return () => h(Child)\n      },\n    }))\n  })\n\n  test('on suspense root', async () => {\n    const state = reactive({ color: 'red' })\n    const root = document.createElement('div')\n\n    let resolveAsync: any\n    let asyncPromise: any\n\n    const AsyncComp = {\n      setup() {\n        asyncPromise = new Promise(r => {\n          resolveAsync = () => {\n            r(() => h('p', 'default'))\n          }\n        })\n        return asyncPromise\n      },\n    }\n\n    const App = {\n      setup() {\n        useCssVars(() => state)\n        return () =>\n          h(Suspense, null, {\n            default: h(AsyncComp),\n            fallback: h('div', 'fallback'),\n          })\n      },\n    }\n\n    render(h(App), root)\n    await nextTick()\n    // css vars use with fallback tree\n    for (const c of [].slice.call(root.children as any)) {\n      expect((c as HTMLElement).style.getPropertyValue(`--color`)).toBe(`red`)\n    }\n    // AsyncComp resolve\n    resolveAsync()\n    await asyncPromise.then(() => {})\n    // Suspense effects flush\n    await nextTick()\n    // css vars use with default tree\n    for (const c of [].slice.call(root.children as any)) {\n      expect((c as HTMLElement).style.getPropertyValue(`--color`)).toBe(`red`)\n    }\n\n    state.color = 'green'\n    await nextTick()\n    for (const c of [].slice.call(root.children as any)) {\n      expect((c as HTMLElement).style.getPropertyValue(`--color`)).toBe('green')\n    }\n  })\n\n  test('with v-if & async component & suspense', async () => {\n    const state = reactive({ color: 'red' })\n    const root = document.createElement('div')\n    const show = ref(false)\n    let resolveAsync: any\n    let asyncPromise: any\n\n    const AsyncComp = {\n      setup() {\n        useCssVars(() => state)\n        asyncPromise = new Promise(r => {\n          resolveAsync = () => {\n            r(() => h('p', 'default'))\n          }\n        })\n        return asyncPromise\n      },\n    }\n\n    const App = {\n      setup() {\n        return () =>\n          h(Suspense, null, {\n            default: h('div', {}, show.value ? h(AsyncComp) : h('p')),\n          })\n      },\n    }\n\n    render(h(App), root)\n    await nextTick()\n    // AsyncComp resolve\n    show.value = true\n    await nextTick()\n    resolveAsync()\n    await asyncPromise.then(() => {})\n    // Suspense effects flush\n    await nextTick()\n    // css vars use with default tree\n    for (const c of [].slice.call(root.children as any)) {\n      expect(\n        ((c as any).children[0] as HTMLElement).style.getPropertyValue(\n          `--color`,\n        ),\n      ).toBe(`red`)\n    }\n\n    state.color = 'green'\n    await nextTick()\n    for (const c of [].slice.call(root.children as any)) {\n      expect(\n        ((c as any).children[0] as HTMLElement).style.getPropertyValue(\n          `--color`,\n        ),\n      ).toBe('green')\n    }\n  })\n\n  test('with subTree changed', async () => {\n    const state = reactive({ color: 'red' })\n    const value = ref(true)\n    const root = document.createElement('div')\n\n    const App = {\n      setup() {\n        useCssVars(() => state)\n        return () => (value.value ? [h('div')] : [h('div'), h('div')])\n      },\n    }\n\n    render(h(App), root)\n    await nextTick()\n    // css vars use with fallback tree\n    for (const c of [].slice.call(root.children as any)) {\n      expect((c as HTMLElement).style.getPropertyValue(`--color`)).toBe(`red`)\n    }\n\n    value.value = false\n    await nextTick()\n    for (const c of [].slice.call(root.children as any)) {\n      expect((c as HTMLElement).style.getPropertyValue(`--color`)).toBe('red')\n    }\n  })\n\n  // #3894\n  test('with subTree change inside HOC', async () => {\n    const state = reactive({ color: 'red' })\n    const value = ref(true)\n    const root = document.createElement('div')\n\n    const Child: FunctionalComponent = (_, { slots }) => slots.default!()\n\n    const App = {\n      setup() {\n        useCssVars(() => state)\n        return () =>\n          h(Child, null, () =>\n            value.value ? [h('div')] : [h('div'), h('div')],\n          )\n      },\n    }\n\n    render(h(App), root)\n    await nextTick()\n    // css vars use with fallback tree\n    for (const c of [].slice.call(root.children as any)) {\n      expect((c as HTMLElement).style.getPropertyValue(`--color`)).toBe(`red`)\n    }\n\n    value.value = false\n    await nextTick()\n    for (const c of [].slice.call(root.children as any)) {\n      expect((c as HTMLElement).style.getPropertyValue(`--color`)).toBe('red')\n    }\n  })\n\n  test('with createStaticVNode', async () => {\n    const state = reactive({ color: 'red' })\n    const root = document.createElement('div')\n\n    const App = {\n      setup() {\n        useCssVars(() => state)\n        return () => [\n          h('div'),\n          createStaticVNode('<div>1</div><div><span>2</span></div>', 2),\n          h('div'),\n        ]\n      },\n    }\n\n    render(h(App), root)\n    await nextTick()\n    for (const c of [].slice.call(root.children as any)) {\n      expect((c as HTMLElement).style.getPropertyValue(`--color`)).toBe('red')\n    }\n  })\n\n  test('with teleport', async () => {\n    document.body.innerHTML = ''\n    const state = reactive({ color: 'red' })\n    const root = document.createElement('div')\n    const target = document.body\n\n    const App = {\n      setup() {\n        useCssVars(() => state)\n        return () => [h(Teleport, { to: target }, [h('div')])]\n      },\n    }\n\n    render(h(App), root)\n    await nextTick()\n    for (const c of [].slice.call(target.children as any)) {\n      expect((c as HTMLElement).style.getPropertyValue(`--color`)).toBe('red')\n    }\n  })\n\n  test('with teleport in child slot', async () => {\n    document.body.innerHTML = ''\n    const state = reactive({ color: 'red' })\n    const root = document.createElement('div')\n    const target = document.body\n\n    const Child: FunctionalComponent = (_, { slots }) => {\n      return h('div', slots.default && slots.default())\n    }\n\n    const App = {\n      setup() {\n        useCssVars(() => state)\n        return () => h(Child, () => [h(Teleport, { to: target }, [h('div')])])\n      },\n    }\n\n    render(h(App), root)\n    await nextTick()\n    for (const c of [].slice.call(target.children as any)) {\n      expect((c as HTMLElement).style.getPropertyValue(`--color`)).toBe('red')\n    }\n  })\n\n  test('with teleport(change subTree)', async () => {\n    document.body.innerHTML = ''\n    const state = reactive({ color: 'red' })\n    const root = document.createElement('div')\n    const target = document.body\n    const toggle = ref(false)\n\n    const App = {\n      setup() {\n        useCssVars(() => state)\n        return () => [\n          h(Teleport, { to: target }, [\n            h('div'),\n            toggle.value ? h('div') : null,\n          ]),\n        ]\n      },\n    }\n\n    render(h(App), root)\n    await nextTick()\n    expect(target.children.length).toBe(1)\n    for (const c of [].slice.call(target.children as any)) {\n      expect((c as HTMLElement).style.getPropertyValue(`--color`)).toBe('red')\n    }\n\n    toggle.value = true\n    await nextTick()\n    expect(target.children.length).toBe(2)\n    for (const c of [].slice.call(target.children as any)) {\n      expect((c as HTMLElement).style.getPropertyValue(`--color`)).toBe('red')\n    }\n  })\n\n  test('with teleport(disabled)', async () => {\n    document.body.innerHTML = ''\n    const state = reactive({ color: 'red' })\n    const root = document.createElement('div')\n    const target = document.body\n\n    const App = {\n      setup() {\n        useCssVars(() => state)\n        return () => [h(Teleport, { to: target, disabled: true }, [h('div')])]\n      },\n    }\n\n    expect(() => render(h(App), root)).not.toThrow(TypeError)\n    await nextTick()\n    expect(target.children.length).toBe(0)\n    expect(root.children[0].outerHTML.includes('data-v-owner')).toBe(true)\n  })\n\n  test('with string style', async () => {\n    document.body.innerHTML = ''\n    const state = reactive({ color: 'red' })\n    const root = document.createElement('div')\n    const disabled = ref(false)\n\n    const App = {\n      setup() {\n        useCssVars(() => state)\n        return () => [\n          h(\n            'div',\n            { style: disabled.value ? 'pointer-events: none' : undefined },\n            'foo',\n          ),\n        ]\n      },\n    }\n    render(h(App), root)\n    await nextTick()\n    for (const c of [].slice.call(root.children as any)) {\n      expect((c as HTMLElement).style.getPropertyValue(`--color`)).toBe('red')\n    }\n    disabled.value = true\n    await nextTick()\n\n    for (const c of [].slice.call(root.children as any)) {\n      expect((c as HTMLElement).style.getPropertyValue(`--color`)).toBe('red')\n    }\n  })\n\n  test('with delay mount child', async () => {\n    const state = reactive({ color: 'red' })\n    const value = ref(false)\n    const root = document.createElement('div')\n\n    const Child = {\n      setup() {\n        onMounted(() => {\n          const childEl = root.children[0]\n          expect(getComputedStyle(childEl!).getPropertyValue(`--color`)).toBe(\n            `red`,\n          )\n        })\n        return () => h('div', { id: 'childId' })\n      },\n    }\n    const App = {\n      setup() {\n        useCssVars(() => state)\n        return () => (value.value ? h(Child) : [h('span')])\n      },\n    }\n\n    render(h(App), root)\n    await nextTick()\n    // css vars use with fallback tree\n    for (const c of [].slice.call(root.children as any)) {\n      expect((c as HTMLElement).style.getPropertyValue(`--color`)).toBe(`red`)\n    }\n\n    // mount child\n    value.value = true\n    await nextTick()\n    for (const c of [].slice.call(root.children as any)) {\n      expect((c as HTMLElement).style.getPropertyValue(`--color`)).toBe(`red`)\n    }\n  })\n\n  // #8826\n  test('with custom element', async () => {\n    const state = reactive({ color: 'red' })\n    const container = document.createElement('div')\n    const App = defineCustomElement({\n      styles: [`div { color: red; }`],\n      setup() {\n        useCssVars(() => state)\n        return () => {\n          return h('div', 'hello')\n        }\n      },\n    })\n    customElements.define('css-vars-ce', App)\n    container.innerHTML = `<css-vars-ce></css-vars-ce>`\n    document.body.appendChild(container)\n    await nextTick()\n    expect(container.innerHTML).toBe(\n      `<css-vars-ce style=\"--color: red;\"></css-vars-ce>`,\n    )\n  })\n\n  test('should set vars before child component onMount hook', () => {\n    const state = reactive({ color: 'red' })\n    const root = document.createElement('div')\n    let colorInOnMount\n\n    const App = {\n      setup() {\n        useCssVars(() => state)\n        onMounted(() => {\n          colorInOnMount = (\n            root.children[0] as HTMLElement\n          ).style.getPropertyValue(`--color`)\n        })\n        return () => h('div')\n      },\n    }\n\n    render(h(App), root)\n    expect(colorInOnMount).toBe(`red`)\n  })\n\n  test('should set vars as `initial` for nullish values', async () => {\n    // `getPropertyValue` cannot reflect the real value for white spaces and JSDOM also\n    // doesn't 100% reflect the real behavior of browsers, so we only keep the test for\n    // `initial` value here.\n    // The value normalization is tested in packages/shared/__tests__/cssVars.spec.ts.\n    const state = reactive<Record<string, unknown>>({\n      foo: undefined,\n      bar: null,\n    })\n    const root = document.createElement('div')\n    const App = {\n      setup() {\n        useCssVars(() => state)\n        return () => h('div')\n      },\n    }\n    render(h(App), root)\n    await nextTick()\n    const style = (root.children[0] as HTMLElement).style\n    expect(style.getPropertyValue('--foo')).toBe('initial')\n    expect(style.getPropertyValue('--bar')).toBe('initial')\n  })\n})\n"
  },
  {
    "path": "packages/runtime-dom/__tests__/nodeOps.spec.ts",
    "content": "import { defineComponent, h, nextTick, ref } from 'vue'\nimport { mathmlNS, nodeOps, svgNS } from '../src/nodeOps'\nimport { render } from '@vue/runtime-dom'\ndescribe('runtime-dom: node-ops', () => {\n  test(\"the <select>'s multiple attr should be set in createElement\", () => {\n    const el = nodeOps.createElement('select', undefined, undefined, {\n      multiple: '',\n    }) as HTMLSelectElement\n    const option1 = nodeOps.createElement('option') as HTMLOptionElement\n    const option2 = nodeOps.createElement('option') as HTMLOptionElement\n    option1.selected = true\n    option2.selected = true\n    nodeOps.insert(option1, el)\n    nodeOps.insert(option2, el)\n\n    expect(el.multiple).toBe(true)\n    expect(option1.selected).toBe(true)\n    expect(option2.selected).toBe(true)\n  })\n\n  test('create custom elements', () => {\n    const spyCreateElement = vi.spyOn(document, 'createElement')\n\n    nodeOps.createElement('custom-element')\n    expect(spyCreateElement).toHaveBeenLastCalledWith('custom-element')\n\n    nodeOps.createElement('custom-element', undefined, 'li')\n    expect(spyCreateElement).toHaveBeenLastCalledWith('custom-element', {\n      is: 'li',\n    })\n\n    spyCreateElement.mockClear()\n  })\n\n  describe('insertStaticContent', () => {\n    test('fresh insertion', () => {\n      const content = `<div>one</div><div>two</div>three`\n      const parent = document.createElement('div')\n      const nodes = nodeOps.insertStaticContent!(\n        content,\n        parent,\n        null,\n        undefined,\n      )\n      expect(parent.innerHTML).toBe(content)\n      expect(nodes[0]).toBe(parent.firstChild)\n      expect(nodes[1]).toBe(parent.lastChild)\n    })\n\n    test('fresh insertion with anchor', () => {\n      const content = `<div>one</div><div>two</div>three`\n      const existing = `<div>existing</div>`\n      const parent = document.createElement('div')\n      parent.innerHTML = existing\n      const anchor = parent.firstChild\n      const nodes = nodeOps.insertStaticContent!(\n        content,\n        parent,\n        anchor,\n        undefined,\n      )\n      expect(parent.innerHTML).toBe(content + existing)\n      expect(nodes[0]).toBe(parent.firstChild)\n      expect(nodes[1]).toBe(parent.childNodes[parent.childNodes.length - 2])\n    })\n\n    test('fresh insertion as svg', () => {\n      const content = `<text>hello</text><circle cx=\"100\" cy=\"100\" r=\"80\"></circle>`\n      const parent = document.createElementNS(svgNS, 'svg')\n      const [first, last] = nodeOps.insertStaticContent!(\n        content,\n        parent,\n        null,\n        'svg',\n      )\n      expect(parent.innerHTML).toBe(content)\n      expect(first).toBe(parent.firstChild)\n      expect(last).toBe(parent.lastChild)\n      expect((first as Element).namespaceURI).toMatch('svg')\n      expect((last as Element).namespaceURI).toMatch('svg')\n    })\n\n    test('fresh insertion as svg, with anchor', () => {\n      const content = `<text>hello</text><circle cx=\"100\" cy=\"100\" r=\"80\"></circle>`\n      const existing = `<path></path>`\n      const parent = document.createElementNS(svgNS, 'svg')\n      parent.innerHTML = existing\n      const anchor = parent.firstChild\n      const [first, last] = nodeOps.insertStaticContent!(\n        content,\n        parent,\n        anchor,\n        'svg',\n      )\n      expect(parent.innerHTML).toBe(content + existing)\n      expect(first).toBe(parent.firstChild)\n      expect(last).toBe(parent.childNodes[parent.childNodes.length - 2])\n      expect((first as Element).namespaceURI).toMatch('svg')\n      expect((last as Element).namespaceURI).toMatch('svg')\n    })\n\n    test('cached insertion', () => {\n      const content = `<div>one</div><div>two</div>three`\n      const existing = `<div>existing</div>`\n      const parent = document.createElement('div')\n      parent.innerHTML = existing\n      const anchor = parent.firstChild\n\n      const cached = document.createElement('div')\n      cached.innerHTML = content\n\n      const nodes = nodeOps.insertStaticContent!(\n        content,\n        parent,\n        anchor,\n        undefined,\n        cached.firstChild,\n        cached.lastChild,\n      )\n      expect(parent.innerHTML).toBe(content + existing)\n      expect(nodes[0]).toBe(parent.firstChild)\n      expect(nodes[1]).toBe(parent.childNodes[parent.childNodes.length - 2])\n    })\n\n    test('The math elements should keep their MathML namespace', async () => {\n      let root = document.createElement('div') as any\n\n      let countRef: any\n      const component = defineComponent({\n        data() {\n          return { value: 0 }\n        },\n        setup() {\n          const count = ref(0)\n          countRef = count\n          return {\n            count,\n          }\n        },\n        template: `\n          <div>\n            <math>\n              <mrow class=\"bar\" v-if=\"count % 2\">Bar</mrow>\n              <msup class=\"foo\" v-else>Foo</msup>\n            </math>\n          </div>\n        `,\n      })\n      render(h(component), root)\n      const foo = root.querySelector('.foo')\n      expect(foo.namespaceURI).toBe(mathmlNS)\n      countRef.value++\n      await nextTick()\n      const bar = root.querySelector('.bar')\n      expect(bar.namespaceURI).toBe(mathmlNS)\n    })\n  })\n})\n"
  },
  {
    "path": "packages/runtime-dom/__tests__/patchAttrs.spec.ts",
    "content": "import { patchProp } from '../src/patchProp'\nimport { xlinkNS } from '../src/modules/attrs'\n\ndescribe('runtime-dom: attrs patching', () => {\n  test('xlink attributes', () => {\n    const el = document.createElementNS('http://www.w3.org/2000/svg', 'use')\n    patchProp(el, 'xlink:href', null, 'a', 'svg')\n    expect(el.getAttributeNS(xlinkNS, 'href')).toBe('a')\n    patchProp(el, 'xlink:href', 'a', null, 'svg')\n    expect(el.getAttributeNS(xlinkNS, 'href')).toBe(null)\n  })\n\n  test('textContent attributes /w svg', () => {\n    const el = document.createElementNS('http://www.w3.org/2000/svg', 'use')\n    patchProp(el, 'textContent', null, 'foo', 'svg')\n    expect(el.attributes.length).toBe(0)\n    expect(el.innerHTML).toBe('foo')\n  })\n\n  test('boolean attributes', () => {\n    const el = document.createElement('input')\n    patchProp(el, 'readonly', null, true)\n    expect(el.getAttribute('readonly')).toBe('')\n    patchProp(el, 'readonly', true, false)\n    expect(el.getAttribute('readonly')).toBe(null)\n    patchProp(el, 'readonly', false, '')\n    expect(el.getAttribute('readonly')).toBe('')\n    patchProp(el, 'readonly', '', 0)\n    expect(el.getAttribute('readonly')).toBe(null)\n    patchProp(el, 'readonly', 0, '0')\n    expect(el.getAttribute('readonly')).toBe('')\n    patchProp(el, 'readonly', '0', false)\n    expect(el.getAttribute('readonly')).toBe(null)\n    patchProp(el, 'readonly', false, 1)\n    expect(el.getAttribute('readonly')).toBe('')\n    patchProp(el, 'readonly', 1, undefined)\n    expect(el.getAttribute('readonly')).toBe(null)\n  })\n\n  test('attributes', () => {\n    const el = document.createElement('div')\n    patchProp(el, 'foo', null, 'a')\n    expect(el.getAttribute('foo')).toBe('a')\n    patchProp(el, 'foo', 'a', null)\n    expect(el.getAttribute('foo')).toBe(null)\n  })\n\n  // #949\n  test('onxxx but non-listener attributes', () => {\n    const el = document.createElement('div')\n    patchProp(el, 'onwards', null, 'a')\n    expect(el.getAttribute('onwards')).toBe('a')\n    patchProp(el, 'onwards', 'a', null)\n    expect(el.getAttribute('onwards')).toBe(null)\n  })\n\n  // #10597\n  test('should allow setting attribute to symbol', () => {\n    const el = document.createElement('div')\n    const symbol = Symbol('foo')\n    patchProp(el, 'foo', null, symbol)\n    expect(el.getAttribute('foo')).toBe(symbol.toString())\n  })\n\n  // #10598\n  test('should allow setting value to symbol', () => {\n    const el = document.createElement('input')\n    const symbol = Symbol('foo')\n    patchProp(el, 'value', null, symbol)\n    expect(el.value).toBe(symbol.toString())\n  })\n\n  // #11177\n  test('should allow setting value to object, leaving stringification to the element/browser', () => {\n    // normal behavior\n    const el = document.createElement('div')\n    const obj = { toString: () => 'foo' }\n    patchProp(el, 'data-test', null, obj)\n    expect(el.dataset.test).toBe('foo')\n\n    const el2 = document.createElement('div')\n    let testvalue: null | typeof obj = null\n    // simulating a web component that implements its own setAttribute handler\n    el2.setAttribute = (name, value) => {\n      testvalue = value\n    }\n    patchProp(el2, 'data-test', null, obj)\n    expect(el2.dataset.test).toBe(undefined)\n    expect(testvalue).toBe(obj)\n  })\n\n  // #13946\n  test('sandbox should be handled as attribute even if property exists', () => {\n    const iframe = document.createElement('iframe') as any\n    let propSetCount = 0\n    // simulate sandbox property in jsdom environment\n    Object.defineProperty(iframe, 'sandbox', {\n      configurable: true,\n      enumerable: true,\n      get() {\n        return this._sandbox\n      },\n      set(v) {\n        propSetCount++\n        this._sandbox = v\n      },\n    })\n\n    patchProp(iframe, 'sandbox', null, 'allow-scripts')\n    expect(iframe.getAttribute('sandbox')).toBe('allow-scripts')\n    expect(propSetCount).toBe(0)\n\n    patchProp(iframe, 'sandbox', 'allow-scripts', null)\n    expect(iframe.hasAttribute('sandbox')).toBe(false)\n    expect(iframe.getAttribute('sandbox')).toBe(null)\n    expect(propSetCount).toBe(0)\n\n    patchProp(iframe, 'sandbox', null, '')\n    expect(iframe.getAttribute('sandbox')).toBe('')\n    expect(iframe.hasAttribute('sandbox')).toBe(true)\n    expect(propSetCount).toBe(0)\n\n    delete iframe.sandbox\n  })\n})\n"
  },
  {
    "path": "packages/runtime-dom/__tests__/patchClass.spec.ts",
    "content": "import { patchProp } from '../src/patchProp'\nimport {\n  type ElementWithTransition,\n  vtcKey,\n} from '../src/components/Transition'\nimport { svgNS } from '../src/nodeOps'\n\ndescribe('runtime-dom: class patching', () => {\n  test('basics', () => {\n    const el = document.createElement('div')\n    patchProp(el, 'class', null, 'foo')\n    expect(el.className).toBe('foo')\n    patchProp(el, 'class', null, null)\n    expect(el.className).toBe('')\n  })\n\n  test('transition class', () => {\n    const el = document.createElement('div') as ElementWithTransition\n    el[vtcKey] = new Set(['bar', 'baz'])\n    patchProp(el, 'class', null, 'foo')\n    expect(el.className).toBe('foo bar baz')\n    patchProp(el, 'class', null, null)\n    expect(el.className).toBe('bar baz')\n    delete el[vtcKey]\n    patchProp(el, 'class', null, 'foo')\n    expect(el.className).toBe('foo')\n  })\n\n  test('svg', () => {\n    const el = document.createElementNS(svgNS, 'svg')\n    patchProp(el, 'class', null, 'foo', 'svg')\n    expect(el.getAttribute('class')).toBe('foo')\n  })\n})\n"
  },
  {
    "path": "packages/runtime-dom/__tests__/patchEvents.spec.ts",
    "content": "import { patchProp } from '../src/patchProp'\n\nconst timeout = () => new Promise(r => setTimeout(r))\n\ndescribe(`runtime-dom: events patching`, () => {\n  it('should assign event handler', async () => {\n    const el = document.createElement('div')\n    const fn = vi.fn()\n    patchProp(el, 'onClick', null, fn)\n    el.dispatchEvent(new Event('click'))\n    await timeout()\n    el.dispatchEvent(new Event('click'))\n    await timeout()\n    el.dispatchEvent(new Event('click'))\n    await timeout()\n    expect(fn).toHaveBeenCalledTimes(3)\n  })\n\n  it('should update event handler', async () => {\n    const el = document.createElement('div')\n    const prevFn = vi.fn()\n    const nextFn = vi.fn()\n    patchProp(el, 'onClick', null, prevFn)\n    el.dispatchEvent(new Event('click'))\n    patchProp(el, 'onClick', prevFn, nextFn)\n    await timeout()\n    el.dispatchEvent(new Event('click'))\n    await timeout()\n    el.dispatchEvent(new Event('click'))\n    await timeout()\n    expect(prevFn).toHaveBeenCalledTimes(1)\n    expect(nextFn).toHaveBeenCalledTimes(2)\n  })\n\n  it('should support multiple event handlers', async () => {\n    const el = document.createElement('div')\n    const fn1 = vi.fn()\n    const fn2 = vi.fn()\n    patchProp(el, 'onClick', null, [fn1, fn2])\n    el.dispatchEvent(new Event('click'))\n    await timeout()\n    expect(fn1).toHaveBeenCalledTimes(1)\n    expect(fn2).toHaveBeenCalledTimes(1)\n  })\n\n  it('should unassign event handler', async () => {\n    const el = document.createElement('div')\n    const fn = vi.fn()\n    patchProp(el, 'onClick', null, fn)\n    patchProp(el, 'onClick', fn, null)\n    el.dispatchEvent(new Event('click'))\n    await timeout()\n    expect(fn).not.toHaveBeenCalled()\n  })\n\n  it('should support event option modifiers', async () => {\n    const el = document.createElement('div')\n    const fn = vi.fn()\n    patchProp(el, 'onClickOnceCapture', null, fn)\n    el.dispatchEvent(new Event('click'))\n    await timeout()\n    el.dispatchEvent(new Event('click'))\n    await timeout()\n    expect(fn).toHaveBeenCalledTimes(1)\n  })\n\n  it('should unassign event handler with options', async () => {\n    const el = document.createElement('div')\n    const fn = vi.fn()\n    patchProp(el, 'onClickCapture', null, fn)\n    el.dispatchEvent(new Event('click'))\n    await timeout()\n    expect(fn).toHaveBeenCalledTimes(1)\n\n    patchProp(el, 'onClickCapture', fn, null)\n    el.dispatchEvent(new Event('click'))\n    await timeout()\n    el.dispatchEvent(new Event('click'))\n    await timeout()\n    expect(fn).toHaveBeenCalledTimes(1)\n  })\n\n  it('should support native onclick', async () => {\n    const el = document.createElement('div')\n\n    // string should be set as attribute\n    const fn = ((el as any).spy = vi.fn())\n    patchProp(el, 'onclick', null, 'this.spy(1)')\n    el.dispatchEvent(new Event('click'))\n    await timeout()\n    expect(fn).toHaveBeenCalledWith(1)\n\n    const fn2 = vi.fn()\n    patchProp(el, 'onclick', 'this.spy(1)', fn2)\n    const event = new Event('click')\n    el.dispatchEvent(event)\n    await timeout()\n    expect(fn).toHaveBeenCalledTimes(1)\n    expect(fn2).toHaveBeenCalledWith(event)\n  })\n\n  it('should support stopImmediatePropagation on multiple listeners', async () => {\n    const el = document.createElement('div')\n    const fn1 = vi.fn((e: Event) => {\n      e.stopImmediatePropagation()\n    })\n    const fn2 = vi.fn()\n    patchProp(el, 'onClick', null, [fn1, fn2])\n    el.dispatchEvent(new Event('click'))\n    await timeout()\n    expect(fn1).toHaveBeenCalledTimes(1)\n    expect(fn2).toHaveBeenCalledTimes(0)\n  })\n\n  // #1747\n  it('should handle same computed handler function being bound on multiple targets', async () => {\n    const el1 = document.createElement('div')\n    const el2 = document.createElement('div')\n\n    // const event = new Event('click')\n    const prevFn = vi.fn()\n    const nextFn = vi.fn()\n\n    patchProp(el1, 'onClick', null, prevFn)\n    patchProp(el2, 'onClick', null, prevFn)\n\n    el1.dispatchEvent(new Event('click'))\n    el2.dispatchEvent(new Event('click'))\n    await timeout()\n    expect(prevFn).toHaveBeenCalledTimes(2)\n    expect(nextFn).toHaveBeenCalledTimes(0)\n\n    patchProp(el1, 'onClick', prevFn, nextFn)\n    patchProp(el2, 'onClick', prevFn, nextFn)\n\n    el1.dispatchEvent(new Event('click'))\n    el2.dispatchEvent(new Event('click'))\n    await timeout()\n    expect(prevFn).toHaveBeenCalledTimes(2)\n    expect(nextFn).toHaveBeenCalledTimes(2)\n\n    el1.dispatchEvent(new Event('click'))\n    el2.dispatchEvent(new Event('click'))\n    await timeout()\n    expect(prevFn).toHaveBeenCalledTimes(2)\n    expect(nextFn).toHaveBeenCalledTimes(4)\n  })\n\n  // vuejs/vue#6566\n  it('should not fire handler attached by the event itself', async () => {\n    const el = document.createElement('div')\n    const child = document.createElement('div')\n    el.appendChild(child)\n    document.body.appendChild(el)\n    const childFn = vi.fn()\n    const parentFn = vi.fn()\n\n    patchProp(child, 'onClick', null, () => {\n      childFn()\n      patchProp(el, 'onClick', null, parentFn)\n    })\n\n    await timeout()\n    child.dispatchEvent(new Event('click', { bubbles: true }))\n\n    expect(childFn).toHaveBeenCalled()\n    expect(parentFn).not.toHaveBeenCalled()\n  })\n\n  // #2841\n  test('should patch event correctly in web-components', async () => {\n    class TestElement extends HTMLElement {\n      constructor() {\n        super()\n      }\n    }\n    window.customElements.define('test-element', TestElement)\n    const testElement = document.createElement('test-element', {\n      is: 'test-element',\n    })\n    const fn1 = vi.fn()\n    const fn2 = vi.fn()\n\n    // in webComponents, @foo-bar will patch prop 'onFooBar'\n    // and @foobar will patch prop 'onFoobar'\n\n    patchProp(testElement, 'onFooBar', null, fn1)\n    testElement.dispatchEvent(new CustomEvent('foo-bar'))\n    expect(fn1).toHaveBeenCalledTimes(1)\n\n    patchProp(testElement, 'onFoobar', null, fn2)\n    testElement.dispatchEvent(new CustomEvent('foobar'))\n    expect(fn2).toHaveBeenCalledTimes(1)\n  })\n\n  it('handles an unknown type', () => {\n    const el = document.createElement('div')\n    patchProp(el, 'onClick', null, 'test')\n    el.dispatchEvent(new Event('click'))\n    expect(\n      `Wrong type passed as event handler to onClick - did you forget @ or : ` +\n        `in front of your prop?\\nExpected function or array of functions, received type string.`,\n    ).toHaveBeenWarned()\n  })\n})\n"
  },
  {
    "path": "packages/runtime-dom/__tests__/patchProps.spec.ts",
    "content": "import { patchProp } from '../src/patchProp'\nimport {\n  h,\n  nextTick,\n  ref,\n  render,\n  vModelCheckbox,\n  withDirectives,\n} from '../src'\n\ndescribe('runtime-dom: props patching', () => {\n  test('basic', () => {\n    const el = document.createElement('div')\n    patchProp(el, 'id', null, 'foo')\n    expect(el.id).toBe('foo')\n    // prop with string value should be set to empty string on null values\n    patchProp(el, 'id', null, null)\n    expect(el.id).toBe('')\n    expect(el.getAttribute('id')).toBe(null)\n  })\n\n  test('value', () => {\n    const el = document.createElement('input')\n    patchProp(el, 'value', null, 'foo')\n    expect(el.value).toBe('foo')\n    patchProp(el, 'value', null, null)\n    expect(el.value).toBe('')\n    expect(el.getAttribute('value')).toBe(null)\n    const obj = {}\n    patchProp(el, 'value', null, obj)\n    expect(el.value).toBe(obj.toString())\n    expect((el as any)._value).toBe(obj)\n\n    const option = document.createElement('option')\n    patchProp(option, 'textContent', null, 'foo')\n    expect(option.value).toBe('foo')\n    expect(option.getAttribute('value')).toBe(null)\n    patchProp(option, 'value', null, 'foo')\n    expect(option.value).toBe('foo')\n    expect(option.getAttribute('value')).toBe('foo')\n  })\n\n  test('value for custom elements', () => {\n    class TestElement extends HTMLElement {\n      constructor() {\n        super()\n      }\n\n      // intentionally uses _value because this is used in \"normal\" HTMLElement for storing the object of the set property value\n      private _value: any\n      get value() {\n        return this._value\n      }\n\n      set value(val) {\n        this._value = val\n        this.setterCalled++\n      }\n\n      public setterCalled: number = 0\n    }\n    window.customElements.define('patch-props-test-element', TestElement)\n    const el = document.createElement('patch-props-test-element') as TestElement\n    patchProp(el, 'value', null, 'foo')\n    expect(el.value).toBe('foo')\n    expect(el.setterCalled).toBe(1)\n    patchProp(el, 'value', null, null)\n    expect(el.value).toBe('')\n    expect(el.setterCalled).toBe(2)\n    expect(el.getAttribute('value')).toBe(null)\n    const obj = {}\n    patchProp(el, 'value', null, obj)\n    expect(el.value).toBe(obj)\n    expect(el.setterCalled).toBe(3)\n  })\n\n  // For <input type=\"text\">, setting el.value won't create a `value` attribute\n  // so we need to add tests for other elements\n  test('value for non-text input', () => {\n    const el = document.createElement('option')\n    el.textContent = 'foo' // #4956\n    patchProp(el, 'value', null, 'foo')\n    expect(el.getAttribute('value')).toBe('foo')\n    expect(el.value).toBe('foo')\n    patchProp(el, 'value', null, null)\n    el.textContent = ''\n    expect(el.value).toBe('')\n    // #3475\n    expect(el.getAttribute('value')).toBe(null)\n  })\n\n  test('boolean prop', () => {\n    const el = document.createElement('select')\n    patchProp(el, 'multiple', null, '')\n    expect(el.multiple).toBe(true)\n    patchProp(el, 'multiple', null, null)\n    expect(el.multiple).toBe(false)\n    patchProp(el, 'multiple', null, true)\n    expect(el.multiple).toBe(true)\n    patchProp(el, 'multiple', null, 0)\n    expect(el.multiple).toBe(false)\n    patchProp(el, 'multiple', null, '0')\n    expect(el.multiple).toBe(true)\n    patchProp(el, 'multiple', null, false)\n    expect(el.multiple).toBe(false)\n    patchProp(el, 'multiple', null, 1)\n    expect(el.multiple).toBe(true)\n    patchProp(el, 'multiple', null, undefined)\n    expect(el.multiple).toBe(false)\n  })\n\n  test('innerHTML unmount prev children', () => {\n    const fn = vi.fn()\n    const comp = {\n      render: () => 'foo',\n      unmounted: fn,\n    }\n    const root = document.createElement('div')\n    render(h('div', null, [h(comp)]), root)\n    expect(root.innerHTML).toBe(`<div>foo</div>`)\n\n    render(h('div', { innerHTML: 'bar' }), root)\n    expect(root.innerHTML).toBe(`<div>bar</div>`)\n    expect(fn).toHaveBeenCalled()\n  })\n\n  // #954\n  test('(svg) innerHTML unmount prev children', () => {\n    const fn = vi.fn()\n    const comp = {\n      render: () => 'foo',\n      unmounted: fn,\n    }\n    const root = document.createElement('div')\n    render(h('div', null, [h(comp)]), root)\n    expect(root.innerHTML).toBe(`<div>foo</div>`)\n\n    render(h('svg', { innerHTML: '<g></g>' }), root)\n    expect(root.innerHTML).toBe(`<svg><g></g></svg>`)\n    expect(fn).toHaveBeenCalled()\n  })\n\n  test('patch innerHTML porp', async () => {\n    const root = document.createElement('div')\n    const state = ref(false)\n    const Comp = {\n      render: () => {\n        if (state.value) {\n          return h('div', [h('del', null, 'baz')])\n        } else {\n          return h('div', { innerHTML: 'baz' })\n        }\n      },\n    }\n    render(h(Comp), root)\n    expect(root.innerHTML).toBe(`<div>baz</div>`)\n    state.value = true\n    await nextTick()\n    expect(root.innerHTML).toBe(`<div><del>baz</del></div>`)\n  })\n\n  test('patch innerHTML porp w/ undefined value', async () => {\n    const root = document.createElement('div')\n    render(h('div', { innerHTML: undefined }), root)\n    expect(root.innerHTML).toBe(`<div></div>`)\n  })\n\n  test('textContent unmount prev children', () => {\n    const fn = vi.fn()\n    const comp = {\n      render: () => 'foo',\n      unmounted: fn,\n    }\n    const root = document.createElement('div')\n    render(h('div', null, [h(comp)]), root)\n    expect(root.innerHTML).toBe(`<div>foo</div>`)\n\n    render(h('div', { textContent: 'bar' }), root)\n    expect(root.innerHTML).toBe(`<div>bar</div>`)\n    expect(fn).toHaveBeenCalled()\n  })\n\n  // #1049\n  test('set value as-is for non string-value props', () => {\n    const el = document.createElement('video')\n    // jsdom doesn't really support video playback. srcObject in a real browser\n    // should default to `null`, but in jsdom it's `undefined`.\n    // anyway, here we just want to make sure Vue doesn't set non-string props\n    // to an empty string on nullish values - it should reset to its default\n    // value.\n    el.srcObject = null\n    const initialValue = el.srcObject\n    const fakeObject = {}\n    patchProp(el, 'srcObject', null, fakeObject)\n    expect(el.srcObject).toBe(fakeObject)\n    patchProp(el, 'srcObject', null, null)\n    expect(el.srcObject).toBe(initialValue)\n  })\n\n  test('catch and warn prop set TypeError', () => {\n    const el = document.createElement('div')\n    Object.defineProperty(el, 'someProp', {\n      set() {\n        throw new TypeError('Invalid type')\n      },\n    })\n    patchProp(el, 'someProp', null, 'foo')\n\n    expect(`Failed setting prop \"someProp\" on <div>`).toHaveBeenWarnedLast()\n  })\n\n  // #1576\n  test('remove attribute when value is falsy', () => {\n    const el = document.createElement('div')\n    patchProp(el, 'id', null, '')\n    expect(el.hasAttribute('id')).toBe(true)\n    patchProp(el, 'id', null, null)\n    expect(el.hasAttribute('id')).toBe(false)\n\n    patchProp(el, 'id', null, '')\n    expect(el.hasAttribute('id')).toBe(true)\n    patchProp(el, 'id', null, undefined)\n    expect(el.hasAttribute('id')).toBe(false)\n\n    patchProp(el, 'id', null, '')\n    expect(el.hasAttribute('id')).toBe(true)\n\n    // #2677\n    const img = document.createElement('img')\n    patchProp(img, 'width', null, '')\n    expect(el.hasAttribute('width')).toBe(false)\n    patchProp(img, 'width', null, 0)\n    expect(img.hasAttribute('width')).toBe(true)\n\n    patchProp(img, 'width', null, null)\n    expect(img.hasAttribute('width')).toBe(false)\n    patchProp(img, 'width', null, 0)\n    expect(img.hasAttribute('width')).toBe(true)\n\n    patchProp(img, 'width', null, undefined)\n    expect(img.hasAttribute('width')).toBe(false)\n    patchProp(img, 'width', null, 0)\n    expect(img.hasAttribute('width')).toBe(true)\n  })\n\n  test('form attribute', () => {\n    const el = document.createElement('input')\n    patchProp(el, 'form', null, 'foo')\n    // non existent element\n    expect(el.form).toBe(null)\n    expect(el.getAttribute('form')).toBe('foo')\n    // remove attribute\n    patchProp(el, 'form', 'foo', null)\n    expect(el.getAttribute('form')).toBe(null)\n  })\n\n  test('readonly type prop on textarea', () => {\n    const el = document.createElement('textarea')\n    // just to verify that it doesn't throw when i.e. switching a dynamic :is from an 'input' to a 'textarea'\n    // see https://github.com/vuejs/core/issues/2766\n    patchProp(el, 'type', 'text', null)\n  })\n\n  test('force patch as prop', () => {\n    const el = document.createElement('div') as any\n    patchProp(el, '.x', null, 1)\n    expect(el.x).toBe(1)\n  })\n\n  test('force patch as attribute', () => {\n    const el = document.createElement('div') as any\n    el.x = 1\n    patchProp(el, '^x', null, 2)\n    expect(el.x).toBe(1)\n    expect(el.getAttribute('x')).toBe('2')\n  })\n\n  test('input with size (number property)', () => {\n    const el = document.createElement('input')\n    patchProp(el, 'size', null, 100)\n    expect(el.size).toBe(100)\n    patchProp(el, 'size', 100, null)\n    expect(el.getAttribute('size')).toBe(null)\n    expect('Failed setting prop \"size\" on <input>').not.toHaveBeenWarned()\n    patchProp(el, 'size', null, 'foobar')\n    expect('Failed setting prop \"size\" on <input>').toHaveBeenWarnedLast()\n  })\n\n  test('select with type (string property)', () => {\n    const el = document.createElement('select')\n    patchProp(el, 'type', null, 'test')\n    expect(el.type).toBe('select-one')\n    expect('Failed setting prop \"type\" on <select>').toHaveBeenWarnedLast()\n  })\n\n  test('select with willValidate (boolean property)', () => {\n    const el = document.createElement('select')\n    patchProp(el, 'willValidate', true, null)\n    expect(el.willValidate).toBe(true)\n    expect(\n      'Failed setting prop \"willValidate\" on <select>',\n    ).toHaveBeenWarnedLast()\n  })\n\n  test('patch value for select', () => {\n    const root = document.createElement('div')\n    render(\n      h('select', { value: 'foo' }, [\n        h('option', { value: 'foo' }, 'foo'),\n        h('option', { value: 'bar' }, 'bar'),\n      ]),\n      root,\n    )\n    const el = root.children[0] as HTMLSelectElement\n    expect(el.value).toBe('foo')\n\n    render(\n      h('select', { value: 'baz' }, [\n        h('option', { value: 'foo' }, 'foo'),\n        h('option', { value: 'baz' }, 'baz'),\n      ]),\n      root,\n    )\n    expect(el.value).toBe('baz')\n  })\n\n  test('init empty value for option', () => {\n    const root = document.createElement('div')\n    render(\n      h('select', { value: 'foo' }, [h('option', { value: '' }, 'foo')]),\n      root,\n    )\n    const select = root.children[0] as HTMLSelectElement\n    const option = select.children[0] as HTMLOptionElement\n    expect(select.value).toBe('')\n    expect(option.value).toBe('')\n  })\n\n  // #8780\n  test('embedded tag with width and height', () => {\n    // Width and height of some embedded element such as img、video、source、canvas\n    // must be set as attribute\n    const el = document.createElement('img')\n    patchProp(el, 'width', null, '24px')\n    expect(el.getAttribute('width')).toBe('24px')\n  })\n\n  // # 9762 should fallthrough to `key in el` logic for non embedded tags\n  test('width and height on custom elements', () => {\n    const el = document.createElement('foobar')\n    patchProp(el, 'width', null, '24px')\n    expect(el.getAttribute('width')).toBe('24px')\n  })\n\n  test('translate attribute', () => {\n    const el = document.createElement('div')\n    patchProp(el, 'translate', null, 'no')\n    expect(el.translate).toBeFalsy()\n    expect(el.getAttribute('translate')).toBe('no')\n  })\n\n  // #11647\n  test('should not trigger input mutation when `value` is `undefined`', async () => {\n    const fn = vi.fn()\n    const comp = {\n      setup() {\n        const checked = ref()\n        return () =>\n          withDirectives(\n            h('input', {\n              type: 'checkbox',\n              value: undefined,\n              'onUpdate:modelValue': (value: any) => {\n                checked.value = value\n              },\n            }),\n            [[vModelCheckbox, checked.value]],\n          )\n      },\n    }\n\n    const root = document.createElement('div')\n    render(h(comp), root)\n    document.body.append(root)\n\n    const el = root.children[0] as HTMLInputElement\n    const observer = new MutationObserver(fn)\n    observer.observe(el, {\n      attributes: true,\n    })\n\n    el.click()\n    await nextTick()\n\n    expect(fn).toBeCalledTimes(0)\n  })\n})\n"
  },
  {
    "path": "packages/runtime-dom/__tests__/patchStyle.spec.ts",
    "content": "import { patchProp } from '../src/patchProp'\n\ndescribe(`runtime-dom: style patching`, () => {\n  it('string', () => {\n    const el = document.createElement('div')\n    patchProp(el, 'style', {}, 'color:red')\n    expect(el.style.cssText.replace(/\\s/g, '')).toBe('color:red;')\n  })\n\n  // #1309\n  it('should not patch same string style', () => {\n    const el = document.createElement('div')\n    const fn = vi.fn()\n    const value = (el.style.cssText = 'color:red;')\n    Object.defineProperty(el.style, 'cssText', {\n      get(): any {\n        return value\n      },\n      set: fn,\n    })\n    patchProp(el, 'style', value, value)\n    expect(el.style.cssText.replace(/\\s/g, '')).toBe('color:red;')\n    expect(fn).not.toBeCalled()\n  })\n\n  it('plain object', () => {\n    const el = document.createElement('div')\n    patchProp(el, 'style', {}, { color: 'red' })\n    expect(el.style.cssText.replace(/\\s/g, '')).toBe('color:red;')\n  })\n\n  it('camelCase', () => {\n    const el = document.createElement('div')\n    patchProp(el, 'style', {}, { marginRight: '10px' })\n    expect(el.style.cssText.replace(/\\s/g, '')).toBe('margin-right:10px;')\n  })\n\n  it('remove if falsy value', () => {\n    const el = document.createElement('div')\n    patchProp(el, 'style', null, {\n      color: undefined,\n      borderRadius: null,\n    })\n    expect(el.style.cssText.replace(/\\s/g, '')).toBe('')\n\n    patchProp(\n      el,\n      'style',\n      { color: 'red' },\n      { color: null, borderRadius: undefined },\n    )\n    expect(el.style.cssText.replace(/\\s/g, '')).toBe('')\n  })\n\n  it('!important', () => {\n    const el = document.createElement('div')\n    patchProp(el, 'style', {}, { color: 'red !important' })\n    expect(el.style.cssText.replace(/\\s/g, '')).toBe('color:red!important;')\n  })\n\n  it('camelCase with !important', () => {\n    const el = document.createElement('div')\n    patchProp(el, 'style', {}, { marginRight: '10px !important' })\n    expect(el.style.cssText.replace(/\\s/g, '')).toBe(\n      'margin-right:10px!important;',\n    )\n  })\n\n  it('object with multiple entries', () => {\n    const el = document.createElement('div')\n    patchProp(el, 'style', {}, { color: 'red', marginRight: '10px' })\n    expect(el.style.getPropertyValue('color')).toBe('red')\n    expect(el.style.getPropertyValue('margin-right')).toBe('10px')\n  })\n\n  it('patch with falsy style value', () => {\n    const el = document.createElement('div')\n    patchProp(el as any, 'style', { width: '100px' }, { width: 0 })\n    expect(el.style.width).toBe('0px')\n  })\n\n  it('should remove style attribute on falsy value', () => {\n    const el = document.createElement('div')\n    el.style.cssText = 'color: red;'\n    patchProp(el as any, 'style', {}, null)\n    expect(el.hasAttribute('style')).toBe(false)\n    expect(el.style.cssText).toBe('')\n  })\n\n  it('should warn for trailing semicolons', () => {\n    const el = document.createElement('div')\n    patchProp(el, 'style', null, { color: 'red;' })\n    expect(\n      `Unexpected semicolon at the end of 'color' style value: 'red;'`,\n    ).toHaveBeenWarned()\n\n    patchProp(el, 'style', null, { '--custom': '100; ' })\n    expect(\n      `Unexpected semicolon at the end of '--custom' style value: '100; '`,\n    ).toHaveBeenWarned()\n  })\n\n  it('should not warn for escaped trailing semicolons', () => {\n    const el = document.createElement('div')\n    patchProp(el, 'style', null, { '--custom': '100\\\\;' })\n    expect(el.style.getPropertyValue('--custom')).toBe('100\\\\;')\n  })\n\n  it('shorthand properties', () => {\n    const el = document.createElement('div')\n    patchProp(\n      el as any,\n      'style',\n      { borderBottom: '1px solid red' },\n      { border: '1px solid green' },\n    )\n    expect(el.style.border).toBe('1px solid green')\n    expect(el.style.borderBottom).toBe('1px solid green')\n  })\n\n  // JSDOM doesn't support custom properties on style object so we have to\n  // mock it here.\n  function mockElementWithStyle() {\n    const store: any = {}\n    return {\n      style: {\n        display: '',\n        WebkitTransition: '',\n        setProperty(key: string, val: string) {\n          store[key] = val\n        },\n        getPropertyValue(key: string) {\n          return store[key]\n        },\n      },\n    }\n  }\n\n  it('CSS custom properties', () => {\n    const el = mockElementWithStyle()\n    patchProp(el as any, 'style', {}, { '--theme': 'red' } as any)\n    expect(el.style.getPropertyValue('--theme')).toBe('red')\n  })\n\n  it('auto vendor prefixing', () => {\n    const el = mockElementWithStyle()\n    patchProp(el as any, 'style', {}, { transition: 'all 1s' })\n    expect(el.style.WebkitTransition).toBe('all 1s')\n  })\n\n  it('multiple values', () => {\n    const el = mockElementWithStyle()\n    patchProp(\n      el as any,\n      'style',\n      {},\n      { display: ['-webkit-box', '-ms-flexbox', 'flex'] },\n    )\n    expect(el.style.display).toBe('flex')\n  })\n\n  it('should clear previous css string value', () => {\n    const el = document.createElement('div')\n    patchProp(el, 'style', {}, 'color:red')\n    expect(el.style.cssText.replace(/\\s/g, '')).toBe('color:red;')\n\n    patchProp(el, 'style', 'color:red', { fontSize: '12px' })\n    expect(el.style.cssText.replace(/\\s/g, '')).toBe('font-size:12px;')\n  })\n})\n"
  },
  {
    "path": "packages/runtime-dom/__tests__/rendererStaticNode.spec.ts",
    "content": "import { createStaticVNode, h, render } from '../src'\n\ndescribe('static vnode handling', () => {\n  const content = `<div>hello</div><p>world</p>`\n  const content2 = `<p>foo</p><div>bar</div><span>baz</span>`\n\n  const s = createStaticVNode(content, 2)\n  const s2 = createStaticVNode(content2, 3)\n\n  test('should mount from string', () => {\n    const root = document.createElement('div')\n    render(h('div', [s]), root)\n    expect(root.innerHTML).toBe(`<div>${content}</div>`)\n  })\n\n  test('should support reusing the same hoisted node', () => {\n    const root = document.createElement('div')\n    render(h('div', [s, s]), root)\n    expect(root.innerHTML).toBe(`<div>${content}${content}</div>`)\n  })\n\n  // the rest only happens during HMR but needs to be correctly supported\n  test('should update', () => {\n    const root = document.createElement('div')\n    render(h('div', [s]), root)\n    expect(root.innerHTML).toBe(`<div>${content}</div>`)\n    render(h('div', [s2]), root)\n    expect(root.innerHTML).toBe(`<div>${content2}</div>`)\n  })\n\n  test('should move', () => {\n    const root = document.createElement('div')\n    render(h('div', [h('b'), s, h('b')]), root)\n    expect(root.innerHTML).toBe(`<div><b></b>${content}<b></b></div>`)\n    render(h('div', [s, h('b'), h('b')]), root)\n    expect(root.innerHTML).toBe(`<div>${content}<b></b><b></b></div>`)\n    render(h('div', [h('b'), h('b'), s]), root)\n    expect(root.innerHTML).toBe(`<div><b></b><b></b>${content}</div>`)\n  })\n\n  test('should remove', () => {\n    const root = document.createElement('div')\n    render(h('div', [h('b'), s, h('b')]), root)\n    expect(root.innerHTML).toBe(`<div><b></b>${content}<b></b></div>`)\n    render(h('div', [h('b'), h('b')]), root)\n    expect(root.innerHTML).toBe(`<div><b></b><b></b></div>`)\n    render(h('div', [h('b'), h('b'), s]), root)\n    expect(root.innerHTML).toBe(`<div><b></b><b></b>${content}</div>`)\n  })\n})\n"
  },
  {
    "path": "packages/runtime-dom/index.js",
    "content": "'use strict'\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./dist/runtime-dom.cjs.prod.js')\n} else {\n  module.exports = require('./dist/runtime-dom.cjs.js')\n}\n"
  },
  {
    "path": "packages/runtime-dom/package.json",
    "content": "{\n  \"name\": \"@vue/runtime-dom\",\n  \"version\": \"3.5.30\",\n  \"description\": \"@vue/runtime-dom\",\n  \"main\": \"index.js\",\n  \"module\": \"dist/runtime-dom.esm-bundler.js\",\n  \"types\": \"dist/runtime-dom.d.ts\",\n  \"unpkg\": \"dist/runtime-dom.global.js\",\n  \"files\": [\n    \"index.js\",\n    \"dist\"\n  ],\n  \"exports\": {\n    \".\": {\n      \"types\": \"./dist/runtime-dom.d.ts\",\n      \"node\": {\n        \"production\": \"./dist/runtime-dom.cjs.prod.js\",\n        \"development\": \"./dist/runtime-dom.cjs.js\",\n        \"default\": \"./index.js\"\n      },\n      \"module\": \"./dist/runtime-dom.esm-bundler.js\",\n      \"import\": \"./dist/runtime-dom.esm-bundler.js\",\n      \"require\": \"./index.js\"\n    },\n    \"./*\": \"./*\"\n  },\n  \"sideEffects\": false,\n  \"buildOptions\": {\n    \"name\": \"VueRuntimeDOM\",\n    \"formats\": [\n      \"esm-bundler\",\n      \"esm-browser\",\n      \"cjs\",\n      \"global\"\n    ]\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/vuejs/core.git\",\n    \"directory\": \"packages/runtime-dom\"\n  },\n  \"keywords\": [\n    \"vue\"\n  ],\n  \"author\": \"Evan You\",\n  \"license\": \"MIT\",\n  \"bugs\": {\n    \"url\": \"https://github.com/vuejs/core/issues\"\n  },\n  \"homepage\": \"https://github.com/vuejs/core/tree/main/packages/runtime-dom#readme\",\n  \"dependencies\": {\n    \"@vue/shared\": \"workspace:*\",\n    \"@vue/runtime-core\": \"workspace:*\",\n    \"@vue/reactivity\": \"workspace:*\",\n    \"csstype\": \"^3.2.3\"\n  },\n  \"devDependencies\": {\n    \"@types/trusted-types\": \"^2.0.7\"\n  }\n}\n"
  },
  {
    "path": "packages/runtime-dom/src/apiCustomElement.ts",
    "content": "import {\n  type App,\n  type Component,\n  type ComponentCustomElementInterface,\n  type ComponentInjectOptions,\n  type ComponentInternalInstance,\n  type ComponentObjectPropsOptions,\n  type ComponentOptions,\n  type ComponentOptionsBase,\n  type ComponentOptionsMixin,\n  type ComponentProvideOptions,\n  type ComponentPublicInstance,\n  type ComputedOptions,\n  type ConcreteComponent,\n  type CreateAppFunction,\n  type CreateComponentPublicInstanceWithMixins,\n  type DefineComponent,\n  type Directive,\n  type EmitsOptions,\n  type EmitsToProps,\n  type ExtractPropTypes,\n  type MethodOptions,\n  type RenderFunction,\n  type SetupContext,\n  type SlotsType,\n  type VNode,\n  type VNodeProps,\n  createVNode,\n  defineComponent,\n  getCurrentInstance,\n  nextTick,\n  unref,\n  warn,\n} from '@vue/runtime-core'\nimport {\n  camelize,\n  extend,\n  hasOwn,\n  hyphenate,\n  isArray,\n  isPlainObject,\n  toNumber,\n} from '@vue/shared'\nimport { createApp, createSSRApp, render } from '.'\n\n// marker for attr removal\nconst REMOVAL = {}\n\nexport type VueElementConstructor<P = {}> = {\n  new (initialProps?: Record<string, any>): VueElement & P\n}\n\nexport interface CustomElementOptions {\n  styles?: string[]\n  shadowRoot?: boolean\n  shadowRootOptions?: Omit<ShadowRootInit, 'mode'>\n  nonce?: string\n  configureApp?: (app: App) => void\n}\n\n// defineCustomElement provides the same type inference as defineComponent\n// so most of the following overloads should be kept in sync w/ defineComponent.\n\n// overload 1: direct setup function\nexport function defineCustomElement<Props, RawBindings = object>(\n  setup: (props: Props, ctx: SetupContext) => RawBindings | RenderFunction,\n  options?: Pick<ComponentOptions, 'name' | 'inheritAttrs' | 'emits'> &\n    CustomElementOptions & {\n      props?: (keyof Props)[]\n    },\n): VueElementConstructor<Props>\nexport function defineCustomElement<Props, RawBindings = object>(\n  setup: (props: Props, ctx: SetupContext) => RawBindings | RenderFunction,\n  options?: Pick<ComponentOptions, 'name' | 'inheritAttrs' | 'emits'> &\n    CustomElementOptions & {\n      props?: ComponentObjectPropsOptions<Props>\n    },\n): VueElementConstructor<Props>\n\n// overload 2: defineCustomElement with options object, infer props from options\nexport function defineCustomElement<\n  // props\n  RuntimePropsOptions extends ComponentObjectPropsOptions =\n    ComponentObjectPropsOptions,\n  PropsKeys extends string = string,\n  // emits\n  RuntimeEmitsOptions extends EmitsOptions = {},\n  EmitsKeys extends string = string,\n  // other options\n  Data = {},\n  SetupBindings = {},\n  Computed extends ComputedOptions = {},\n  Methods extends MethodOptions = {},\n  Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,\n  Extends extends ComponentOptionsMixin = ComponentOptionsMixin,\n  InjectOptions extends ComponentInjectOptions = {},\n  InjectKeys extends string = string,\n  Slots extends SlotsType = {},\n  LocalComponents extends Record<string, Component> = {},\n  Directives extends Record<string, Directive> = {},\n  Exposed extends string = string,\n  Provide extends ComponentProvideOptions = ComponentProvideOptions,\n  // resolved types\n  InferredProps = string extends PropsKeys\n    ? ComponentObjectPropsOptions extends RuntimePropsOptions\n      ? {}\n      : ExtractPropTypes<RuntimePropsOptions>\n    : { [key in PropsKeys]?: any },\n  ResolvedProps = InferredProps & EmitsToProps<RuntimeEmitsOptions>,\n>(\n  options: CustomElementOptions & {\n    props?: (RuntimePropsOptions & ThisType<void>) | PropsKeys[]\n  } & ComponentOptionsBase<\n      ResolvedProps,\n      SetupBindings,\n      Data,\n      Computed,\n      Methods,\n      Mixin,\n      Extends,\n      RuntimeEmitsOptions,\n      EmitsKeys,\n      {}, // Defaults\n      InjectOptions,\n      InjectKeys,\n      Slots,\n      LocalComponents,\n      Directives,\n      Exposed,\n      Provide\n    > &\n    ThisType<\n      CreateComponentPublicInstanceWithMixins<\n        Readonly<ResolvedProps>,\n        SetupBindings,\n        Data,\n        Computed,\n        Methods,\n        Mixin,\n        Extends,\n        RuntimeEmitsOptions,\n        EmitsKeys,\n        {},\n        false,\n        InjectOptions,\n        Slots,\n        LocalComponents,\n        Directives,\n        Exposed\n      >\n    >,\n  extraOptions?: CustomElementOptions,\n): VueElementConstructor<ResolvedProps>\n\n// overload 3: defining a custom element from the returned value of\n// `defineComponent`\nexport function defineCustomElement<\n  // this should be `ComponentPublicInstanceConstructor` but that type is not exported\n  T extends { new (...args: any[]): ComponentPublicInstance<any> },\n>(\n  options: T,\n  extraOptions?: CustomElementOptions,\n): VueElementConstructor<\n  T extends DefineComponent<infer P, any, any, any> ? P : unknown\n>\n\n/*@__NO_SIDE_EFFECTS__*/\nexport function defineCustomElement(\n  options: any,\n  extraOptions?: ComponentOptions,\n  /**\n   * @internal\n   */\n  _createApp?: CreateAppFunction<Element>,\n): VueElementConstructor {\n  let Comp = defineComponent(options, extraOptions) as any\n  if (isPlainObject(Comp)) Comp = extend({}, Comp, extraOptions)\n  class VueCustomElement extends VueElement {\n    static def = Comp\n    constructor(initialProps?: Record<string, any>) {\n      super(Comp, initialProps, _createApp)\n    }\n  }\n\n  return VueCustomElement\n}\n\n/*@__NO_SIDE_EFFECTS__*/\nexport const defineSSRCustomElement = ((\n  options: any,\n  extraOptions?: ComponentOptions,\n) => {\n  // @ts-expect-error\n  return defineCustomElement(options, extraOptions, createSSRApp)\n}) as typeof defineCustomElement\n\nconst BaseClass = (\n  typeof HTMLElement !== 'undefined' ? HTMLElement : class {}\n) as typeof HTMLElement\n\ntype InnerComponentDef = ConcreteComponent & CustomElementOptions\n\nexport class VueElement\n  extends BaseClass\n  implements ComponentCustomElementInterface\n{\n  _isVueCE = true\n  /**\n   * @internal\n   */\n  _instance: ComponentInternalInstance | null = null\n  /**\n   * @internal\n   */\n  _app: App | null = null\n  /**\n   * @internal\n   */\n  _root: Element | ShadowRoot\n  /**\n   * @internal\n   */\n  _nonce: string | undefined = this._def.nonce\n\n  /**\n   * @internal\n   */\n  _teleportTargets?: Set<Element>\n\n  private _connected = false\n  private _resolved = false\n  private _patching = false\n  private _dirty = false\n  private _numberProps: Record<string, true> | null = null\n  private _styleChildren = new WeakSet()\n  private _pendingResolve: Promise<void> | undefined\n  private _parent: VueElement | undefined\n  private _styleAnchors: WeakMap<ConcreteComponent, HTMLStyleElement> =\n    new WeakMap()\n  /**\n   * dev only\n   */\n  private _styles?: HTMLStyleElement[]\n  /**\n   * dev only\n   */\n  private _childStyles?: Map<string, HTMLStyleElement[]>\n  private _ob?: MutationObserver | null = null\n  private _slots?: Record<string, Node[]>\n\n  constructor(\n    /**\n     * Component def - note this may be an AsyncWrapper, and this._def will\n     * be overwritten by the inner component when resolved.\n     */\n    private _def: InnerComponentDef,\n    private _props: Record<string, any> = {},\n    private _createApp: CreateAppFunction<Element> = createApp,\n  ) {\n    super()\n    if (this.shadowRoot && _createApp !== createApp) {\n      this._root = this.shadowRoot\n    } else {\n      if (__DEV__ && this.shadowRoot) {\n        warn(\n          `Custom element has pre-rendered declarative shadow root but is not ` +\n            `defined as hydratable. Use \\`defineSSRCustomElement\\`.`,\n        )\n      }\n      if (_def.shadowRoot !== false) {\n        this.attachShadow(\n          extend({}, _def.shadowRootOptions, {\n            mode: 'open',\n          }) as ShadowRootInit,\n        )\n        this._root = this.shadowRoot!\n      } else {\n        this._root = this\n      }\n    }\n  }\n\n  connectedCallback(): void {\n    // avoid resolving component if it's not connected\n    if (!this.isConnected) return\n\n    // avoid re-parsing slots if already resolved\n    if (!this.shadowRoot && !this._resolved) {\n      this._parseSlots()\n    }\n    this._connected = true\n\n    // locate nearest Vue custom element parent for provide/inject\n    let parent: Node | null = this\n    while (\n      (parent =\n        parent &&\n        // #12479 should check assignedSlot first to get correct parent\n        ((parent as Element).assignedSlot ||\n          parent.parentNode ||\n          (parent as ShadowRoot).host))\n    ) {\n      if (parent instanceof VueElement) {\n        this._parent = parent\n        break\n      }\n    }\n\n    if (!this._instance) {\n      if (this._resolved) {\n        this._mount(this._def)\n      } else {\n        if (parent && parent._pendingResolve) {\n          this._pendingResolve = parent._pendingResolve.then(() => {\n            this._pendingResolve = undefined\n            this._resolveDef()\n          })\n        } else {\n          this._resolveDef()\n        }\n      }\n    }\n  }\n\n  private _setParent(parent = this._parent) {\n    if (parent) {\n      this._instance!.parent = parent._instance\n      this._inheritParentContext(parent)\n    }\n  }\n\n  private _inheritParentContext(parent = this._parent) {\n    // #13212, the provides object of the app context must inherit the provides\n    // object from the parent element so we can inject values from both places\n    if (parent && this._app) {\n      Object.setPrototypeOf(\n        this._app._context.provides,\n        parent._instance!.provides,\n      )\n    }\n  }\n\n  disconnectedCallback(): void {\n    this._connected = false\n    nextTick(() => {\n      if (!this._connected) {\n        if (this._ob) {\n          this._ob.disconnect()\n          this._ob = null\n        }\n        // unmount\n        this._app && this._app.unmount()\n        if (this._instance) this._instance.ce = undefined\n        this._app = this._instance = null\n        if (this._teleportTargets) {\n          this._teleportTargets.clear()\n          this._teleportTargets = undefined\n        }\n      }\n    })\n  }\n\n  private _processMutations(mutations: MutationRecord[]) {\n    for (const m of mutations) {\n      this._setAttr(m.attributeName!)\n    }\n  }\n\n  /**\n   * resolve inner component definition (handle possible async component)\n   */\n  private _resolveDef() {\n    if (this._pendingResolve) {\n      return\n    }\n\n    // set initial attrs\n    for (let i = 0; i < this.attributes.length; i++) {\n      this._setAttr(this.attributes[i].name)\n    }\n\n    // watch future attr changes\n    this._ob = new MutationObserver(this._processMutations.bind(this))\n\n    this._ob.observe(this, { attributes: true })\n\n    const resolve = (def: InnerComponentDef, isAsync = false) => {\n      this._resolved = true\n      this._pendingResolve = undefined\n\n      const { props, styles } = def\n\n      // cast Number-type props set before resolve\n      let numberProps\n      if (props && !isArray(props)) {\n        for (const key in props) {\n          const opt = props[key]\n          if (opt === Number || (opt && opt.type === Number)) {\n            if (key in this._props) {\n              this._props[key] = toNumber(this._props[key])\n            }\n            ;(numberProps || (numberProps = Object.create(null)))[\n              camelize(key)\n            ] = true\n          }\n        }\n      }\n      this._numberProps = numberProps\n      this._resolveProps(def)\n\n      // apply CSS\n      if (this.shadowRoot) {\n        this._applyStyles(styles)\n      } else if (__DEV__ && styles) {\n        warn(\n          'Custom element style injection is not supported when using ' +\n            'shadowRoot: false',\n        )\n      }\n\n      // initial mount\n      this._mount(def)\n    }\n\n    const asyncDef = (this._def as ComponentOptions).__asyncLoader\n    if (asyncDef) {\n      this._pendingResolve = asyncDef().then((def: InnerComponentDef) => {\n        def.configureApp = this._def.configureApp\n        resolve((this._def = def), true)\n      })\n    } else {\n      resolve(this._def)\n    }\n  }\n\n  private _mount(def: InnerComponentDef) {\n    if ((__DEV__ || __FEATURE_PROD_DEVTOOLS__) && !def.name) {\n      // @ts-expect-error\n      def.name = 'VueElement'\n    }\n    this._app = this._createApp(def)\n    // inherit before configureApp to detect context overwrites\n    this._inheritParentContext()\n    if (def.configureApp) {\n      def.configureApp(this._app)\n    }\n    this._app._ceVNode = this._createVNode()\n    this._app.mount(this._root)\n\n    // apply expose after mount\n    const exposed = this._instance && this._instance.exposed\n    if (!exposed) return\n    for (const key in exposed) {\n      if (!hasOwn(this, key)) {\n        // exposed properties are readonly\n        Object.defineProperty(this, key, {\n          // unwrap ref to be consistent with public instance behavior\n          get: () => unref(exposed[key]),\n        })\n      } else if (__DEV__) {\n        warn(`Exposed property \"${key}\" already exists on custom element.`)\n      }\n    }\n  }\n\n  private _resolveProps(def: InnerComponentDef) {\n    const { props } = def\n    const declaredPropKeys = isArray(props) ? props : Object.keys(props || {})\n\n    // check if there are props set pre-upgrade or connect\n    for (const key of Object.keys(this)) {\n      if (key[0] !== '_' && declaredPropKeys.includes(key)) {\n        this._setProp(key, this[key as keyof this])\n      }\n    }\n\n    // defining getter/setters on prototype\n    for (const key of declaredPropKeys.map(camelize)) {\n      Object.defineProperty(this, key, {\n        get(this: VueElement) {\n          return this._getProp(key)\n        },\n        set(this: VueElement, val) {\n          this._setProp(key, val, true, !this._patching)\n        },\n      })\n    }\n  }\n\n  protected _setAttr(key: string): void {\n    if (key.startsWith('data-v-')) return\n    const has = this.hasAttribute(key)\n    let value = has ? this.getAttribute(key) : REMOVAL\n    const camelKey = camelize(key)\n    if (has && this._numberProps && this._numberProps[camelKey]) {\n      value = toNumber(value)\n    }\n    this._setProp(camelKey, value, false, true)\n  }\n\n  /**\n   * @internal\n   */\n  protected _getProp(key: string): any {\n    return this._props[key]\n  }\n\n  /**\n   * @internal\n   */\n  _setProp(\n    key: string,\n    val: any,\n    shouldReflect = true,\n    shouldUpdate = false,\n  ): void {\n    if (val !== this._props[key]) {\n      this._dirty = true\n      if (val === REMOVAL) {\n        delete this._props[key]\n      } else {\n        this._props[key] = val\n        // support set key on ceVNode\n        if (key === 'key' && this._app) {\n          this._app._ceVNode!.key = val\n        }\n      }\n      if (shouldUpdate && this._instance) {\n        this._update()\n      }\n      // reflect\n      if (shouldReflect) {\n        const ob = this._ob\n        if (ob) {\n          this._processMutations(ob.takeRecords())\n          ob.disconnect()\n        }\n        if (val === true) {\n          this.setAttribute(hyphenate(key), '')\n        } else if (typeof val === 'string' || typeof val === 'number') {\n          this.setAttribute(hyphenate(key), val + '')\n        } else if (!val) {\n          this.removeAttribute(hyphenate(key))\n        }\n        ob && ob.observe(this, { attributes: true })\n      }\n    }\n  }\n\n  private _update() {\n    const vnode = this._createVNode()\n    if (this._app) vnode.appContext = this._app._context\n    render(vnode, this._root)\n  }\n\n  private _createVNode(): VNode<any, any> {\n    const baseProps: VNodeProps = {}\n    if (!this.shadowRoot) {\n      baseProps.onVnodeMounted = baseProps.onVnodeUpdated =\n        this._renderSlots.bind(this)\n    }\n    const vnode = createVNode(this._def, extend(baseProps, this._props))\n    if (!this._instance) {\n      vnode.ce = instance => {\n        this._instance = instance\n        instance.ce = this\n        instance.isCE = true // for vue-i18n backwards compat\n        // HMR\n        if (__DEV__) {\n          instance.ceReload = newStyles => {\n            // always reset styles\n            if (this._styles) {\n              this._styles.forEach(s => this._root.removeChild(s))\n              this._styles.length = 0\n            }\n            this._styleAnchors.delete(this._def)\n            this._applyStyles(newStyles)\n            this._instance = null\n            this._update()\n          }\n        }\n\n        const dispatch = (event: string, args: any[]) => {\n          this.dispatchEvent(\n            new CustomEvent(\n              event,\n              isPlainObject(args[0])\n                ? extend({ detail: args }, args[0])\n                : { detail: args },\n            ),\n          )\n        }\n\n        // intercept emit\n        instance.emit = (event: string, ...args: any[]) => {\n          // dispatch both the raw and hyphenated versions of an event\n          // to match Vue behavior\n          dispatch(event, args)\n          if (hyphenate(event) !== event) {\n            dispatch(hyphenate(event), args)\n          }\n        }\n\n        this._setParent()\n      }\n    }\n    return vnode\n  }\n\n  private _applyStyles(\n    styles: string[] | undefined,\n    owner?: ConcreteComponent,\n    parentComp?: ConcreteComponent,\n  ) {\n    if (!styles) return\n    if (owner) {\n      if (owner === this._def || this._styleChildren.has(owner)) {\n        return\n      }\n      this._styleChildren.add(owner)\n    }\n\n    const nonce = this._nonce\n    const root = this.shadowRoot!\n    const insertionAnchor = parentComp\n      ? this._getStyleAnchor(parentComp) || this._getStyleAnchor(this._def)\n      : this._getRootStyleInsertionAnchor(root)\n    let last: HTMLStyleElement | null = null\n    for (let i = styles.length - 1; i >= 0; i--) {\n      const s = document.createElement('style')\n      if (nonce) s.setAttribute('nonce', nonce)\n      s.textContent = styles[i]\n\n      root.insertBefore(s, last || insertionAnchor)\n      last = s\n      if (i === 0) {\n        if (!parentComp) this._styleAnchors.set(this._def, s)\n        if (owner) this._styleAnchors.set(owner, s)\n      }\n\n      // record for HMR\n      if (__DEV__) {\n        if (owner) {\n          if (owner.__hmrId) {\n            if (!this._childStyles) this._childStyles = new Map()\n            let entry = this._childStyles.get(owner.__hmrId)\n            if (!entry) {\n              this._childStyles.set(owner.__hmrId, (entry = []))\n            }\n            entry.push(s)\n          }\n        } else {\n          ;(this._styles || (this._styles = [])).push(s)\n        }\n      }\n    }\n  }\n\n  private _getStyleAnchor(comp?: ConcreteComponent): HTMLStyleElement | null {\n    if (!comp) {\n      return null\n    }\n    const anchor = this._styleAnchors.get(comp)\n    if (anchor && anchor.parentNode === this.shadowRoot) {\n      return anchor\n    }\n    if (anchor) {\n      this._styleAnchors.delete(comp)\n    }\n    return null\n  }\n\n  private _getRootStyleInsertionAnchor(root: ShadowRoot): ChildNode | null {\n    for (let i = 0; i < root.childNodes.length; i++) {\n      const node = root.childNodes[i]\n      if (!(node instanceof HTMLStyleElement)) {\n        return node\n      }\n    }\n    return null\n  }\n\n  /**\n   * Only called when shadowRoot is false\n   */\n  private _parseSlots() {\n    const slots: VueElement['_slots'] = (this._slots = {})\n    let n\n    while ((n = this.firstChild)) {\n      const slotName =\n        (n.nodeType === 1 && (n as Element).getAttribute('slot')) || 'default'\n      ;(slots[slotName] || (slots[slotName] = [])).push(n)\n      this.removeChild(n)\n    }\n  }\n\n  /**\n   * Only called when shadowRoot is false\n   */\n  private _renderSlots() {\n    const outlets = this._getSlots()\n    const scopeId = this._instance!.type.__scopeId\n    for (let i = 0; i < outlets.length; i++) {\n      const o = outlets[i] as HTMLSlotElement\n      const slotName = o.getAttribute('name') || 'default'\n      const content = this._slots![slotName]\n      const parent = o.parentNode!\n      if (content) {\n        for (const n of content) {\n          // for :slotted css\n          if (scopeId && n.nodeType === 1) {\n            const id = scopeId + '-s'\n            const walker = document.createTreeWalker(n, 1)\n            ;(n as Element).setAttribute(id, '')\n            let child\n            while ((child = walker.nextNode())) {\n              ;(child as Element).setAttribute(id, '')\n            }\n          }\n          parent.insertBefore(n, o)\n        }\n      } else {\n        while (o.firstChild) parent.insertBefore(o.firstChild, o)\n      }\n      parent.removeChild(o)\n    }\n  }\n\n  /**\n   * @internal\n   */\n  private _getSlots(): HTMLSlotElement[] {\n    const roots: Element[] = [this]\n    if (this._teleportTargets) {\n      roots.push(...this._teleportTargets)\n    }\n\n    const slots = new Set<HTMLSlotElement>()\n    for (const root of roots) {\n      const found = root.querySelectorAll<HTMLSlotElement>('slot')\n      for (let i = 0; i < found.length; i++) {\n        slots.add(found[i])\n      }\n    }\n\n    return Array.from(slots)\n  }\n\n  /**\n   * @internal\n   */\n  _injectChildStyle(\n    comp: ConcreteComponent & CustomElementOptions,\n    parentComp?: ConcreteComponent,\n  ): void {\n    this._applyStyles(comp.styles, comp, parentComp)\n  }\n\n  /**\n   * @internal\n   */\n  _beginPatch(): void {\n    this._patching = true\n    this._dirty = false\n  }\n\n  /**\n   * @internal\n   */\n  _endPatch(): void {\n    this._patching = false\n    if (this._dirty && this._instance) {\n      this._update()\n    }\n  }\n\n  /**\n   * @internal\n   */\n  _hasShadowRoot(): boolean {\n    return this._def.shadowRoot !== false\n  }\n\n  /**\n   * @internal\n   */\n  _removeChildStyle(comp: ConcreteComponent): void {\n    if (__DEV__) {\n      this._styleChildren.delete(comp)\n      this._styleAnchors.delete(comp)\n      if (this._childStyles && comp.__hmrId) {\n        // clear old styles\n        const oldStyles = this._childStyles.get(comp.__hmrId)\n        if (oldStyles) {\n          oldStyles.forEach(s => this._root.removeChild(s))\n          oldStyles.length = 0\n        }\n      }\n    }\n  }\n}\n\nexport function useHost(caller?: string): VueElement | null {\n  const instance = getCurrentInstance()\n  const el = instance && (instance.ce as VueElement)\n  if (el) {\n    return el\n  } else if (__DEV__) {\n    if (!instance) {\n      warn(\n        `${caller || 'useHost'} called without an active component instance.`,\n      )\n    } else {\n      warn(\n        `${caller || 'useHost'} can only be used in components defined via ` +\n          `defineCustomElement.`,\n      )\n    }\n  }\n  return null\n}\n\n/**\n * Retrieve the shadowRoot of the current custom element. Only usable in setup()\n * of a `defineCustomElement` component.\n */\nexport function useShadowRoot(): ShadowRoot | null {\n  const el = __DEV__ ? useHost('useShadowRoot') : useHost()\n  return el && el.shadowRoot\n}\n"
  },
  {
    "path": "packages/runtime-dom/src/components/Transition.ts",
    "content": "import {\n  BaseTransition,\n  type BaseTransitionProps,\n  BaseTransitionPropsValidators,\n  DeprecationTypes,\n  type FunctionalComponent,\n  assertNumber,\n  compatUtils,\n  h,\n} from '@vue/runtime-core'\nimport { extend, isArray, isObject, toNumber } from '@vue/shared'\n\nconst TRANSITION = 'transition'\nconst ANIMATION = 'animation'\n\ntype AnimationTypes = typeof TRANSITION | typeof ANIMATION\n\nexport interface TransitionProps extends BaseTransitionProps<Element> {\n  name?: string\n  type?: AnimationTypes\n  css?: boolean\n  duration?: number | { enter: number; leave: number }\n  // custom transition classes\n  enterFromClass?: string\n  enterActiveClass?: string\n  enterToClass?: string\n  appearFromClass?: string\n  appearActiveClass?: string\n  appearToClass?: string\n  leaveFromClass?: string\n  leaveActiveClass?: string\n  leaveToClass?: string\n}\n\nexport const vtcKey: unique symbol = Symbol('_vtc')\n\nexport interface ElementWithTransition extends HTMLElement {\n  // _vtc = Vue Transition Classes.\n  // Store the temporarily-added transition classes on the element\n  // so that we can avoid overwriting them if the element's class is patched\n  // during the transition.\n  [vtcKey]?: Set<string>\n}\n\nconst DOMTransitionPropsValidators = {\n  name: String,\n  type: String,\n  css: {\n    type: Boolean,\n    default: true,\n  },\n  duration: [String, Number, Object],\n  enterFromClass: String,\n  enterActiveClass: String,\n  enterToClass: String,\n  appearFromClass: String,\n  appearActiveClass: String,\n  appearToClass: String,\n  leaveFromClass: String,\n  leaveActiveClass: String,\n  leaveToClass: String,\n}\n\nexport const TransitionPropsValidators: any = /*@__PURE__*/ extend(\n  {},\n  BaseTransitionPropsValidators as any,\n  DOMTransitionPropsValidators,\n)\n\n/**\n * Wrap logic that attaches extra properties to Transition in a function\n * so that it can be annotated as pure\n */\nconst decorate = (t: typeof Transition) => {\n  t.displayName = 'Transition'\n  t.props = TransitionPropsValidators\n  if (__COMPAT__) {\n    t.__isBuiltIn = true\n  }\n  return t\n}\n\n/**\n * DOM Transition is a higher-order-component based on the platform-agnostic\n * base Transition component, with DOM-specific logic.\n */\nexport const Transition: FunctionalComponent<TransitionProps> =\n  /*@__PURE__*/ decorate((props, { slots }) =>\n    h(BaseTransition, resolveTransitionProps(props), slots),\n  )\n\n/**\n * #3227 Incoming hooks may be merged into arrays when wrapping Transition\n * with custom HOCs.\n */\nconst callHook = (\n  hook: Function | Function[] | undefined,\n  args: any[] = [],\n) => {\n  if (isArray(hook)) {\n    hook.forEach(h => h(...args))\n  } else if (hook) {\n    hook(...args)\n  }\n}\n\n/**\n * Check if a hook expects a callback (2nd arg), which means the user\n * intends to explicitly control the end of the transition.\n */\nconst hasExplicitCallback = (\n  hook: Function | Function[] | undefined,\n): boolean => {\n  return hook\n    ? isArray(hook)\n      ? hook.some(h => h.length > 1)\n      : hook.length > 1\n    : false\n}\n\nexport function resolveTransitionProps(\n  rawProps: TransitionProps,\n): BaseTransitionProps<Element> {\n  const baseProps: BaseTransitionProps<Element> = {}\n  for (const key in rawProps) {\n    if (!(key in DOMTransitionPropsValidators)) {\n      ;(baseProps as any)[key] = (rawProps as any)[key]\n    }\n  }\n\n  if (rawProps.css === false) {\n    return baseProps\n  }\n\n  const {\n    name = 'v',\n    type,\n    duration,\n    enterFromClass = `${name}-enter-from`,\n    enterActiveClass = `${name}-enter-active`,\n    enterToClass = `${name}-enter-to`,\n    appearFromClass = enterFromClass,\n    appearActiveClass = enterActiveClass,\n    appearToClass = enterToClass,\n    leaveFromClass = `${name}-leave-from`,\n    leaveActiveClass = `${name}-leave-active`,\n    leaveToClass = `${name}-leave-to`,\n  } = rawProps\n\n  // legacy transition class compat\n  const legacyClassEnabled =\n    __COMPAT__ &&\n    compatUtils.isCompatEnabled(DeprecationTypes.TRANSITION_CLASSES, null)\n  let legacyEnterFromClass: string\n  let legacyAppearFromClass: string\n  let legacyLeaveFromClass: string\n  if (__COMPAT__ && legacyClassEnabled) {\n    const toLegacyClass = (cls: string) => cls.replace(/-from$/, '')\n    if (!rawProps.enterFromClass) {\n      legacyEnterFromClass = toLegacyClass(enterFromClass)\n    }\n    if (!rawProps.appearFromClass) {\n      legacyAppearFromClass = toLegacyClass(appearFromClass)\n    }\n    if (!rawProps.leaveFromClass) {\n      legacyLeaveFromClass = toLegacyClass(leaveFromClass)\n    }\n  }\n\n  const durations = normalizeDuration(duration)\n  const enterDuration = durations && durations[0]\n  const leaveDuration = durations && durations[1]\n  const {\n    onBeforeEnter,\n    onEnter,\n    onEnterCancelled,\n    onLeave,\n    onLeaveCancelled,\n    onBeforeAppear = onBeforeEnter,\n    onAppear = onEnter,\n    onAppearCancelled = onEnterCancelled,\n  } = baseProps\n\n  const finishEnter = (\n    el: Element & { _enterCancelled?: boolean },\n    isAppear: boolean,\n    done?: () => void,\n    isCancelled?: boolean,\n  ) => {\n    el._enterCancelled = isCancelled\n    removeTransitionClass(el, isAppear ? appearToClass : enterToClass)\n    removeTransitionClass(el, isAppear ? appearActiveClass : enterActiveClass)\n    done && done()\n  }\n\n  const finishLeave = (\n    el: Element & { _isLeaving?: boolean },\n    done?: () => void,\n  ) => {\n    el._isLeaving = false\n    removeTransitionClass(el, leaveFromClass)\n    removeTransitionClass(el, leaveToClass)\n    removeTransitionClass(el, leaveActiveClass)\n    done && done()\n  }\n\n  const makeEnterHook = (isAppear: boolean) => {\n    return (el: Element, done: () => void) => {\n      const hook = isAppear ? onAppear : onEnter\n      const resolve = () => finishEnter(el, isAppear, done)\n      callHook(hook, [el, resolve])\n      nextFrame(() => {\n        removeTransitionClass(el, isAppear ? appearFromClass : enterFromClass)\n        if (__COMPAT__ && legacyClassEnabled) {\n          const legacyClass = isAppear\n            ? legacyAppearFromClass\n            : legacyEnterFromClass\n          if (legacyClass) {\n            removeTransitionClass(el, legacyClass)\n          }\n        }\n        addTransitionClass(el, isAppear ? appearToClass : enterToClass)\n        if (!hasExplicitCallback(hook)) {\n          whenTransitionEnds(el, type, enterDuration, resolve)\n        }\n      })\n    }\n  }\n\n  return extend(baseProps, {\n    onBeforeEnter(el) {\n      callHook(onBeforeEnter, [el])\n      addTransitionClass(el, enterFromClass)\n      if (__COMPAT__ && legacyClassEnabled && legacyEnterFromClass) {\n        addTransitionClass(el, legacyEnterFromClass)\n      }\n      addTransitionClass(el, enterActiveClass)\n    },\n    onBeforeAppear(el) {\n      callHook(onBeforeAppear, [el])\n      addTransitionClass(el, appearFromClass)\n      if (__COMPAT__ && legacyClassEnabled && legacyAppearFromClass) {\n        addTransitionClass(el, legacyAppearFromClass)\n      }\n      addTransitionClass(el, appearActiveClass)\n    },\n    onEnter: makeEnterHook(false),\n    onAppear: makeEnterHook(true),\n    onLeave(\n      el: Element & { _isLeaving?: boolean; _enterCancelled?: boolean },\n      done,\n    ) {\n      el._isLeaving = true\n      const resolve = () => finishLeave(el, done)\n      addTransitionClass(el, leaveFromClass)\n      if (__COMPAT__ && legacyClassEnabled && legacyLeaveFromClass) {\n        addTransitionClass(el, legacyLeaveFromClass)\n      }\n      // add *-leave-active class before reflow so in the case of a cancelled enter transition\n      // the css will not get the final state (#10677)\n      if (!el._enterCancelled) {\n        // force reflow so *-leave-from classes immediately take effect (#2593)\n        forceReflow(el)\n        addTransitionClass(el, leaveActiveClass)\n      } else {\n        addTransitionClass(el, leaveActiveClass)\n        forceReflow(el)\n      }\n      nextFrame(() => {\n        if (!el._isLeaving) {\n          // cancelled\n          return\n        }\n        removeTransitionClass(el, leaveFromClass)\n        if (__COMPAT__ && legacyClassEnabled && legacyLeaveFromClass) {\n          removeTransitionClass(el, legacyLeaveFromClass)\n        }\n        addTransitionClass(el, leaveToClass)\n        if (!hasExplicitCallback(onLeave)) {\n          whenTransitionEnds(el, type, leaveDuration, resolve)\n        }\n      })\n      callHook(onLeave, [el, resolve])\n    },\n    onEnterCancelled(el) {\n      finishEnter(el, false, undefined, true)\n      callHook(onEnterCancelled, [el])\n    },\n    onAppearCancelled(el) {\n      finishEnter(el, true, undefined, true)\n      callHook(onAppearCancelled, [el])\n    },\n    onLeaveCancelled(el) {\n      finishLeave(el)\n      callHook(onLeaveCancelled, [el])\n    },\n  } as BaseTransitionProps<Element>)\n}\n\nfunction normalizeDuration(\n  duration: TransitionProps['duration'],\n): [number, number] | null {\n  if (duration == null) {\n    return null\n  } else if (isObject(duration)) {\n    return [NumberOf(duration.enter), NumberOf(duration.leave)]\n  } else {\n    const n = NumberOf(duration)\n    return [n, n]\n  }\n}\n\nfunction NumberOf(val: unknown): number {\n  const res = toNumber(val)\n  if (__DEV__) {\n    assertNumber(res, '<transition> explicit duration')\n  }\n  return res\n}\n\nexport function addTransitionClass(el: Element, cls: string): void {\n  cls.split(/\\s+/).forEach(c => c && el.classList.add(c))\n  ;(\n    (el as ElementWithTransition)[vtcKey] ||\n    ((el as ElementWithTransition)[vtcKey] = new Set())\n  ).add(cls)\n}\n\nexport function removeTransitionClass(el: Element, cls: string): void {\n  cls.split(/\\s+/).forEach(c => c && el.classList.remove(c))\n  const _vtc = (el as ElementWithTransition)[vtcKey]\n  if (_vtc) {\n    _vtc.delete(cls)\n    if (!_vtc!.size) {\n      ;(el as ElementWithTransition)[vtcKey] = undefined\n    }\n  }\n}\n\nfunction nextFrame(cb: () => void) {\n  requestAnimationFrame(() => {\n    requestAnimationFrame(cb)\n  })\n}\n\nlet endId = 0\n\nfunction whenTransitionEnds(\n  el: Element & { _endId?: number },\n  expectedType: TransitionProps['type'] | undefined,\n  explicitTimeout: number | null,\n  resolve: () => void,\n) {\n  const id = (el._endId = ++endId)\n  const resolveIfNotStale = () => {\n    if (id === el._endId) {\n      resolve()\n    }\n  }\n\n  if (explicitTimeout != null) {\n    return setTimeout(resolveIfNotStale, explicitTimeout)\n  }\n\n  const { type, timeout, propCount } = getTransitionInfo(el, expectedType)\n  if (!type) {\n    return resolve()\n  }\n\n  const endEvent = type + 'end'\n  let ended = 0\n  const end = () => {\n    el.removeEventListener(endEvent, onEnd)\n    resolveIfNotStale()\n  }\n  const onEnd = (e: Event) => {\n    if (e.target === el && ++ended >= propCount) {\n      end()\n    }\n  }\n  setTimeout(() => {\n    if (ended < propCount) {\n      end()\n    }\n  }, timeout + 1)\n  el.addEventListener(endEvent, onEnd)\n}\n\ninterface CSSTransitionInfo {\n  type: AnimationTypes | null\n  propCount: number\n  timeout: number\n  hasTransform: boolean\n}\n\ntype AnimationProperties = 'Delay' | 'Duration'\ntype StylePropertiesKey =\n  | `${AnimationTypes}${AnimationProperties}`\n  | `${typeof TRANSITION}Property`\n\nexport function getTransitionInfo(\n  el: Element,\n  expectedType?: TransitionProps['type'],\n): CSSTransitionInfo {\n  const styles = window.getComputedStyle(el) as Pick<\n    CSSStyleDeclaration,\n    StylePropertiesKey\n  >\n  // JSDOM may return undefined for transition properties\n  const getStyleProperties = (key: StylePropertiesKey) =>\n    (styles[key] || '').split(', ')\n  const transitionDelays = getStyleProperties(`${TRANSITION}Delay`)\n  const transitionDurations = getStyleProperties(`${TRANSITION}Duration`)\n  const transitionTimeout = getTimeout(transitionDelays, transitionDurations)\n  const animationDelays = getStyleProperties(`${ANIMATION}Delay`)\n  const animationDurations = getStyleProperties(`${ANIMATION}Duration`)\n  const animationTimeout = getTimeout(animationDelays, animationDurations)\n\n  let type: CSSTransitionInfo['type'] = null\n  let timeout = 0\n  let propCount = 0\n  if (expectedType === TRANSITION) {\n    if (transitionTimeout > 0) {\n      type = TRANSITION\n      timeout = transitionTimeout\n      propCount = transitionDurations.length\n    }\n  } else if (expectedType === ANIMATION) {\n    if (animationTimeout > 0) {\n      type = ANIMATION\n      timeout = animationTimeout\n      propCount = animationDurations.length\n    }\n  } else {\n    timeout = Math.max(transitionTimeout, animationTimeout)\n    type =\n      timeout > 0\n        ? transitionTimeout > animationTimeout\n          ? TRANSITION\n          : ANIMATION\n        : null\n    propCount = type\n      ? type === TRANSITION\n        ? transitionDurations.length\n        : animationDurations.length\n      : 0\n  }\n  const hasTransform =\n    type === TRANSITION &&\n    /\\b(?:transform|all)(?:,|$)/.test(\n      getStyleProperties(`${TRANSITION}Property`).toString(),\n    )\n  return {\n    type,\n    timeout,\n    propCount,\n    hasTransform,\n  }\n}\n\nfunction getTimeout(delays: string[], durations: string[]): number {\n  while (delays.length < durations.length) {\n    delays = delays.concat(delays)\n  }\n  return Math.max(...durations.map((d, i) => toMs(d) + toMs(delays[i])))\n}\n\n// Old versions of Chromium (below 61.0.3163.100) formats floating pointer\n// numbers in a locale-dependent way, using a comma instead of a dot.\n// If comma is not replaced with a dot, the input will be rounded down\n// (i.e. acting as a floor function) causing unexpected behaviors\nfunction toMs(s: string): number {\n  // #8409 default value for CSS durations can be 'auto'\n  if (s === 'auto') return 0\n  return Number(s.slice(0, -1).replace(',', '.')) * 1000\n}\n\n// synchronously force layout to put elements into a certain state\nexport function forceReflow(el?: Node): number {\n  const targetDocument = el ? el.ownerDocument! : document\n  return targetDocument.body.offsetHeight\n}\n"
  },
  {
    "path": "packages/runtime-dom/src/components/TransitionGroup.ts",
    "content": "import {\n  type ElementWithTransition,\n  type TransitionProps,\n  TransitionPropsValidators,\n  addTransitionClass,\n  forceReflow,\n  getTransitionInfo,\n  removeTransitionClass,\n  resolveTransitionProps,\n  vtcKey,\n} from './Transition'\nimport {\n  type ComponentOptions,\n  DeprecationTypes,\n  Fragment,\n  type SetupContext,\n  Text,\n  type VNode,\n  compatUtils,\n  createVNode,\n  getCurrentInstance,\n  getTransitionRawChildren,\n  onUpdated,\n  resolveTransitionHooks,\n  setTransitionHooks,\n  toRaw,\n  useTransitionState,\n  warn,\n} from '@vue/runtime-core'\nimport { extend } from '@vue/shared'\n\ninterface Position {\n  top: number\n  left: number\n}\n\nconst positionMap = new WeakMap<VNode, Position>()\nconst newPositionMap = new WeakMap<VNode, Position>()\nconst moveCbKey = Symbol('_moveCb')\nconst enterCbKey = Symbol('_enterCb')\n\nexport type TransitionGroupProps = Omit<TransitionProps, 'mode'> & {\n  tag?: string\n  moveClass?: string\n}\n\n/**\n * Wrap logic that modifies TransitionGroup properties in a function\n * so that it can be annotated as pure\n */\nconst decorate = (t: typeof TransitionGroupImpl) => {\n  // TransitionGroup does not support \"mode\" so we need to remove it from the\n  // props declarations, but direct delete operation is considered a side effect\n  delete t.props.mode\n  if (__COMPAT__) {\n    t.__isBuiltIn = true\n  }\n  return t\n}\n\nconst TransitionGroupImpl: ComponentOptions = /*@__PURE__*/ decorate({\n  name: 'TransitionGroup',\n\n  props: /*@__PURE__*/ extend({}, TransitionPropsValidators, {\n    tag: String,\n    moveClass: String,\n  }),\n\n  setup(props: TransitionGroupProps, { slots }: SetupContext) {\n    const instance = getCurrentInstance()!\n    const state = useTransitionState()\n    let prevChildren: VNode[]\n    let children: VNode[]\n\n    onUpdated(() => {\n      // children is guaranteed to exist after initial render\n      if (!prevChildren.length) {\n        return\n      }\n      const moveClass = props.moveClass || `${props.name || 'v'}-move`\n\n      if (\n        !hasCSSTransform(\n          prevChildren[0].el as ElementWithTransition,\n          instance.vnode.el as Node,\n          moveClass,\n        )\n      ) {\n        prevChildren = []\n        return\n      }\n\n      // we divide the work into three loops to avoid mixing DOM reads and writes\n      // in each iteration - which helps prevent layout thrashing.\n      prevChildren.forEach(callPendingCbs)\n      prevChildren.forEach(recordPosition)\n      const movedChildren = prevChildren.filter(applyTranslation)\n\n      // force reflow to put everything in position\n      forceReflow(instance.vnode.el as Node)\n\n      movedChildren.forEach(c => {\n        const el = c.el as ElementWithTransition\n        const style = el.style\n        addTransitionClass(el, moveClass)\n        style.transform = style.webkitTransform = style.transitionDuration = ''\n        const cb = ((el as any)[moveCbKey] = (e: TransitionEvent) => {\n          if (e && e.target !== el) {\n            return\n          }\n          if (!e || e.propertyName.endsWith('transform')) {\n            el.removeEventListener('transitionend', cb)\n            ;(el as any)[moveCbKey] = null\n            removeTransitionClass(el, moveClass)\n          }\n        })\n        el.addEventListener('transitionend', cb)\n      })\n      prevChildren = []\n    })\n\n    return () => {\n      const rawProps = toRaw(props)\n      const cssTransitionProps = resolveTransitionProps(rawProps)\n      let tag = rawProps.tag || Fragment\n\n      if (\n        __COMPAT__ &&\n        !rawProps.tag &&\n        compatUtils.checkCompatEnabled(\n          DeprecationTypes.TRANSITION_GROUP_ROOT,\n          instance.parent,\n        )\n      ) {\n        tag = 'span'\n      }\n\n      prevChildren = []\n      if (children) {\n        for (let i = 0; i < children.length; i++) {\n          const child = children[i]\n          if (child.el && child.el instanceof Element) {\n            prevChildren.push(child)\n            setTransitionHooks(\n              child,\n              resolveTransitionHooks(\n                child,\n                cssTransitionProps,\n                state,\n                instance,\n              ),\n            )\n            positionMap.set(child, getPosition(child.el as HTMLElement))\n          }\n        }\n      }\n\n      children = slots.default ? getTransitionRawChildren(slots.default()) : []\n\n      for (let i = 0; i < children.length; i++) {\n        const child = children[i]\n        if (child.key != null) {\n          setTransitionHooks(\n            child,\n            resolveTransitionHooks(child, cssTransitionProps, state, instance),\n          )\n        } else if (__DEV__ && child.type !== Text) {\n          warn(`<TransitionGroup> children must be keyed.`)\n        }\n      }\n\n      return createVNode(tag, null, children)\n    }\n  },\n})\n\nexport const TransitionGroup = TransitionGroupImpl as unknown as {\n  new (): {\n    $props: TransitionGroupProps\n  }\n}\n\nfunction callPendingCbs(c: VNode) {\n  const el = c.el as any\n  if (el[moveCbKey]) {\n    el[moveCbKey]()\n  }\n  if (el[enterCbKey]) {\n    el[enterCbKey]()\n  }\n}\n\nfunction recordPosition(c: VNode) {\n  newPositionMap.set(c, getPosition(c.el as HTMLElement))\n}\n\nfunction applyTranslation(c: VNode): VNode | undefined {\n  const oldPos = positionMap.get(c)!\n  const newPos = newPositionMap.get(c)!\n  const dx = oldPos.left - newPos.left\n  const dy = oldPos.top - newPos.top\n  if (dx || dy) {\n    const el = c.el as HTMLElement\n    const s = el.style\n    const rect = el.getBoundingClientRect()\n    let scaleX = 1\n    let scaleY = 1\n    if (el.offsetWidth) scaleX = rect.width / el.offsetWidth\n    if (el.offsetHeight) scaleY = rect.height / el.offsetHeight\n    if (!Number.isFinite(scaleX) || scaleX === 0) scaleX = 1\n    if (!Number.isFinite(scaleY) || scaleY === 0) scaleY = 1\n    // Avoid division noise when scale is effectively 1.\n    if (Math.abs(scaleX - 1) < 0.01) scaleX = 1\n    if (Math.abs(scaleY - 1) < 0.01) scaleY = 1\n    s.transform = s.webkitTransform = `translate(${dx / scaleX}px,${\n      dy / scaleY\n    }px)`\n    s.transitionDuration = '0s'\n    return c\n  }\n}\n\nfunction getPosition(el: HTMLElement): Position {\n  const rect = el.getBoundingClientRect()\n  return {\n    left: rect.left,\n    top: rect.top,\n  }\n}\n\nfunction hasCSSTransform(\n  el: ElementWithTransition,\n  root: Node,\n  moveClass: string,\n): boolean {\n  // Detect whether an element with the move class applied has\n  // CSS transitions. Since the element may be inside an entering\n  // transition at this very moment, we make a clone of it and remove\n  // all other transition classes applied to ensure only the move class\n  // is applied.\n  const clone = el.cloneNode() as HTMLElement\n  const _vtc = el[vtcKey]\n  if (_vtc) {\n    _vtc.forEach(cls => {\n      cls.split(/\\s+/).forEach(c => c && clone.classList.remove(c))\n    })\n  }\n  moveClass.split(/\\s+/).forEach(c => c && clone.classList.add(c))\n  clone.style.display = 'none'\n  const container = (\n    root.nodeType === 1 ? root : root.parentNode\n  ) as HTMLElement\n  container.appendChild(clone)\n  const { hasTransform } = getTransitionInfo(clone)\n  container.removeChild(clone)\n  return hasTransform\n}\n"
  },
  {
    "path": "packages/runtime-dom/src/directives/vModel.ts",
    "content": "import {\n  type DirectiveBinding,\n  type DirectiveHook,\n  type ObjectDirective,\n  type VNode,\n  nextTick,\n  warn,\n} from '@vue/runtime-core'\nimport { addEventListener } from '../modules/events'\nimport {\n  invokeArrayFns,\n  isArray,\n  isSet,\n  looseEqual,\n  looseIndexOf,\n  looseToNumber,\n} from '@vue/shared'\n\ntype AssignerFn = (value: any) => void\n\nconst getModelAssigner = (vnode: VNode): AssignerFn => {\n  const fn =\n    vnode.props!['onUpdate:modelValue'] ||\n    (__COMPAT__ && vnode.props!['onModelCompat:input'])\n  return isArray(fn) ? value => invokeArrayFns(fn, value) : fn\n}\n\nfunction onCompositionStart(e: Event) {\n  ;(e.target as any).composing = true\n}\n\nfunction onCompositionEnd(e: Event) {\n  const target = e.target as any\n  if (target.composing) {\n    target.composing = false\n    target.dispatchEvent(new Event('input'))\n  }\n}\n\nconst assignKey: unique symbol = Symbol('_assign')\n\ntype ModelDirective<T, Modifiers extends string = string> = ObjectDirective<\n  T & { [assignKey]: AssignerFn; _assigning?: boolean },\n  any,\n  Modifiers\n>\n\nfunction castValue(value: string, trim?: boolean, number?: boolean | null) {\n  if (trim) value = value.trim()\n  if (number) value = looseToNumber(value)\n  return value\n}\n\n// We are exporting the v-model runtime directly as vnode hooks so that it can\n// be tree-shaken in case v-model is never used.\nexport const vModelText: ModelDirective<\n  HTMLInputElement | HTMLTextAreaElement,\n  'trim' | 'number' | 'lazy'\n> = {\n  created(el, { modifiers: { lazy, trim, number } }, vnode) {\n    el[assignKey] = getModelAssigner(vnode)\n    const castToNumber =\n      number || (vnode.props && vnode.props.type === 'number')\n    addEventListener(el, lazy ? 'change' : 'input', e => {\n      if ((e.target as any).composing) return\n      el[assignKey](castValue(el.value, trim, castToNumber))\n    })\n    if (trim || castToNumber) {\n      addEventListener(el, 'change', () => {\n        el.value = castValue(el.value, trim, castToNumber)\n      })\n    }\n    if (!lazy) {\n      addEventListener(el, 'compositionstart', onCompositionStart)\n      addEventListener(el, 'compositionend', onCompositionEnd)\n      // Safari < 10.2 & UIWebView doesn't fire compositionend when\n      // switching focus before confirming composition choice\n      // this also fixes the issue where some browsers e.g. iOS Chrome\n      // fires \"change\" instead of \"input\" on autocomplete.\n      addEventListener(el, 'change', onCompositionEnd)\n    }\n  },\n  // set value on mounted so it's after min/max for type=\"range\"\n  mounted(el, { value }) {\n    el.value = value == null ? '' : value\n  },\n  beforeUpdate(\n    el,\n    { value, oldValue, modifiers: { lazy, trim, number } },\n    vnode,\n  ) {\n    el[assignKey] = getModelAssigner(vnode)\n    // avoid clearing unresolved text. #2302\n    if ((el as any).composing) return\n    const elValue =\n      (number || el.type === 'number') && !/^0\\d/.test(el.value)\n        ? looseToNumber(el.value)\n        : el.value\n    const newValue = value == null ? '' : value\n\n    if (elValue === newValue) {\n      return\n    }\n\n    if (document.activeElement === el && el.type !== 'range') {\n      // #8546\n      if (lazy && value === oldValue) {\n        return\n      }\n      if (trim && el.value.trim() === newValue) {\n        return\n      }\n    }\n\n    el.value = newValue\n  },\n}\n\nexport const vModelCheckbox: ModelDirective<HTMLInputElement> = {\n  // #4096 array checkboxes need to be deep traversed\n  deep: true,\n  created(el, _, vnode) {\n    el[assignKey] = getModelAssigner(vnode)\n    addEventListener(el, 'change', () => {\n      const modelValue = (el as any)._modelValue\n      const elementValue = getValue(el)\n      const checked = el.checked\n      const assign = el[assignKey]\n      if (isArray(modelValue)) {\n        const index = looseIndexOf(modelValue, elementValue)\n        const found = index !== -1\n        if (checked && !found) {\n          assign(modelValue.concat(elementValue))\n        } else if (!checked && found) {\n          const filtered = [...modelValue]\n          filtered.splice(index, 1)\n          assign(filtered)\n        }\n      } else if (isSet(modelValue)) {\n        const cloned = new Set(modelValue)\n        if (checked) {\n          cloned.add(elementValue)\n        } else {\n          cloned.delete(elementValue)\n        }\n        assign(cloned)\n      } else {\n        assign(getCheckboxValue(el, checked))\n      }\n    })\n  },\n  // set initial checked on mount to wait for true-value/false-value\n  mounted: setChecked,\n  beforeUpdate(el, binding, vnode) {\n    el[assignKey] = getModelAssigner(vnode)\n    setChecked(el, binding, vnode)\n  },\n}\n\nfunction setChecked(\n  el: HTMLInputElement,\n  { value, oldValue }: DirectiveBinding,\n  vnode: VNode,\n) {\n  // store the v-model value on the element so it can be accessed by the\n  // change listener.\n  ;(el as any)._modelValue = value\n  let checked: boolean\n\n  if (isArray(value)) {\n    checked = looseIndexOf(value, vnode.props!.value) > -1\n  } else if (isSet(value)) {\n    checked = value.has(vnode.props!.value)\n  } else {\n    if (value === oldValue) return\n    checked = looseEqual(value, getCheckboxValue(el, true))\n  }\n\n  // Only update if the checked state has changed\n  if (el.checked !== checked) {\n    el.checked = checked\n  }\n}\n\nexport const vModelRadio: ModelDirective<HTMLInputElement> = {\n  created(el, { value }, vnode) {\n    el.checked = looseEqual(value, vnode.props!.value)\n    el[assignKey] = getModelAssigner(vnode)\n    addEventListener(el, 'change', () => {\n      el[assignKey](getValue(el))\n    })\n  },\n  beforeUpdate(el, { value, oldValue }, vnode) {\n    el[assignKey] = getModelAssigner(vnode)\n    if (value !== oldValue) {\n      el.checked = looseEqual(value, vnode.props!.value)\n    }\n  },\n}\n\nexport const vModelSelect: ModelDirective<HTMLSelectElement, 'number'> = {\n  // <select multiple> value need to be deep traversed\n  deep: true,\n  created(el, { value, modifiers: { number } }, vnode) {\n    const isSetModel = isSet(value)\n    addEventListener(el, 'change', () => {\n      const selectedVal = Array.prototype.filter\n        .call(el.options, (o: HTMLOptionElement) => o.selected)\n        .map((o: HTMLOptionElement) =>\n          number ? looseToNumber(getValue(o)) : getValue(o),\n        )\n      el[assignKey](\n        el.multiple\n          ? isSetModel\n            ? new Set(selectedVal)\n            : selectedVal\n          : selectedVal[0],\n      )\n      el._assigning = true\n      nextTick(() => {\n        el._assigning = false\n      })\n    })\n    el[assignKey] = getModelAssigner(vnode)\n  },\n  // set value in mounted & updated because <select> relies on its children\n  // <option>s.\n  mounted(el, { value }) {\n    setSelected(el, value)\n  },\n  beforeUpdate(el, _binding, vnode) {\n    el[assignKey] = getModelAssigner(vnode)\n  },\n  updated(el, { value }) {\n    if (!el._assigning) {\n      setSelected(el, value)\n    }\n  },\n}\n\nfunction setSelected(el: HTMLSelectElement, value: any) {\n  const isMultiple = el.multiple\n  const isArrayValue = isArray(value)\n  if (isMultiple && !isArrayValue && !isSet(value)) {\n    __DEV__ &&\n      warn(\n        `<select multiple v-model> expects an Array or Set value for its binding, ` +\n          `but got ${Object.prototype.toString.call(value).slice(8, -1)}.`,\n      )\n    return\n  }\n\n  for (let i = 0, l = el.options.length; i < l; i++) {\n    const option = el.options[i]\n    const optionValue = getValue(option)\n    if (isMultiple) {\n      if (isArrayValue) {\n        const optionType = typeof optionValue\n        // fast path for string / number values\n        if (optionType === 'string' || optionType === 'number') {\n          option.selected = value.some(v => String(v) === String(optionValue))\n        } else {\n          option.selected = looseIndexOf(value, optionValue) > -1\n        }\n      } else {\n        option.selected = value.has(optionValue)\n      }\n    } else if (looseEqual(getValue(option), value)) {\n      if (el.selectedIndex !== i) el.selectedIndex = i\n      return\n    }\n  }\n  if (!isMultiple && el.selectedIndex !== -1) {\n    el.selectedIndex = -1\n  }\n}\n\n// retrieve raw value set via :value bindings\nfunction getValue(el: HTMLOptionElement | HTMLInputElement) {\n  return '_value' in el ? (el as any)._value : el.value\n}\n\n// retrieve raw value for true-value and false-value set via :true-value or :false-value bindings\nfunction getCheckboxValue(\n  el: HTMLInputElement & { _trueValue?: any; _falseValue?: any },\n  checked: boolean,\n) {\n  const key = checked ? '_trueValue' : '_falseValue'\n  return key in el ? el[key] : checked\n}\n\nexport const vModelDynamic: ObjectDirective<\n  HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement\n> = {\n  created(el, binding, vnode) {\n    callModelHook(el, binding, vnode, null, 'created')\n  },\n  mounted(el, binding, vnode) {\n    callModelHook(el, binding, vnode, null, 'mounted')\n  },\n  beforeUpdate(el, binding, vnode, prevVNode) {\n    callModelHook(el, binding, vnode, prevVNode, 'beforeUpdate')\n  },\n  updated(el, binding, vnode, prevVNode) {\n    callModelHook(el, binding, vnode, prevVNode, 'updated')\n  },\n}\n\nfunction resolveDynamicModel(tagName: string, type: string | undefined) {\n  switch (tagName) {\n    case 'SELECT':\n      return vModelSelect\n    case 'TEXTAREA':\n      return vModelText\n    default:\n      switch (type) {\n        case 'checkbox':\n          return vModelCheckbox\n        case 'radio':\n          return vModelRadio\n        default:\n          return vModelText\n      }\n  }\n}\n\nfunction callModelHook(\n  el: HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement,\n  binding: DirectiveBinding,\n  vnode: VNode,\n  prevVNode: VNode | null,\n  hook: keyof ObjectDirective,\n) {\n  const modelToUse = resolveDynamicModel(\n    el.tagName,\n    vnode.props && vnode.props.type,\n  )\n  const fn = modelToUse[hook] as DirectiveHook\n  fn && fn(el, binding, vnode, prevVNode)\n}\n\n// SSR vnode transforms, only used when user includes client-oriented render\n// function in SSR\nexport function initVModelForSSR(): void {\n  vModelText.getSSRProps = ({ value }) => ({ value })\n\n  vModelRadio.getSSRProps = ({ value }, vnode) => {\n    if (vnode.props && looseEqual(vnode.props.value, value)) {\n      return { checked: true }\n    }\n  }\n\n  vModelCheckbox.getSSRProps = ({ value }, vnode) => {\n    if (isArray(value)) {\n      if (vnode.props && looseIndexOf(value, vnode.props.value) > -1) {\n        return { checked: true }\n      }\n    } else if (isSet(value)) {\n      if (vnode.props && value.has(vnode.props.value)) {\n        return { checked: true }\n      }\n    } else if (value) {\n      return { checked: true }\n    }\n  }\n\n  vModelDynamic.getSSRProps = (binding, vnode) => {\n    if (typeof vnode.type !== 'string') {\n      return\n    }\n    const modelToUse = resolveDynamicModel(\n      // resolveDynamicModel expects an uppercase tag name, but vnode.type is lowercase\n      vnode.type.toUpperCase(),\n      vnode.props && vnode.props.type,\n    )\n    if (modelToUse.getSSRProps) {\n      return modelToUse.getSSRProps(binding, vnode)\n    }\n  }\n}\n\nexport type VModelDirective =\n  | typeof vModelText\n  | typeof vModelCheckbox\n  | typeof vModelSelect\n  | typeof vModelRadio\n  | typeof vModelDynamic\n"
  },
  {
    "path": "packages/runtime-dom/src/directives/vOn.ts",
    "content": "import {\n  type ComponentInternalInstance,\n  DeprecationTypes,\n  type Directive,\n  type LegacyConfig,\n  compatUtils,\n  getCurrentInstance,\n} from '@vue/runtime-core'\nimport { hyphenate, isArray } from '@vue/shared'\n\nconst systemModifiers = ['ctrl', 'shift', 'alt', 'meta'] as const\ntype SystemModifiers = (typeof systemModifiers)[number]\ntype CompatModifiers = keyof typeof keyNames\n\nexport type VOnModifiers = SystemModifiers | ModifierGuards | CompatModifiers\ntype KeyedEvent = KeyboardEvent | MouseEvent | TouchEvent\n\ntype ModifierGuards =\n  | 'shift'\n  | 'ctrl'\n  | 'alt'\n  | 'meta'\n  | 'left'\n  | 'right'\n  | 'stop'\n  | 'prevent'\n  | 'self'\n  | 'middle'\n  | 'exact'\nconst modifierGuards: Record<\n  ModifierGuards,\n  | ((e: Event) => void | boolean)\n  | ((e: Event, modifiers: string[]) => void | boolean)\n> = {\n  stop: (e: Event) => e.stopPropagation(),\n  prevent: (e: Event) => e.preventDefault(),\n  self: (e: Event) => e.target !== e.currentTarget,\n  ctrl: (e: Event) => !(e as KeyedEvent).ctrlKey,\n  shift: (e: Event) => !(e as KeyedEvent).shiftKey,\n  alt: (e: Event) => !(e as KeyedEvent).altKey,\n  meta: (e: Event) => !(e as KeyedEvent).metaKey,\n  left: (e: Event) => 'button' in e && (e as MouseEvent).button !== 0,\n  middle: (e: Event) => 'button' in e && (e as MouseEvent).button !== 1,\n  right: (e: Event) => 'button' in e && (e as MouseEvent).button !== 2,\n  exact: (e, modifiers) =>\n    systemModifiers.some(m => (e as any)[`${m}Key`] && !modifiers.includes(m)),\n}\n\n/**\n * @private\n */\nexport const withModifiers = <\n  T extends (event: Event, ...args: unknown[]) => any,\n>(\n  fn: T & { _withMods?: { [key: string]: T } },\n  modifiers: VOnModifiers[],\n): T => {\n  if (!fn) return fn\n  const cache = fn._withMods || (fn._withMods = {})\n  const cacheKey = modifiers.join('.')\n  return (\n    cache[cacheKey] ||\n    (cache[cacheKey] = ((event, ...args) => {\n      for (let i = 0; i < modifiers.length; i++) {\n        const guard = modifierGuards[modifiers[i] as ModifierGuards]\n        if (guard && guard(event, modifiers)) return\n      }\n      return fn(event, ...args)\n    }) as T)\n  )\n}\n\n// Kept for 2.x compat.\n// Note: IE11 compat for `spacebar` and `del` is removed for now.\nconst keyNames: Record<\n  'esc' | 'space' | 'up' | 'left' | 'right' | 'down' | 'delete',\n  string\n> = {\n  esc: 'escape',\n  space: ' ',\n  up: 'arrow-up',\n  left: 'arrow-left',\n  right: 'arrow-right',\n  down: 'arrow-down',\n  delete: 'backspace',\n}\n\n/**\n * @private\n */\nexport const withKeys = <T extends (event: KeyboardEvent) => any>(\n  fn: T & { _withKeys?: { [k: string]: T } },\n  modifiers: string[],\n): T => {\n  let globalKeyCodes: LegacyConfig['keyCodes']\n  let instance: ComponentInternalInstance | null = null\n  if (__COMPAT__) {\n    instance = getCurrentInstance()\n    if (\n      compatUtils.isCompatEnabled(DeprecationTypes.CONFIG_KEY_CODES, instance)\n    ) {\n      if (instance) {\n        globalKeyCodes = (instance.appContext.config as LegacyConfig).keyCodes\n      }\n    }\n    if (__DEV__ && modifiers.some(m => /^\\d+$/.test(m))) {\n      compatUtils.warnDeprecation(\n        DeprecationTypes.V_ON_KEYCODE_MODIFIER,\n        instance,\n      )\n    }\n  }\n\n  const cache: { [k: string]: T } = fn._withKeys || (fn._withKeys = {})\n  const cacheKey = modifiers.join('.')\n\n  return (\n    cache[cacheKey] ||\n    (cache[cacheKey] = (event => {\n      if (!('key' in event)) {\n        return\n      }\n\n      const eventKey = hyphenate(event.key)\n      if (\n        modifiers.some(\n          k =>\n            k === eventKey ||\n            keyNames[k as unknown as CompatModifiers] === eventKey,\n        )\n      ) {\n        return fn(event)\n      }\n\n      if (__COMPAT__) {\n        const keyCode = String(event.keyCode)\n        if (\n          compatUtils.isCompatEnabled(\n            DeprecationTypes.V_ON_KEYCODE_MODIFIER,\n            instance,\n          ) &&\n          modifiers.some(mod => mod == keyCode)\n        ) {\n          return fn(event)\n        }\n        if (globalKeyCodes) {\n          for (const mod of modifiers) {\n            const codes = globalKeyCodes[mod]\n            if (codes) {\n              const matches = isArray(codes)\n                ? codes.some(code => String(code) === keyCode)\n                : String(codes) === keyCode\n              if (matches) {\n                return fn(event)\n              }\n            }\n          }\n        }\n      }\n    }) as T)\n  )\n}\n\nexport type VOnDirective = Directive<any, any, VOnModifiers>\n"
  },
  {
    "path": "packages/runtime-dom/src/directives/vShow.ts",
    "content": "import type { ObjectDirective } from '@vue/runtime-core'\n\nexport const vShowOriginalDisplay: unique symbol = Symbol('_vod')\nexport const vShowHidden: unique symbol = Symbol('_vsh')\n\nexport interface VShowElement extends HTMLElement {\n  // _vod = vue original display\n  [vShowOriginalDisplay]: string\n  [vShowHidden]: boolean\n}\n\nexport const vShow: ObjectDirective<VShowElement> & { name: 'show' } = {\n  // used for prop mismatch check during hydration\n  name: 'show',\n  beforeMount(el, { value }, { transition }) {\n    el[vShowOriginalDisplay] =\n      el.style.display === 'none' ? '' : el.style.display\n    if (transition && value) {\n      transition.beforeEnter(el)\n    } else {\n      setDisplay(el, value)\n    }\n  },\n  mounted(el, { value }, { transition }) {\n    if (transition && value) {\n      transition.enter(el)\n    }\n  },\n  updated(el, { value, oldValue }, { transition }) {\n    if (!value === !oldValue) return\n    if (transition) {\n      if (value) {\n        transition.beforeEnter(el)\n        setDisplay(el, true)\n        transition.enter(el)\n      } else {\n        transition.leave(el, () => {\n          setDisplay(el, false)\n        })\n      }\n    } else {\n      setDisplay(el, value)\n    }\n  },\n  beforeUnmount(el, { value }) {\n    setDisplay(el, value)\n  },\n}\n\nfunction setDisplay(el: VShowElement, value: unknown): void {\n  el.style.display = value ? el[vShowOriginalDisplay] : 'none'\n  el[vShowHidden] = !value\n}\n\n// SSR vnode transforms, only used when user includes client-oriented render\n// function in SSR\nexport function initVShowForSSR(): void {\n  vShow.getSSRProps = ({ value }) => {\n    if (!value) {\n      return { style: { display: 'none' } }\n    }\n  }\n}\n"
  },
  {
    "path": "packages/runtime-dom/src/helpers/useCssModule.ts",
    "content": "import { getCurrentInstance, warn } from '@vue/runtime-core'\nimport { EMPTY_OBJ } from '@vue/shared'\n\nexport function useCssModule(name = '$style'): Record<string, string> {\n  if (!__GLOBAL__) {\n    const instance = getCurrentInstance()!\n    if (!instance) {\n      __DEV__ && warn(`useCssModule must be called inside setup()`)\n      return EMPTY_OBJ\n    }\n    const modules = instance.type.__cssModules\n    if (!modules) {\n      __DEV__ && warn(`Current instance does not have CSS modules injected.`)\n      return EMPTY_OBJ\n    }\n    const mod = modules[name]\n    if (!mod) {\n      __DEV__ &&\n        warn(`Current instance does not have CSS module named \"${name}\".`)\n      return EMPTY_OBJ\n    }\n    return mod as Record<string, string>\n  } else {\n    /* v8 ignore start */\n    if (__DEV__) {\n      warn(`useCssModule() is not supported in the global build.`)\n    }\n    return EMPTY_OBJ\n    /* v8 ignore stop */\n  }\n}\n"
  },
  {
    "path": "packages/runtime-dom/src/helpers/useCssVars.ts",
    "content": "import {\n  Fragment,\n  Static,\n  type VNode,\n  getCurrentInstance,\n  onBeforeUpdate,\n  onMounted,\n  onUnmounted,\n  queuePostFlushCb,\n  warn,\n  watch,\n} from '@vue/runtime-core'\nimport { NOOP, ShapeFlags, normalizeCssVarValue } from '@vue/shared'\n\nexport const CSS_VAR_TEXT: unique symbol = Symbol(__DEV__ ? 'CSS_VAR_TEXT' : '')\n/**\n * Runtime helper for SFC's CSS variable injection feature.\n * @private\n */\nexport function useCssVars(\n  getter: (ctx: any) => Record<string, unknown>,\n): void {\n  if (!__BROWSER__ && !__TEST__) return\n\n  const instance = getCurrentInstance()\n  /* v8 ignore start */\n  if (!instance) {\n    __DEV__ &&\n      warn(`useCssVars is called without current active component instance.`)\n    return\n  }\n  /* v8 ignore stop */\n\n  const updateTeleports = (instance.ut = (vars = getter(instance.proxy)) => {\n    Array.from(\n      document.querySelectorAll(`[data-v-owner=\"${instance.uid}\"]`),\n    ).forEach(node => setVarsOnNode(node, vars))\n  })\n\n  if (__DEV__) {\n    instance.getCssVars = () => getter(instance.proxy)\n  }\n\n  const setVars = () => {\n    const vars = getter(instance.proxy)\n    if (instance.ce) {\n      setVarsOnNode(instance.ce as any, vars)\n    } else {\n      setVarsOnVNode(instance.subTree, vars)\n    }\n    updateTeleports(vars)\n  }\n\n  // handle cases where child component root is affected\n  // and triggers reflow in onMounted\n  onBeforeUpdate(() => {\n    queuePostFlushCb(setVars)\n  })\n\n  onMounted(() => {\n    // run setVars synchronously here, but run as post-effect on changes\n    watch(setVars, NOOP, { flush: 'post' })\n    const ob = new MutationObserver(setVars)\n    ob.observe(instance.subTree.el!.parentNode, { childList: true })\n    onUnmounted(() => ob.disconnect())\n  })\n}\n\nfunction setVarsOnVNode(vnode: VNode, vars: Record<string, unknown>) {\n  if (__FEATURE_SUSPENSE__ && vnode.shapeFlag & ShapeFlags.SUSPENSE) {\n    const suspense = vnode.suspense!\n    vnode = suspense.activeBranch!\n    if (suspense.pendingBranch && !suspense.isHydrating) {\n      suspense.effects.push(() => {\n        setVarsOnVNode(suspense.activeBranch!, vars)\n      })\n    }\n  }\n\n  // drill down HOCs until it's a non-component vnode\n  while (vnode.component) {\n    vnode = vnode.component.subTree\n  }\n\n  if (vnode.shapeFlag & ShapeFlags.ELEMENT && vnode.el) {\n    setVarsOnNode(vnode.el as Node, vars)\n  } else if (vnode.type === Fragment) {\n    ;(vnode.children as VNode[]).forEach(c => setVarsOnVNode(c, vars))\n  } else if (vnode.type === Static) {\n    let { el, anchor } = vnode\n    while (el) {\n      setVarsOnNode(el as Node, vars)\n      if (el === anchor) break\n      el = el.nextSibling\n    }\n  }\n}\n\nfunction setVarsOnNode(el: Node, vars: Record<string, unknown>) {\n  if (el.nodeType === 1) {\n    const style = (el as HTMLElement).style\n    let cssText = ''\n    for (const key in vars) {\n      const value = normalizeCssVarValue(vars[key])\n      style.setProperty(`--${key}`, value)\n      cssText += `--${key}: ${value};`\n    }\n    ;(style as any)[CSS_VAR_TEXT] = cssText\n  }\n}\n"
  },
  {
    "path": "packages/runtime-dom/src/index.ts",
    "content": "import {\n  type App,\n  type CreateAppFunction,\n  type DefineComponent,\n  DeprecationTypes,\n  type Directive,\n  type ElementNamespace,\n  type HydrationRenderer,\n  type Renderer,\n  type RootHydrateFunction,\n  type RootRenderFunction,\n  compatUtils,\n  createHydrationRenderer,\n  createRenderer,\n  isRuntimeOnly,\n  warn,\n} from '@vue/runtime-core'\nimport { nodeOps } from './nodeOps'\nimport { patchProp } from './patchProp'\nexport { nodeOps, patchProp }\n// Importing from the compiler, will be tree-shaken in prod\nimport {\n  NOOP,\n  extend,\n  isFunction,\n  isHTMLTag,\n  isMathMLTag,\n  isSVGTag,\n  isString,\n} from '@vue/shared'\nimport type { TransitionProps } from './components/Transition'\nimport type { TransitionGroupProps } from './components/TransitionGroup'\nimport type { vShow } from './directives/vShow'\nimport type { VOnDirective } from './directives/vOn'\nimport type { VModelDirective } from './directives/vModel'\nimport type { ClassValue, StyleValue } from './jsx'\n\n/**\n * This is a stub implementation to prevent the need to use dom types.\n *\n * To enable proper types, add `\"dom\"` to `\"lib\"` in your `tsconfig.json`.\n */\ntype DomType<T> = typeof globalThis extends { window: unknown } ? T : never\n\ndeclare module '@vue/reactivity' {\n  export interface RefUnwrapBailTypes {\n    runtimeDOMBailTypes: DomType<Node | Window>\n  }\n}\n\ndeclare module '@vue/runtime-core' {\n  interface AllowedAttrs {\n    class?: ClassValue\n    style?: StyleValue\n  }\n\n  interface GlobalComponents {\n    Transition: DefineComponent<TransitionProps>\n    TransitionGroup: DefineComponent<TransitionGroupProps>\n  }\n\n  interface GlobalDirectives {\n    vShow: typeof vShow\n    vOn: VOnDirective\n    vBind: VModelDirective\n    vIf: Directive<any, boolean>\n    vOnce: Directive\n    vSlot: Directive\n  }\n}\n\nconst rendererOptions = /*@__PURE__*/ extend({ patchProp }, nodeOps)\n\n// lazy create the renderer - this makes core renderer logic tree-shakable\n// in case the user only imports reactivity utilities from Vue.\nlet renderer: Renderer<Element | ShadowRoot> | HydrationRenderer\n\nlet enabledHydration = false\n\nfunction ensureRenderer() {\n  return (\n    renderer ||\n    (renderer = createRenderer<Node, Element | ShadowRoot>(rendererOptions))\n  )\n}\n\nfunction ensureHydrationRenderer() {\n  renderer = enabledHydration\n    ? renderer\n    : createHydrationRenderer(rendererOptions)\n  enabledHydration = true\n  return renderer as HydrationRenderer\n}\n\n// use explicit type casts here to avoid import() calls in rolled-up d.ts\nexport const render = ((...args) => {\n  ensureRenderer().render(...args)\n}) as RootRenderFunction<Element | ShadowRoot>\n\nexport const hydrate = ((...args) => {\n  ensureHydrationRenderer().hydrate(...args)\n}) as RootHydrateFunction\n\nexport const createApp = ((...args) => {\n  const app = ensureRenderer().createApp(...args)\n\n  if (__DEV__) {\n    injectNativeTagCheck(app)\n    injectCompilerOptionsCheck(app)\n  }\n\n  const { mount } = app\n  app.mount = (containerOrSelector: Element | ShadowRoot | string): any => {\n    const container = normalizeContainer(containerOrSelector)\n    if (!container) return\n\n    const component = app._component\n    if (!isFunction(component) && !component.render && !component.template) {\n      // __UNSAFE__\n      // Reason: potential execution of JS expressions in in-DOM template.\n      // The user must make sure the in-DOM template is trusted. If it's\n      // rendered by the server, the template should not contain any user data.\n      component.template = container.innerHTML\n      // 2.x compat check\n      if (__COMPAT__ && __DEV__ && container.nodeType === 1) {\n        for (let i = 0; i < (container as Element).attributes.length; i++) {\n          const attr = (container as Element).attributes[i]\n          if (attr.name !== 'v-cloak' && /^(?:v-|:|@)/.test(attr.name)) {\n            compatUtils.warnDeprecation(\n              DeprecationTypes.GLOBAL_MOUNT_CONTAINER,\n              null,\n            )\n            break\n          }\n        }\n      }\n    }\n\n    // clear content before mounting\n    if (container.nodeType === 1) {\n      container.textContent = ''\n    }\n    const proxy = mount(container, false, resolveRootNamespace(container))\n    if (container instanceof Element) {\n      container.removeAttribute('v-cloak')\n      container.setAttribute('data-v-app', '')\n    }\n    return proxy\n  }\n\n  return app\n}) as CreateAppFunction<Element>\n\nexport const createSSRApp = ((...args) => {\n  const app = ensureHydrationRenderer().createApp(...args)\n\n  if (__DEV__) {\n    injectNativeTagCheck(app)\n    injectCompilerOptionsCheck(app)\n  }\n\n  const { mount } = app\n  app.mount = (containerOrSelector: Element | ShadowRoot | string): any => {\n    const container = normalizeContainer(containerOrSelector)\n    if (container) {\n      return mount(container, true, resolveRootNamespace(container))\n    }\n  }\n\n  return app\n}) as CreateAppFunction<Element>\n\nfunction resolveRootNamespace(\n  container: Element | ShadowRoot,\n): ElementNamespace {\n  if (container instanceof SVGElement) {\n    return 'svg'\n  }\n  if (\n    typeof MathMLElement === 'function' &&\n    container instanceof MathMLElement\n  ) {\n    return 'mathml'\n  }\n}\n\nfunction injectNativeTagCheck(app: App) {\n  // Inject `isNativeTag`\n  // this is used for component name validation (dev only)\n  Object.defineProperty(app.config, 'isNativeTag', {\n    value: (tag: string) => isHTMLTag(tag) || isSVGTag(tag) || isMathMLTag(tag),\n    writable: false,\n  })\n}\n\n// dev only\nfunction injectCompilerOptionsCheck(app: App) {\n  if (isRuntimeOnly()) {\n    const isCustomElement = app.config.isCustomElement\n    Object.defineProperty(app.config, 'isCustomElement', {\n      get() {\n        return isCustomElement\n      },\n      set() {\n        warn(\n          `The \\`isCustomElement\\` config option is deprecated. Use ` +\n            `\\`compilerOptions.isCustomElement\\` instead.`,\n        )\n      },\n    })\n\n    const compilerOptions = app.config.compilerOptions\n    const msg =\n      `The \\`compilerOptions\\` config option is only respected when using ` +\n      `a build of Vue.js that includes the runtime compiler (aka \"full build\"). ` +\n      `Since you are using the runtime-only build, \\`compilerOptions\\` ` +\n      `must be passed to \\`@vue/compiler-dom\\` in the build setup instead.\\n` +\n      `- For vue-loader: pass it via vue-loader's \\`compilerOptions\\` loader option.\\n` +\n      `- For vue-cli: see https://cli.vuejs.org/guide/webpack.html#modifying-options-of-a-loader\\n` +\n      `- For vite: pass it via @vitejs/plugin-vue options. See https://github.com/vitejs/vite-plugin-vue/tree/main/packages/plugin-vue#example-for-passing-options-to-vuecompiler-sfc`\n\n    Object.defineProperty(app.config, 'compilerOptions', {\n      get() {\n        warn(msg)\n        return compilerOptions\n      },\n      set() {\n        warn(msg)\n      },\n    })\n  }\n}\n\nfunction normalizeContainer(\n  container: Element | ShadowRoot | string,\n): Element | ShadowRoot | null {\n  if (isString(container)) {\n    const res = document.querySelector(container)\n    if (__DEV__ && !res) {\n      warn(\n        `Failed to mount app: mount target selector \"${container}\" returned null.`,\n      )\n    }\n    return res\n  }\n  if (\n    __DEV__ &&\n    window.ShadowRoot &&\n    container instanceof window.ShadowRoot &&\n    container.mode === 'closed'\n  ) {\n    warn(\n      `mounting on a ShadowRoot with \\`{mode: \"closed\"}\\` may lead to unpredictable bugs`,\n    )\n  }\n  return container as any\n}\n\n// Custom element support\nexport {\n  defineCustomElement,\n  defineSSRCustomElement,\n  useShadowRoot,\n  useHost,\n  VueElement,\n  type VueElementConstructor,\n  type CustomElementOptions,\n} from './apiCustomElement'\n\n// SFC CSS utilities\nexport { useCssModule } from './helpers/useCssModule'\nexport { useCssVars } from './helpers/useCssVars'\n\n// DOM-only components\nexport { Transition, type TransitionProps } from './components/Transition'\nexport {\n  TransitionGroup,\n  type TransitionGroupProps,\n} from './components/TransitionGroup'\n\n// **Internal** DOM-only runtime directive helpers\nexport {\n  vModelText,\n  vModelCheckbox,\n  vModelRadio,\n  vModelSelect,\n  vModelDynamic,\n} from './directives/vModel'\nexport { withModifiers, withKeys } from './directives/vOn'\nexport { vShow } from './directives/vShow'\n\nimport { initVModelForSSR } from './directives/vModel'\nimport { initVShowForSSR } from './directives/vShow'\n\nlet ssrDirectiveInitialized = false\n\n/**\n * @internal\n */\nexport const initDirectivesForSSR: () => void = __SSR__\n  ? () => {\n      if (!ssrDirectiveInitialized) {\n        ssrDirectiveInitialized = true\n        initVModelForSSR()\n        initVShowForSSR()\n      }\n    }\n  : NOOP\n\n// re-export everything from core\n// h, Component, reactivity API, nextTick, flags & types\nexport * from '@vue/runtime-core'\n\nexport * from './jsx'\n"
  },
  {
    "path": "packages/runtime-dom/src/jsx.ts",
    "content": "// Note: this file is auto concatenated to the end of the bundled d.ts during\n// build.\n\n// This code is based on react definition in DefinitelyTyped published under the MIT license.\n//      Repository: https://github.com/DefinitelyTyped/DefinitelyTyped\n//      Path in the repository: types/react/index.d.ts\n//\n// Copyrights of original definition are:\n//      AssureSign <http://www.assuresign.com>\n//      Microsoft <https://microsoft.com>\n//                 John Reilly <https://github.com/johnnyreilly>\n//      Benoit Benezech <https://github.com/bbenezech>\n//      Patricio Zavolinsky <https://github.com/pzavolinsky>\n//      Digiguru <https://github.com/digiguru>\n//      Eric Anderson <https://github.com/ericanderson>\n//      Dovydas Navickas <https://github.com/DovydasNavickas>\n//                 Josh Rutherford <https://github.com/theruther4d>\n//                 Guilherme Hübner <https://github.com/guilhermehubner>\n//                 Ferdy Budhidharma <https://github.com/ferdaber>\n//                 Johann Rakotoharisoa <https://github.com/jrakotoharisoa>\n//                 Olivier Pascal <https://github.com/pascaloliv>\n//                 Martin Hochel <https://github.com/hotell>\n//                 Frank Li <https://github.com/franklixuefei>\n//                 Jessica Franco <https://github.com/Jessidhia>\n//                 Saransh Kataria <https://github.com/saranshkataria>\n//                 Kanitkorn Sujautra <https://github.com/lukyth>\n//                 Sebastian Silbermann <https://github.com/eps1lon>\n\nimport type * as CSS from 'csstype'\n\nexport interface CSSProperties\n  extends\n    CSS.Properties<string | number>,\n    CSS.PropertiesHyphen<string | number> {\n  /**\n   * The index signature was removed to enable closed typing for style\n   * using CSSType. You're able to use type assertion or module augmentation\n   * to add properties or an index signature of your own.\n   *\n   * For examples and more information, visit:\n   * https://github.com/frenic/csstype#what-should-i-do-when-i-get-type-errors\n   */\n  [v: `--${string}`]: string | number | undefined\n}\n\ntype Booleanish = boolean | 'true' | 'false'\ntype Numberish = number | string\n\n// All the WAI-ARIA 1.1 attributes from https://www.w3.org/TR/wai-aria-1.1/\nexport interface AriaAttributes {\n  /** Identifies the currently active element when DOM focus is on a composite widget, textbox, group, or application. */\n  'aria-activedescendant'?: string | undefined\n  /** Indicates whether assistive technologies will present all, or only parts of, the changed region based on the change notifications defined by the aria-relevant attribute. */\n  'aria-atomic'?: Booleanish | undefined\n  /**\n   * Indicates whether inputting text could trigger display of one or more predictions of the user's intended value for an input and specifies how predictions would be\n   * presented if they are made.\n   */\n  'aria-autocomplete'?: 'none' | 'inline' | 'list' | 'both' | undefined\n  /** Indicates an element is being modified and that assistive technologies MAY want to wait until the modifications are complete before exposing them to the user. */\n  'aria-busy'?: Booleanish | undefined\n  /**\n   * Indicates the current \"checked\" state of checkboxes, radio buttons, and other widgets.\n   * @see aria-pressed @see aria-selected.\n   */\n  'aria-checked'?: Booleanish | 'mixed' | undefined\n  /**\n   * Defines the total number of columns in a table, grid, or treegrid.\n   * @see aria-colindex.\n   */\n  'aria-colcount'?: Numberish | undefined\n  /**\n   * Defines an element's column index or position with respect to the total number of columns within a table, grid, or treegrid.\n   * @see aria-colcount @see aria-colspan.\n   */\n  'aria-colindex'?: Numberish | undefined\n  /**\n   * Defines the number of columns spanned by a cell or gridcell within a table, grid, or treegrid.\n   * @see aria-colindex @see aria-rowspan.\n   */\n  'aria-colspan'?: Numberish | undefined\n  /**\n   * Identifies the element (or elements) whose contents or presence are controlled by the current element.\n   * @see aria-owns.\n   */\n  'aria-controls'?: string | undefined\n  /** Indicates the element that represents the current item within a container or set of related elements. */\n  'aria-current'?:\n    | Booleanish\n    | 'page'\n    | 'step'\n    | 'location'\n    | 'date'\n    | 'time'\n    | undefined\n  /**\n   * Identifies the element (or elements) that describes the object.\n   * @see aria-labelledby\n   */\n  'aria-describedby'?: string | undefined\n  /**\n   * Identifies the element that provides a detailed, extended description for the object.\n   * @see aria-describedby.\n   */\n  'aria-details'?: string | undefined\n  /**\n   * Indicates that the element is perceivable but disabled, so it is not editable or otherwise operable.\n   * @see aria-hidden @see aria-readonly.\n   */\n  'aria-disabled'?: Booleanish | undefined\n  /**\n   * Indicates what functions can be performed when a dragged object is released on the drop target.\n   * @deprecated in ARIA 1.1\n   */\n  'aria-dropeffect'?:\n    | 'none'\n    | 'copy'\n    | 'execute'\n    | 'link'\n    | 'move'\n    | 'popup'\n    | undefined\n  /**\n   * Identifies the element that provides an error message for the object.\n   * @see aria-invalid @see aria-describedby.\n   */\n  'aria-errormessage'?: string | undefined\n  /** Indicates whether the element, or another grouping element it controls, is currently expanded or collapsed. */\n  'aria-expanded'?: Booleanish | undefined\n  /**\n   * Identifies the next element (or elements) in an alternate reading order of content which, at the user's discretion,\n   * allows assistive technology to override the general default of reading in document source order.\n   */\n  'aria-flowto'?: string | undefined\n  /**\n   * Indicates an element's \"grabbed\" state in a drag-and-drop operation.\n   * @deprecated in ARIA 1.1\n   */\n  'aria-grabbed'?: Booleanish | undefined\n  /** Indicates the availability and type of interactive popup element, such as menu or dialog, that can be triggered by an element. */\n  'aria-haspopup'?:\n    | Booleanish\n    | 'menu'\n    | 'listbox'\n    | 'tree'\n    | 'grid'\n    | 'dialog'\n    | undefined\n  /**\n   * Indicates whether the element is exposed to an accessibility API.\n   * @see aria-disabled.\n   */\n  'aria-hidden'?: Booleanish | undefined\n  /**\n   * Indicates the entered value does not conform to the format expected by the application.\n   * @see aria-errormessage.\n   */\n  'aria-invalid'?: Booleanish | 'grammar' | 'spelling' | undefined\n  /** Indicates keyboard shortcuts that an author has implemented to activate or give focus to an element. */\n  'aria-keyshortcuts'?: string | undefined\n  /**\n   * Defines a string value that labels the current element.\n   * @see aria-labelledby.\n   */\n  'aria-label'?: string | undefined\n  /**\n   * Identifies the element (or elements) that labels the current element.\n   * @see aria-describedby.\n   */\n  'aria-labelledby'?: string | undefined\n  /** Defines the hierarchical level of an element within a structure. */\n  'aria-level'?: Numberish | undefined\n  /** Indicates that an element will be updated, and describes the types of updates the user agents, assistive technologies, and user can expect from the live region. */\n  'aria-live'?: 'off' | 'assertive' | 'polite' | undefined\n  /** Indicates whether an element is modal when displayed. */\n  'aria-modal'?: Booleanish | undefined\n  /** Indicates whether a text box accepts multiple lines of input or only a single line. */\n  'aria-multiline'?: Booleanish | undefined\n  /** Indicates that the user may select more than one item from the current selectable descendants. */\n  'aria-multiselectable'?: Booleanish | undefined\n  /** Indicates whether the element's orientation is horizontal, vertical, or unknown/ambiguous. */\n  'aria-orientation'?: 'horizontal' | 'vertical' | undefined\n  /**\n   * Identifies an element (or elements) in order to define a visual, functional, or contextual parent/child relationship\n   * between DOM elements where the DOM hierarchy cannot be used to represent the relationship.\n   * @see aria-controls.\n   */\n  'aria-owns'?: string | undefined\n  /**\n   * Defines a short hint (a word or short phrase) intended to aid the user with data entry when the control has no value.\n   * A hint could be a sample value or a brief description of the expected format.\n   */\n  'aria-placeholder'?: string | undefined\n  /**\n   * Defines an element's number or position in the current set of listitems or treeitems. Not required if all elements in the set are present in the DOM.\n   * @see aria-setsize.\n   */\n  'aria-posinset'?: Numberish | undefined\n  /**\n   * Indicates the current \"pressed\" state of toggle buttons.\n   * @see aria-checked @see aria-selected.\n   */\n  'aria-pressed'?: Booleanish | 'mixed' | undefined\n  /**\n   * Indicates that the element is not editable, but is otherwise operable.\n   * @see aria-disabled.\n   */\n  'aria-readonly'?: Booleanish | undefined\n  /**\n   * Indicates what notifications the user agent will trigger when the accessibility tree within a live region is modified.\n   * @see aria-atomic.\n   */\n  'aria-relevant'?:\n    | 'additions'\n    | 'additions removals'\n    | 'additions text'\n    | 'all'\n    | 'removals'\n    | 'removals additions'\n    | 'removals text'\n    | 'text'\n    | 'text additions'\n    | 'text removals'\n    | undefined\n  /** Indicates that user input is required on the element before a form may be submitted. */\n  'aria-required'?: Booleanish | undefined\n  /** Defines a human-readable, author-localized description for the role of an element. */\n  'aria-roledescription'?: string | undefined\n  /**\n   * Defines the total number of rows in a table, grid, or treegrid.\n   * @see aria-rowindex.\n   */\n  'aria-rowcount'?: Numberish | undefined\n  /**\n   * Defines an element's row index or position with respect to the total number of rows within a table, grid, or treegrid.\n   * @see aria-rowcount @see aria-rowspan.\n   */\n  'aria-rowindex'?: Numberish | undefined\n  /**\n   * Defines the number of rows spanned by a cell or gridcell within a table, grid, or treegrid.\n   * @see aria-rowindex @see aria-colspan.\n   */\n  'aria-rowspan'?: Numberish | undefined\n  /**\n   * Indicates the current \"selected\" state of various widgets.\n   * @see aria-checked @see aria-pressed.\n   */\n  'aria-selected'?: Booleanish | undefined\n  /**\n   * Defines the number of items in the current set of listitems or treeitems. Not required if all elements in the set are present in the DOM.\n   * @see aria-posinset.\n   */\n  'aria-setsize'?: Numberish | undefined\n  /** Indicates if items in a table or grid are sorted in ascending or descending order. */\n  'aria-sort'?: 'none' | 'ascending' | 'descending' | 'other' | undefined\n  /** Defines the maximum allowed value for a range widget. */\n  'aria-valuemax'?: Numberish | undefined\n  /** Defines the minimum allowed value for a range widget. */\n  'aria-valuemin'?: Numberish | undefined\n  /**\n   * Defines the current value for a range widget.\n   * @see aria-valuetext.\n   */\n  'aria-valuenow'?: Numberish | undefined\n  /** Defines the human readable text alternative of aria-valuenow for a range widget. */\n  'aria-valuetext'?: string | undefined\n}\n\n// Vue's style normalization supports nested arrays\nexport type StyleValue =\n  | false\n  | null\n  | undefined\n  | string\n  | CSSProperties\n  | Array<StyleValue>\n\n// Support for `class` attribute\nexport type ClassValue =\n  | false\n  | null\n  | undefined\n  | string\n  | Record<string, any>\n  | Array<ClassValue>\n\nexport interface HTMLAttributes extends AriaAttributes, EventHandlers<Events> {\n  innerHTML?: string | undefined\n\n  class?: ClassValue | undefined\n  style?: StyleValue | undefined\n\n  // Standard HTML Attributes\n  accesskey?: string | undefined\n  contenteditable?: Booleanish | 'inherit' | 'plaintext-only' | undefined\n  contextmenu?: string | undefined\n  dir?: string | undefined\n  draggable?: Booleanish | undefined\n  enterkeyhint?:\n    | 'enter'\n    | 'done'\n    | 'go'\n    | 'next'\n    | 'previous'\n    | 'search'\n    | 'send'\n    | undefined\n  /**\n   * @deprecated Use `enterkeyhint` instead.\n   */\n  enterKeyHint?: HTMLAttributes['enterkeyhint']\n  hidden?: Booleanish | '' | 'hidden' | 'until-found' | undefined\n  id?: string | undefined\n  inert?: Booleanish | undefined\n  lang?: string | undefined\n  placeholder?: string | undefined\n  spellcheck?: Booleanish | undefined\n  tabindex?: Numberish | undefined\n  title?: string | undefined\n  translate?: 'yes' | 'no' | undefined\n\n  // Unknown\n  radiogroup?: string | undefined // <command>, <menuitem>\n\n  // WAI-ARIA\n  role?: string | undefined\n\n  // RDFa Attributes\n  about?: string | undefined\n  datatype?: string | undefined\n  inlist?: any\n  prefix?: string | undefined\n  property?: string | undefined\n  resource?: string | undefined\n  typeof?: string | undefined\n  vocab?: string | undefined\n\n  // Non-standard Attributes\n  autocapitalize?: string | undefined\n  autocorrect?: string | undefined\n  autosave?: string | undefined\n  color?: string | undefined\n  itemprop?: string | undefined\n  itemscope?: Booleanish | undefined\n  itemtype?: string | undefined\n  itemid?: string | undefined\n  itemref?: string | undefined\n  results?: Numberish | undefined\n  security?: string | undefined\n  unselectable?: 'on' | 'off' | undefined\n\n  // Living Standard\n  /**\n   * Hints at the type of data that might be entered by the user while editing the element or its contents\n   * @see https://html.spec.whatwg.org/multipage/interaction.html#input-modalities:-the-inputmode-attribute\n   */\n  inputmode?:\n    | 'none'\n    | 'text'\n    | 'tel'\n    | 'url'\n    | 'email'\n    | 'numeric'\n    | 'decimal'\n    | 'search'\n    | undefined\n  /**\n   * Specify that a standard HTML element should behave like a defined custom built-in element\n   * @see https://html.spec.whatwg.org/multipage/custom-elements.html#attr-is\n   */\n  is?: string | undefined\n  /**\n   * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/exportparts\n   */\n  exportparts?: string\n  /**\n   * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/part\n   */\n  part?: string\n}\n\ntype HTMLAttributeReferrerPolicy =\n  | ''\n  | 'no-referrer'\n  | 'no-referrer-when-downgrade'\n  | 'origin'\n  | 'origin-when-cross-origin'\n  | 'same-origin'\n  | 'strict-origin'\n  | 'strict-origin-when-cross-origin'\n  | 'unsafe-url'\n\nexport interface AnchorHTMLAttributes extends HTMLAttributes {\n  download?: any\n  href?: string | undefined\n  hreflang?: string | undefined\n  media?: string | undefined\n  ping?: string | undefined\n  rel?: string | undefined\n  target?: string | undefined\n  type?: string | undefined\n  referrerpolicy?: HTMLAttributeReferrerPolicy | undefined\n}\n\nexport interface AreaHTMLAttributes extends HTMLAttributes {\n  alt?: string | undefined\n  coords?: string | undefined\n  download?: any\n  href?: string | undefined\n  hreflang?: string | undefined\n  media?: string | undefined\n  referrerpolicy?: HTMLAttributeReferrerPolicy | undefined\n  rel?: string | undefined\n  shape?: string | undefined\n  target?: string | undefined\n}\n\nexport interface AudioHTMLAttributes extends MediaHTMLAttributes {}\n\nexport interface BaseHTMLAttributes extends HTMLAttributes {\n  href?: string | undefined\n  target?: string | undefined\n}\n\nexport interface BlockquoteHTMLAttributes extends HTMLAttributes {\n  cite?: string | undefined\n}\n\nexport interface ButtonHTMLAttributes extends HTMLAttributes {\n  autofocus?: Booleanish | undefined\n  disabled?: Booleanish | undefined\n  form?: string | undefined\n  formaction?: string | undefined\n  formenctype?: string | undefined\n  formmethod?: string | undefined\n  formnovalidate?: Booleanish | undefined\n  formtarget?: string | undefined\n  name?: string | undefined\n  type?: 'submit' | 'reset' | 'button' | undefined\n  value?: string | ReadonlyArray<string> | number | undefined\n}\n\nexport interface CanvasHTMLAttributes extends HTMLAttributes {\n  height?: Numberish | undefined\n  width?: Numberish | undefined\n}\n\nexport interface ColHTMLAttributes extends HTMLAttributes {\n  span?: Numberish | undefined\n  width?: Numberish | undefined\n}\n\nexport interface ColgroupHTMLAttributes extends HTMLAttributes {\n  span?: Numberish | undefined\n}\n\nexport interface DataHTMLAttributes extends HTMLAttributes {\n  value?: string | ReadonlyArray<string> | number | undefined\n}\n\nexport interface DetailsHTMLAttributes extends HTMLAttributes {\n  name?: string | undefined\n  open?: Booleanish | undefined\n}\n\nexport interface DelHTMLAttributes extends HTMLAttributes {\n  cite?: string | undefined\n  datetime?: string | undefined\n}\n\nexport interface DialogHTMLAttributes extends HTMLAttributes {\n  open?: Booleanish | undefined\n  onClose?: ((payload: Event) => void) | undefined\n  onCancel?: ((payload: Event) => void) | undefined\n}\n\nexport interface EmbedHTMLAttributes extends HTMLAttributes {\n  height?: Numberish | undefined\n  src?: string | undefined\n  type?: string | undefined\n  width?: Numberish | undefined\n}\n\nexport interface FieldsetHTMLAttributes extends HTMLAttributes {\n  disabled?: Booleanish | undefined\n  form?: string | undefined\n  name?: string | undefined\n}\n\nexport interface FormHTMLAttributes extends HTMLAttributes {\n  acceptcharset?: string | undefined\n  action?: string | undefined\n  autocomplete?: string | undefined\n  enctype?: string | undefined\n  method?: string | undefined\n  name?: string | undefined\n  novalidate?: Booleanish | undefined\n  target?: string | undefined\n}\n\nexport interface HtmlHTMLAttributes extends HTMLAttributes {\n  manifest?: string | undefined\n}\n\nexport interface IframeHTMLAttributes extends HTMLAttributes {\n  allow?: string | undefined\n  allowfullscreen?: Booleanish | undefined\n  allowtransparency?: Booleanish | undefined\n  /** @deprecated */\n  frameborder?: Numberish | undefined\n  height?: Numberish | undefined\n  loading?: 'eager' | 'lazy' | undefined\n  /** @deprecated */\n  marginheight?: Numberish | undefined\n  /** @deprecated */\n  marginwidth?: Numberish | undefined\n  name?: string | undefined\n  referrerpolicy?: HTMLAttributeReferrerPolicy | undefined\n  sandbox?: string | undefined\n  /** @deprecated */\n  scrolling?: string | undefined\n  seamless?: Booleanish | undefined\n  src?: string | undefined\n  srcdoc?: string | undefined\n  width?: Numberish | undefined\n}\n\nexport interface ImgHTMLAttributes extends HTMLAttributes {\n  alt?: string | undefined\n  crossorigin?: 'anonymous' | 'use-credentials' | '' | undefined\n  decoding?: 'async' | 'auto' | 'sync' | undefined\n  fetchpriority?: 'high' | 'low' | 'auto' | undefined\n  height?: Numberish | undefined\n  loading?: 'eager' | 'lazy' | undefined\n  referrerpolicy?: HTMLAttributeReferrerPolicy | undefined\n  sizes?: string | undefined\n  src?: string | undefined\n  srcset?: string | undefined\n  usemap?: string | undefined\n  width?: Numberish | undefined\n}\n\nexport interface InsHTMLAttributes extends HTMLAttributes {\n  cite?: string | undefined\n  datetime?: string | undefined\n}\n\nexport type InputTypeHTMLAttribute =\n  | 'button'\n  | 'checkbox'\n  | 'color'\n  | 'date'\n  | 'datetime-local'\n  | 'email'\n  | 'file'\n  | 'hidden'\n  | 'image'\n  | 'month'\n  | 'number'\n  | 'password'\n  | 'radio'\n  | 'range'\n  | 'reset'\n  | 'search'\n  | 'submit'\n  | 'tel'\n  | 'text'\n  | 'time'\n  | 'url'\n  | 'week'\n  | (string & {})\n\ntype AutoFillAddressKind = 'billing' | 'shipping'\ntype AutoFillBase = '' | 'off' | 'on'\ntype AutoFillContactField =\n  | 'email'\n  | 'tel'\n  | 'tel-area-code'\n  | 'tel-country-code'\n  | 'tel-extension'\n  | 'tel-local'\n  | 'tel-local-prefix'\n  | 'tel-local-suffix'\n  | 'tel-national'\ntype AutoFillContactKind = 'home' | 'mobile' | 'work'\ntype AutoFillCredentialField = 'webauthn'\ntype AutoFillNormalField =\n  | 'additional-name'\n  | 'address-level1'\n  | 'address-level2'\n  | 'address-level3'\n  | 'address-level4'\n  | 'address-line1'\n  | 'address-line2'\n  | 'address-line3'\n  | 'bday-day'\n  | 'bday-month'\n  | 'bday-year'\n  | 'cc-csc'\n  | 'cc-exp'\n  | 'cc-exp-month'\n  | 'cc-exp-year'\n  | 'cc-family-name'\n  | 'cc-given-name'\n  | 'cc-name'\n  | 'cc-number'\n  | 'cc-type'\n  | 'country'\n  | 'country-name'\n  | 'current-password'\n  | 'family-name'\n  | 'given-name'\n  | 'honorific-prefix'\n  | 'honorific-suffix'\n  | 'name'\n  | 'new-password'\n  | 'one-time-code'\n  | 'organization'\n  | 'postal-code'\n  | 'street-address'\n  | 'transaction-amount'\n  | 'transaction-currency'\n  | 'username'\ntype OptionalPrefixToken<T extends string> = `${T} ` | ''\ntype OptionalPostfixToken<T extends string> = ` ${T}` | ''\ntype AutoFillField =\n  | AutoFillNormalField\n  | `${OptionalPrefixToken<AutoFillContactKind>}${AutoFillContactField}`\ntype AutoFillSection = `section-${string}`\ntype AutoFill =\n  | AutoFillBase\n  | `${OptionalPrefixToken<AutoFillSection>}${OptionalPrefixToken<AutoFillAddressKind>}${AutoFillField}${OptionalPostfixToken<AutoFillCredentialField>}`\nexport type InputAutoCompleteAttribute = AutoFill | (string & {})\n\nexport interface InputHTMLAttributes extends HTMLAttributes {\n  accept?: string | undefined\n  alt?: string | undefined\n  autocomplete?: InputAutoCompleteAttribute | undefined\n  autofocus?: Booleanish | undefined\n  capture?: boolean | 'user' | 'environment' | undefined // https://www.w3.org/tr/html-media-capture/#the-capture-attribute\n  checked?: Booleanish | any[] | Set<any> | undefined // for IDE v-model multi-checkbox support\n  crossorigin?: string | undefined\n  disabled?: Booleanish | undefined\n  form?: string | undefined\n  formaction?: string | undefined\n  formenctype?: string | undefined\n  formmethod?: string | undefined\n  formnovalidate?: Booleanish | undefined\n  formtarget?: string | undefined\n  height?: Numberish | undefined\n  indeterminate?: boolean | undefined\n  list?: string | undefined\n  max?: Numberish | undefined\n  maxlength?: Numberish | undefined\n  min?: Numberish | undefined\n  minlength?: Numberish | undefined\n  multiple?: Booleanish | undefined\n  name?: string | undefined\n  pattern?: string | undefined\n  placeholder?: string | undefined\n  readonly?: Booleanish | undefined\n  required?: Booleanish | undefined\n  size?: Numberish | undefined\n  src?: string | undefined\n  step?: Numberish | undefined\n  type?: InputTypeHTMLAttribute | undefined\n  value?: any // we support :value to be bound to anything w/ v-model\n  width?: Numberish | undefined\n  onCancel?: ((payload: Event) => void) | undefined\n}\n\nexport interface KeygenHTMLAttributes extends HTMLAttributes {\n  autofocus?: Booleanish | undefined\n  challenge?: string | undefined\n  disabled?: Booleanish | undefined\n  form?: string | undefined\n  keytype?: string | undefined\n  keyparams?: string | undefined\n  name?: string | undefined\n}\n\nexport interface LabelHTMLAttributes extends HTMLAttributes {\n  for?: string | undefined\n  form?: string | undefined\n}\n\nexport interface LiHTMLAttributes extends HTMLAttributes {\n  value?: string | ReadonlyArray<string> | number | undefined\n}\n\nexport interface LinkHTMLAttributes extends HTMLAttributes {\n  as?: string | undefined\n  crossorigin?: string | undefined\n  href?: string | undefined\n  hreflang?: string | undefined\n  integrity?: string | undefined\n  media?: string | undefined\n  referrerpolicy?: HTMLAttributeReferrerPolicy | undefined\n  rel?: string | undefined\n  sizes?: string | undefined\n  type?: string | undefined\n  charset?: string | undefined\n}\n\nexport interface MapHTMLAttributes extends HTMLAttributes {\n  name?: string | undefined\n}\n\nexport interface MenuHTMLAttributes extends HTMLAttributes {\n  type?: string | undefined\n}\n\nexport interface MediaHTMLAttributes extends HTMLAttributes {\n  autoplay?: Booleanish | undefined\n  controls?: Booleanish | undefined\n  controlslist?: string | undefined\n  crossorigin?: string | undefined\n  loop?: Booleanish | undefined\n  mediagroup?: string | undefined\n  muted?: Booleanish | undefined\n  playsinline?: Booleanish | undefined\n  preload?: string | undefined\n  src?: string | undefined\n}\n\nexport interface MetaHTMLAttributes extends HTMLAttributes {\n  charset?: string | undefined\n  content?: string | undefined\n  httpequiv?: string | undefined\n  name?: string | undefined\n}\n\nexport interface MeterHTMLAttributes extends HTMLAttributes {\n  form?: string | undefined\n  high?: Numberish | undefined\n  low?: Numberish | undefined\n  max?: Numberish | undefined\n  min?: Numberish | undefined\n  optimum?: Numberish | undefined\n  value?: string | ReadonlyArray<string> | number | undefined\n}\n\nexport interface QuoteHTMLAttributes extends HTMLAttributes {\n  cite?: string | undefined\n}\n\nexport interface ObjectHTMLAttributes extends HTMLAttributes {\n  classid?: string | undefined\n  data?: string | undefined\n  form?: string | undefined\n  height?: Numberish | undefined\n  name?: string | undefined\n  type?: string | undefined\n  usemap?: string | undefined\n  width?: Numberish | undefined\n  wmode?: string | undefined\n}\n\nexport interface OlHTMLAttributes extends HTMLAttributes {\n  reversed?: Booleanish | undefined\n  start?: Numberish | undefined\n  type?: '1' | 'a' | 'A' | 'i' | 'I' | undefined\n}\n\nexport interface OptgroupHTMLAttributes extends HTMLAttributes {\n  disabled?: Booleanish | undefined\n  label?: string | undefined\n}\n\nexport interface OptionHTMLAttributes extends HTMLAttributes {\n  disabled?: Booleanish | undefined\n  label?: string | undefined\n  selected?: Booleanish | undefined\n  value?: any // we support :value to be bound to anything w/ v-model\n}\n\nexport interface OutputHTMLAttributes extends HTMLAttributes {\n  for?: string | undefined\n  form?: string | undefined\n  name?: string | undefined\n}\n\nexport interface ParamHTMLAttributes extends HTMLAttributes {\n  name?: string | undefined\n  value?: string | ReadonlyArray<string> | number | undefined\n}\n\nexport interface ProgressHTMLAttributes extends HTMLAttributes {\n  max?: Numberish | undefined\n  value?: string | ReadonlyArray<string> | number | undefined\n}\n\nexport interface ScriptHTMLAttributes extends HTMLAttributes {\n  async?: Booleanish | undefined\n  /** @deprecated */\n  charset?: string | undefined\n  crossorigin?: string | undefined\n  defer?: Booleanish | undefined\n  integrity?: string | undefined\n  nomodule?: Booleanish | undefined\n  referrerpolicy?: HTMLAttributeReferrerPolicy | undefined\n  nonce?: string | undefined\n  src?: string | undefined\n  type?: string | undefined\n}\n\nexport interface SelectHTMLAttributes extends HTMLAttributes {\n  autocomplete?: string | undefined\n  autofocus?: Booleanish | undefined\n  disabled?: Booleanish | undefined\n  form?: string | undefined\n  multiple?: Booleanish | undefined\n  name?: string | undefined\n  required?: Booleanish | undefined\n  size?: Numberish | undefined\n  value?: any // we support :value to be bound to anything w/ v-model\n}\n\nexport interface SourceHTMLAttributes extends HTMLAttributes {\n  media?: string | undefined\n  sizes?: string | undefined\n  src?: string | undefined\n  srcset?: string | undefined\n  type?: string | undefined\n}\n\nexport interface StyleHTMLAttributes extends HTMLAttributes {\n  media?: string | undefined\n  nonce?: string | undefined\n  scoped?: Booleanish | undefined\n  type?: string | undefined\n}\n\nexport interface TableHTMLAttributes extends HTMLAttributes {\n  cellpadding?: Numberish | undefined\n  cellspacing?: Numberish | undefined\n  summary?: string | undefined\n  width?: Numberish | undefined\n}\n\nexport interface TextareaHTMLAttributes extends HTMLAttributes {\n  autocomplete?: string | undefined\n  autofocus?: Booleanish | undefined\n  cols?: Numberish | undefined\n  dirname?: string | undefined\n  disabled?: Booleanish | undefined\n  form?: string | undefined\n  maxlength?: Numberish | undefined\n  minlength?: Numberish | undefined\n  name?: string | undefined\n  placeholder?: string | undefined\n  readonly?: Booleanish | undefined\n  required?: Booleanish | undefined\n  rows?: Numberish | undefined\n  value?: string | ReadonlyArray<string> | number | null | undefined\n  wrap?: string | undefined\n}\n\nexport interface TdHTMLAttributes extends HTMLAttributes {\n  align?: 'left' | 'center' | 'right' | 'justify' | 'char' | undefined\n  colspan?: Numberish | undefined\n  headers?: string | undefined\n  rowspan?: Numberish | undefined\n  scope?: string | undefined\n  abbr?: string | undefined\n  height?: Numberish | undefined\n  width?: Numberish | undefined\n  valign?: 'top' | 'middle' | 'bottom' | 'baseline' | undefined\n}\n\nexport interface ThHTMLAttributes extends HTMLAttributes {\n  align?: 'left' | 'center' | 'right' | 'justify' | 'char' | undefined\n  colspan?: Numberish | undefined\n  headers?: string | undefined\n  rowspan?: Numberish | undefined\n  scope?: string | undefined\n  abbr?: string | undefined\n}\n\nexport interface TimeHTMLAttributes extends HTMLAttributes {\n  datetime?: string | undefined\n}\n\nexport interface TrackHTMLAttributes extends HTMLAttributes {\n  default?: Booleanish | undefined\n  kind?: string | undefined\n  label?: string | undefined\n  src?: string | undefined\n  srclang?: string | undefined\n}\n\nexport interface VideoHTMLAttributes extends MediaHTMLAttributes {\n  height?: Numberish | undefined\n  playsinline?: Booleanish | undefined\n  poster?: string | undefined\n  width?: Numberish | undefined\n  disablePictureInPicture?: Booleanish | undefined\n  disableRemotePlayback?: Booleanish | undefined\n}\n\nexport interface WebViewHTMLAttributes extends HTMLAttributes {\n  allowfullscreen?: Booleanish | undefined\n  allowpopups?: Booleanish | undefined\n  autoFocus?: Booleanish | undefined\n  autosize?: Booleanish | undefined\n  blinkfeatures?: string | undefined\n  disableblinkfeatures?: string | undefined\n  disableguestresize?: Booleanish | undefined\n  disablewebsecurity?: Booleanish | undefined\n  guestinstance?: string | undefined\n  httpreferrer?: string | undefined\n  nodeintegration?: Booleanish | undefined\n  partition?: string | undefined\n  plugins?: Booleanish | undefined\n  preload?: string | undefined\n  src?: string | undefined\n  useragent?: string | undefined\n  webpreferences?: string | undefined\n}\n\nexport interface SVGAttributes extends AriaAttributes, EventHandlers<Events> {\n  innerHTML?: string | undefined\n\n  /**\n   * SVG Styling Attributes\n   * @see https://www.w3.org/TR/SVG/styling.html#ElementSpecificStyling\n   */\n  class?: ClassValue | undefined\n  style?: StyleValue | undefined\n\n  color?: string | undefined\n  height?: Numberish | undefined\n  id?: string | undefined\n  lang?: string | undefined\n  max?: Numberish | undefined\n  media?: string | undefined\n  method?: string | undefined\n  min?: Numberish | undefined\n  name?: string | undefined\n  target?: string | undefined\n  type?: string | undefined\n  width?: Numberish | undefined\n\n  // Other HTML properties supported by SVG elements in browsers\n  role?: string | undefined\n  tabindex?: Numberish | undefined\n  crossOrigin?: 'anonymous' | 'use-credentials' | '' | undefined\n\n  // SVG Specific attributes\n  'accent-height'?: Numberish | undefined\n  accumulate?: 'none' | 'sum' | undefined\n  additive?: 'replace' | 'sum' | undefined\n  'alignment-baseline'?:\n    | 'auto'\n    | 'baseline'\n    | 'before-edge'\n    | 'text-before-edge'\n    | 'middle'\n    | 'central'\n    | 'after-edge'\n    | 'text-after-edge'\n    | 'ideographic'\n    | 'alphabetic'\n    | 'hanging'\n    | 'mathematical'\n    | 'inherit'\n    | undefined\n  allowReorder?: 'no' | 'yes' | undefined\n  alphabetic?: Numberish | undefined\n  amplitude?: Numberish | undefined\n  'arabic-form'?: 'initial' | 'medial' | 'terminal' | 'isolated' | undefined\n  ascent?: Numberish | undefined\n  attributeName?: string | undefined\n  attributeType?: string | undefined\n  autoReverse?: Numberish | undefined\n  azimuth?: Numberish | undefined\n  baseFrequency?: Numberish | undefined\n  'baseline-shift'?: Numberish | undefined\n  baseProfile?: Numberish | undefined\n  bbox?: Numberish | undefined\n  begin?: Numberish | undefined\n  bias?: Numberish | undefined\n  by?: Numberish | undefined\n  calcMode?: Numberish | undefined\n  'cap-height'?: Numberish | undefined\n  clip?: Numberish | undefined\n  'clip-path'?: string | undefined\n  clipPathUnits?: Numberish | undefined\n  'clip-rule'?: Numberish | undefined\n  'color-interpolation'?: Numberish | undefined\n  'color-interpolation-filters'?:\n    | 'auto'\n    | 'sRGB'\n    | 'linearRGB'\n    | 'inherit'\n    | undefined\n  'color-profile'?: Numberish | undefined\n  'color-rendering'?: Numberish | undefined\n  contentScriptType?: Numberish | undefined\n  contentStyleType?: Numberish | undefined\n  cursor?: Numberish | undefined\n  cx?: Numberish | undefined\n  cy?: Numberish | undefined\n  d?: string | undefined\n  decelerate?: Numberish | undefined\n  descent?: Numberish | undefined\n  diffuseConstant?: Numberish | undefined\n  direction?: Numberish | undefined\n  display?: Numberish | undefined\n  divisor?: Numberish | undefined\n  'dominant-baseline'?: Numberish | undefined\n  dur?: Numberish | undefined\n  dx?: Numberish | undefined\n  dy?: Numberish | undefined\n  edgeMode?: Numberish | undefined\n  elevation?: Numberish | undefined\n  'enable-background'?: Numberish | undefined\n  end?: Numberish | undefined\n  exponent?: Numberish | undefined\n  externalResourcesRequired?: Numberish | undefined\n  fill?: string | undefined\n  'fill-opacity'?: Numberish | undefined\n  'fill-rule'?: 'nonzero' | 'evenodd' | 'inherit' | undefined\n  filter?: string | undefined\n  filterRes?: Numberish | undefined\n  filterUnits?: Numberish | undefined\n  'flood-color'?: Numberish | undefined\n  'flood-opacity'?: Numberish | undefined\n  focusable?: Numberish | undefined\n  'font-family'?: string | undefined\n  'font-size'?: Numberish | undefined\n  'font-size-adjust'?: Numberish | undefined\n  'font-stretch'?: Numberish | undefined\n  'font-style'?: Numberish | undefined\n  'font-variant'?: Numberish | undefined\n  'font-weight'?: Numberish | undefined\n  format?: Numberish | undefined\n  from?: Numberish | undefined\n  fx?: Numberish | undefined\n  fy?: Numberish | undefined\n  g1?: Numberish | undefined\n  g2?: Numberish | undefined\n  'glyph-name'?: Numberish | undefined\n  'glyph-orientation-horizontal'?: Numberish | undefined\n  'glyph-orientation-vertical'?: Numberish | undefined\n  glyphRef?: Numberish | undefined\n  gradientTransform?: string | undefined\n  gradientUnits?: string | undefined\n  hanging?: Numberish | undefined\n  'horiz-adv-x'?: Numberish | undefined\n  'horiz-origin-x'?: Numberish | undefined\n  href?: string | undefined\n  ideographic?: Numberish | undefined\n  'image-rendering'?: Numberish | undefined\n  in2?: Numberish | undefined\n  in?: string | undefined\n  intercept?: Numberish | undefined\n  k1?: Numberish | undefined\n  k2?: Numberish | undefined\n  k3?: Numberish | undefined\n  k4?: Numberish | undefined\n  k?: Numberish | undefined\n  kernelMatrix?: Numberish | undefined\n  kernelUnitLength?: Numberish | undefined\n  kerning?: Numberish | undefined\n  keyPoints?: Numberish | undefined\n  keySplines?: Numberish | undefined\n  keyTimes?: Numberish | undefined\n  lengthAdjust?: Numberish | undefined\n  'letter-spacing'?: Numberish | undefined\n  'lighting-color'?: Numberish | undefined\n  limitingConeAngle?: Numberish | undefined\n  local?: Numberish | undefined\n  'marker-end'?: string | undefined\n  markerHeight?: Numberish | undefined\n  'marker-mid'?: string | undefined\n  'marker-start'?: string | undefined\n  markerUnits?: Numberish | undefined\n  markerWidth?: Numberish | undefined\n  mask?: string | undefined\n  maskContentUnits?: Numberish | undefined\n  maskUnits?: Numberish | undefined\n  mathematical?: Numberish | undefined\n  mode?: Numberish | undefined\n  numOctaves?: Numberish | undefined\n  offset?: Numberish | undefined\n  opacity?: Numberish | undefined\n  operator?: Numberish | undefined\n  order?: Numberish | undefined\n  orient?: Numberish | undefined\n  orientation?: Numberish | undefined\n  origin?: Numberish | undefined\n  overflow?: Numberish | undefined\n  'overline-position'?: Numberish | undefined\n  'overline-thickness'?: Numberish | undefined\n  'paint-order'?: Numberish | undefined\n  'panose-1'?: Numberish | undefined\n  pathLength?: Numberish | undefined\n  patternContentUnits?: string | undefined\n  patternTransform?: Numberish | undefined\n  patternUnits?: string | undefined\n  'pointer-events'?: Numberish | undefined\n  points?: string | undefined\n  pointsAtX?: Numberish | undefined\n  pointsAtY?: Numberish | undefined\n  pointsAtZ?: Numberish | undefined\n  preserveAlpha?: Numberish | undefined\n  preserveAspectRatio?: string | undefined\n  primitiveUnits?: Numberish | undefined\n  r?: Numberish | undefined\n  radius?: Numberish | undefined\n  refX?: Numberish | undefined\n  refY?: Numberish | undefined\n  renderingIntent?: Numberish | undefined\n  repeatCount?: Numberish | undefined\n  repeatDur?: Numberish | undefined\n  requiredExtensions?: Numberish | undefined\n  requiredFeatures?: Numberish | undefined\n  restart?: Numberish | undefined\n  result?: string | undefined\n  rotate?: Numberish | undefined\n  rx?: Numberish | undefined\n  ry?: Numberish | undefined\n  scale?: Numberish | undefined\n  seed?: Numberish | undefined\n  'shape-rendering'?: Numberish | undefined\n  slope?: Numberish | undefined\n  spacing?: Numberish | undefined\n  specularConstant?: Numberish | undefined\n  specularExponent?: Numberish | undefined\n  speed?: Numberish | undefined\n  spreadMethod?: string | undefined\n  startOffset?: Numberish | undefined\n  stdDeviation?: Numberish | undefined\n  stemh?: Numberish | undefined\n  stemv?: Numberish | undefined\n  stitchTiles?: Numberish | undefined\n  'stop-color'?: string | undefined\n  'stop-opacity'?: Numberish | undefined\n  'strikethrough-position'?: Numberish | undefined\n  'strikethrough-thickness'?: Numberish | undefined\n  string?: Numberish | undefined\n  stroke?: string | undefined\n  'stroke-dasharray'?: Numberish | undefined\n  'stroke-dashoffset'?: Numberish | undefined\n  'stroke-linecap'?: 'butt' | 'round' | 'square' | 'inherit' | undefined\n  'stroke-linejoin'?: 'miter' | 'round' | 'bevel' | 'inherit' | undefined\n  'stroke-miterlimit'?: Numberish | undefined\n  'stroke-opacity'?: Numberish | undefined\n  'stroke-width'?: Numberish | undefined\n  surfaceScale?: Numberish | undefined\n  systemLanguage?: Numberish | undefined\n  tableValues?: Numberish | undefined\n  targetX?: Numberish | undefined\n  targetY?: Numberish | undefined\n  'text-anchor'?: string | undefined\n  'text-decoration'?: Numberish | undefined\n  textLength?: Numberish | undefined\n  'text-rendering'?: Numberish | undefined\n  to?: Numberish | undefined\n  transform?: string | undefined\n  u1?: Numberish | undefined\n  u2?: Numberish | undefined\n  'underline-position'?: Numberish | undefined\n  'underline-thickness'?: Numberish | undefined\n  unicode?: Numberish | undefined\n  'unicode-bidi'?: Numberish | undefined\n  'unicode-range'?: Numberish | undefined\n  'unitsPer-em'?: Numberish | undefined\n  'v-alphabetic'?: Numberish | undefined\n  values?: string | undefined\n  'vector-effect'?: Numberish | undefined\n  version?: string | undefined\n  'vert-adv-y'?: Numberish | undefined\n  'vert-origin-x'?: Numberish | undefined\n  'vert-origin-y'?: Numberish | undefined\n  'v-hanging'?: Numberish | undefined\n  'v-ideographic'?: Numberish | undefined\n  viewBox?: string | undefined\n  viewTarget?: Numberish | undefined\n  visibility?: Numberish | undefined\n  'v-mathematical'?: Numberish | undefined\n  widths?: Numberish | undefined\n  'word-spacing'?: Numberish | undefined\n  'writing-mode'?: Numberish | undefined\n  x1?: Numberish | undefined\n  x2?: Numberish | undefined\n  x?: Numberish | undefined\n  xChannelSelector?: string | undefined\n  'x-height'?: Numberish | undefined\n  xlinkActuate?: string | undefined\n  xlinkArcrole?: string | undefined\n  xlinkHref?: string | undefined\n  xlinkRole?: string | undefined\n  xlinkShow?: string | undefined\n  xlinkTitle?: string | undefined\n  xlinkType?: string | undefined\n  xmlns?: string | undefined\n  xmlnsXlink?: string | undefined\n  y1?: Numberish | undefined\n  y2?: Numberish | undefined\n  y?: Numberish | undefined\n  yChannelSelector?: string | undefined\n  z?: Numberish | undefined\n  zoomAndPan?: string | undefined\n}\n\nexport interface IntrinsicElementAttributes {\n  a: AnchorHTMLAttributes\n  abbr: HTMLAttributes\n  address: HTMLAttributes\n  area: AreaHTMLAttributes\n  article: HTMLAttributes\n  aside: HTMLAttributes\n  audio: AudioHTMLAttributes\n  b: HTMLAttributes\n  base: BaseHTMLAttributes\n  bdi: HTMLAttributes\n  bdo: HTMLAttributes\n  blockquote: BlockquoteHTMLAttributes\n  body: HTMLAttributes\n  br: HTMLAttributes\n  button: ButtonHTMLAttributes\n  canvas: CanvasHTMLAttributes\n  caption: HTMLAttributes\n  cite: HTMLAttributes\n  code: HTMLAttributes\n  col: ColHTMLAttributes\n  colgroup: ColgroupHTMLAttributes\n  data: DataHTMLAttributes\n  datalist: HTMLAttributes\n  dd: HTMLAttributes\n  del: DelHTMLAttributes\n  details: DetailsHTMLAttributes\n  dfn: HTMLAttributes\n  dialog: DialogHTMLAttributes\n  div: HTMLAttributes\n  dl: HTMLAttributes\n  dt: HTMLAttributes\n  em: HTMLAttributes\n  embed: EmbedHTMLAttributes\n  fieldset: FieldsetHTMLAttributes\n  figcaption: HTMLAttributes\n  figure: HTMLAttributes\n  footer: HTMLAttributes\n  form: FormHTMLAttributes\n  h1: HTMLAttributes\n  h2: HTMLAttributes\n  h3: HTMLAttributes\n  h4: HTMLAttributes\n  h5: HTMLAttributes\n  h6: HTMLAttributes\n  head: HTMLAttributes\n  header: HTMLAttributes\n  hgroup: HTMLAttributes\n  hr: HTMLAttributes\n  html: HtmlHTMLAttributes\n  i: HTMLAttributes\n  iframe: IframeHTMLAttributes\n  img: ImgHTMLAttributes\n  input: InputHTMLAttributes\n  ins: InsHTMLAttributes\n  kbd: HTMLAttributes\n  keygen: KeygenHTMLAttributes\n  label: LabelHTMLAttributes\n  legend: HTMLAttributes\n  li: LiHTMLAttributes\n  link: LinkHTMLAttributes\n  main: HTMLAttributes\n  map: MapHTMLAttributes\n  mark: HTMLAttributes\n  menu: MenuHTMLAttributes\n  meta: MetaHTMLAttributes\n  meter: MeterHTMLAttributes\n  nav: HTMLAttributes\n  noindex: HTMLAttributes\n  noscript: HTMLAttributes\n  object: ObjectHTMLAttributes\n  ol: OlHTMLAttributes\n  optgroup: OptgroupHTMLAttributes\n  option: OptionHTMLAttributes\n  output: OutputHTMLAttributes\n  p: HTMLAttributes\n  param: ParamHTMLAttributes\n  picture: HTMLAttributes\n  pre: HTMLAttributes\n  progress: ProgressHTMLAttributes\n  q: QuoteHTMLAttributes\n  rp: HTMLAttributes\n  rt: HTMLAttributes\n  ruby: HTMLAttributes\n  s: HTMLAttributes\n  samp: HTMLAttributes\n  script: ScriptHTMLAttributes\n  section: HTMLAttributes\n  select: SelectHTMLAttributes\n  small: HTMLAttributes\n  source: SourceHTMLAttributes\n  span: HTMLAttributes\n  strong: HTMLAttributes\n  style: StyleHTMLAttributes\n  sub: HTMLAttributes\n  summary: HTMLAttributes\n  sup: HTMLAttributes\n  table: TableHTMLAttributes\n  template: HTMLAttributes\n  tbody: HTMLAttributes\n  td: TdHTMLAttributes\n  textarea: TextareaHTMLAttributes\n  tfoot: HTMLAttributes\n  th: ThHTMLAttributes\n  thead: HTMLAttributes\n  time: TimeHTMLAttributes\n  title: HTMLAttributes\n  tr: HTMLAttributes\n  track: TrackHTMLAttributes\n  u: HTMLAttributes\n  ul: HTMLAttributes\n  var: HTMLAttributes\n  video: VideoHTMLAttributes\n  wbr: HTMLAttributes\n  webview: WebViewHTMLAttributes\n\n  // SVG\n  svg: SVGAttributes\n\n  animate: SVGAttributes\n  animateMotion: SVGAttributes\n  animateTransform: SVGAttributes\n  circle: SVGAttributes\n  clipPath: SVGAttributes\n  defs: SVGAttributes\n  desc: SVGAttributes\n  ellipse: SVGAttributes\n  feBlend: SVGAttributes\n  feColorMatrix: SVGAttributes\n  feComponentTransfer: SVGAttributes\n  feComposite: SVGAttributes\n  feConvolveMatrix: SVGAttributes\n  feDiffuseLighting: SVGAttributes\n  feDisplacementMap: SVGAttributes\n  feDistantLight: SVGAttributes\n  feDropShadow: SVGAttributes\n  feFlood: SVGAttributes\n  feFuncA: SVGAttributes\n  feFuncB: SVGAttributes\n  feFuncG: SVGAttributes\n  feFuncR: SVGAttributes\n  feGaussianBlur: SVGAttributes\n  feImage: SVGAttributes\n  feMerge: SVGAttributes\n  feMergeNode: SVGAttributes\n  feMorphology: SVGAttributes\n  feOffset: SVGAttributes\n  fePointLight: SVGAttributes\n  feSpecularLighting: SVGAttributes\n  feSpotLight: SVGAttributes\n  feTile: SVGAttributes\n  feTurbulence: SVGAttributes\n  filter: SVGAttributes\n  foreignObject: SVGAttributes\n  g: SVGAttributes\n  image: SVGAttributes\n  line: SVGAttributes\n  linearGradient: SVGAttributes\n  marker: SVGAttributes\n  mask: SVGAttributes\n  metadata: SVGAttributes\n  mpath: SVGAttributes\n  path: SVGAttributes\n  pattern: SVGAttributes\n  polygon: SVGAttributes\n  polyline: SVGAttributes\n  radialGradient: SVGAttributes\n  rect: SVGAttributes\n  set: SVGAttributes\n  stop: SVGAttributes\n  switch: SVGAttributes\n  symbol: SVGAttributes\n  text: SVGAttributes\n  textPath: SVGAttributes\n  tspan: SVGAttributes\n  use: SVGAttributes\n  view: SVGAttributes\n}\n\nexport interface Events {\n  // clipboard events\n  onCopy: ClipboardEvent\n  onCut: ClipboardEvent\n  onPaste: ClipboardEvent\n\n  // composition events\n  onCompositionend: CompositionEvent\n  onCompositionstart: CompositionEvent\n  onCompositionupdate: CompositionEvent\n\n  // drag drop events\n  onDrag: DragEvent\n  onDragend: DragEvent\n  onDragenter: DragEvent\n  onDragexit: DragEvent\n  onDragleave: DragEvent\n  onDragover: DragEvent\n  onDragstart: DragEvent\n  onDrop: DragEvent\n\n  // focus events\n  onFocus: FocusEvent\n  onFocusin: FocusEvent\n  onFocusout: FocusEvent\n  onBlur: FocusEvent\n\n  // form events\n  onChange: Event\n  onBeforeinput: InputEvent\n  onFormdata: FormDataEvent\n  onInput: InputEvent\n  onReset: Event\n  onSubmit: SubmitEvent\n  onInvalid: Event\n\n  // fullscreen events\n  onFullscreenchange: Event\n  onFullscreenerror: Event\n\n  // image events\n  onLoad: Event\n  onError: Event\n\n  // keyboard events\n  onKeydown: KeyboardEvent\n  onKeypress: KeyboardEvent\n  onKeyup: KeyboardEvent\n\n  // mouse events\n  onDblclick: MouseEvent\n  onMousedown: MouseEvent\n  onMouseenter: MouseEvent\n  onMouseleave: MouseEvent\n  onMousemove: MouseEvent\n  onMouseout: MouseEvent\n  onMouseover: MouseEvent\n  onMouseup: MouseEvent\n\n  // media events\n  onAbort: UIEvent\n  onCanplay: Event\n  onCanplaythrough: Event\n  onDurationchange: Event\n  onEmptied: Event\n  onEncrypted: MediaEncryptedEvent\n  onEnded: Event\n  onLoadeddata: Event\n  onLoadedmetadata: Event\n  onLoadstart: Event\n  onPause: Event\n  onPlay: Event\n  onPlaying: Event\n  onProgress: ProgressEvent\n  onRatechange: Event\n  onSeeked: Event\n  onSeeking: Event\n  onStalled: Event\n  onSuspend: Event\n  onTimeupdate: Event\n  onVolumechange: Event\n  onWaiting: Event\n\n  // selection events\n  onSelect: Event\n\n  // scroll events\n  onScroll: Event\n  onScrollend: Event\n\n  // touch events\n  onTouchcancel: TouchEvent\n  onTouchend: TouchEvent\n  onTouchmove: TouchEvent\n  onTouchstart: TouchEvent\n\n  // pointer events\n  onAuxclick: PointerEvent\n  onClick: PointerEvent\n  onContextmenu: PointerEvent\n  onGotpointercapture: PointerEvent\n  onLostpointercapture: PointerEvent\n  onPointerdown: PointerEvent\n  onPointermove: PointerEvent\n  onPointerup: PointerEvent\n  onPointercancel: PointerEvent\n  onPointerenter: PointerEvent\n  onPointerleave: PointerEvent\n  onPointerover: PointerEvent\n  onPointerout: PointerEvent\n\n  // popover events\n  onBeforetoggle: ToggleEvent\n  onToggle: ToggleEvent\n\n  // wheel events\n  onWheel: WheelEvent\n\n  // animation events\n  onAnimationcancel: AnimationEvent\n  onAnimationstart: AnimationEvent\n  onAnimationend: AnimationEvent\n  onAnimationiteration: AnimationEvent\n\n  // security policy events\n  onSecuritypolicyviolation: SecurityPolicyViolationEvent\n\n  // transition events\n  onTransitioncancel: TransitionEvent\n  onTransitionend: TransitionEvent\n  onTransitionrun: TransitionEvent\n  onTransitionstart: TransitionEvent\n}\n\ntype EventHandlers<E> = {\n  [K in keyof E]?: E[K] extends (...args: any) => any\n    ? E[K]\n    : (payload: E[K]) => void\n}\n\nimport type { VNodeRef } from '@vue/runtime-core'\n\nexport interface ReservedProps {\n  key?: PropertyKey | undefined\n  ref?: VNodeRef | undefined\n  ref_for?: boolean | undefined\n  ref_key?: string | undefined\n}\n\nexport type NativeElements = {\n  [K in keyof IntrinsicElementAttributes]: IntrinsicElementAttributes[K] &\n    ReservedProps\n}\n"
  },
  {
    "path": "packages/runtime-dom/src/modules/attrs.ts",
    "content": "import {\n  NOOP,\n  includeBooleanAttr,\n  isSpecialBooleanAttr,\n  isSymbol,\n  makeMap,\n} from '@vue/shared'\nimport {\n  type ComponentInternalInstance,\n  DeprecationTypes,\n  compatUtils,\n} from '@vue/runtime-core'\n\nexport const xlinkNS = 'http://www.w3.org/1999/xlink'\n\nexport function patchAttr(\n  el: Element,\n  key: string,\n  value: any,\n  isSVG: boolean,\n  instance?: ComponentInternalInstance | null,\n  isBoolean: boolean = isSpecialBooleanAttr(key),\n): void {\n  if (isSVG && key.startsWith('xlink:')) {\n    if (value == null) {\n      el.removeAttributeNS(xlinkNS, key.slice(6, key.length))\n    } else {\n      el.setAttributeNS(xlinkNS, key, value)\n    }\n  } else {\n    if (__COMPAT__ && compatCoerceAttr(el, key, value, instance)) {\n      return\n    }\n\n    // note we are only checking boolean attributes that don't have a\n    // corresponding dom prop of the same name here.\n    if (value == null || (isBoolean && !includeBooleanAttr(value))) {\n      el.removeAttribute(key)\n    } else {\n      // attribute value is a string https://html.spec.whatwg.org/multipage/dom.html#attributes\n      el.setAttribute(\n        key,\n        isBoolean ? '' : isSymbol(value) ? String(value) : value,\n      )\n    }\n  }\n}\n\n// 2.x compat\nconst isEnumeratedAttr = __COMPAT__\n  ? /*@__PURE__*/ makeMap('contenteditable,draggable,spellcheck')\n  : NOOP\n\nexport function compatCoerceAttr(\n  el: Element,\n  key: string,\n  value: unknown,\n  instance: ComponentInternalInstance | null = null,\n): boolean {\n  if (isEnumeratedAttr(key)) {\n    const v2CoercedValue =\n      value === undefined\n        ? null\n        : value === null || value === false || value === 'false'\n          ? 'false'\n          : 'true'\n    if (\n      v2CoercedValue &&\n      compatUtils.softAssertCompatEnabled(\n        DeprecationTypes.ATTR_ENUMERATED_COERCION,\n        instance,\n        key,\n        value,\n        v2CoercedValue,\n      )\n    ) {\n      el.setAttribute(key, v2CoercedValue)\n      return true\n    }\n  } else if (\n    value === false &&\n    !(el.tagName === 'INPUT' && key === 'value') &&\n    !isSpecialBooleanAttr(key) &&\n    compatUtils.isCompatEnabled(DeprecationTypes.ATTR_FALSE_VALUE, instance)\n  ) {\n    compatUtils.warnDeprecation(\n      DeprecationTypes.ATTR_FALSE_VALUE,\n      instance,\n      key,\n    )\n    el.removeAttribute(key)\n    return true\n  }\n  return false\n}\n"
  },
  {
    "path": "packages/runtime-dom/src/modules/class.ts",
    "content": "import { type ElementWithTransition, vtcKey } from '../components/Transition'\n\n// compiler should normalize class + :class bindings on the same element\n// into a single binding ['staticClass', dynamic]\nexport function patchClass(\n  el: Element,\n  value: string | null,\n  isSVG: boolean,\n): void {\n  // directly setting className should be faster than setAttribute in theory\n  // if this is an element during a transition, take the temporary transition\n  // classes into account.\n  const transitionClasses = (el as ElementWithTransition)[vtcKey]\n  if (transitionClasses) {\n    value = (\n      value ? [value, ...transitionClasses] : [...transitionClasses]\n    ).join(' ')\n  }\n  if (value == null) {\n    el.removeAttribute('class')\n  } else if (isSVG) {\n    el.setAttribute('class', value)\n  } else {\n    el.className = value\n  }\n}\n"
  },
  {
    "path": "packages/runtime-dom/src/modules/events.ts",
    "content": "import { NOOP, hyphenate, isArray, isFunction } from '@vue/shared'\nimport {\n  type ComponentInternalInstance,\n  ErrorCodes,\n  callWithAsyncErrorHandling,\n  warn,\n} from '@vue/runtime-core'\n\ninterface Invoker extends EventListener {\n  value: EventValue\n  attached: number\n}\n\ntype EventValue = Function | Function[]\n\nexport function addEventListener(\n  el: Element,\n  event: string,\n  handler: EventListener,\n  options?: EventListenerOptions,\n): void {\n  el.addEventListener(event, handler, options)\n}\n\nexport function removeEventListener(\n  el: Element,\n  event: string,\n  handler: EventListener,\n  options?: EventListenerOptions,\n): void {\n  el.removeEventListener(event, handler, options)\n}\n\nconst veiKey: unique symbol = Symbol('_vei')\n\nexport function patchEvent(\n  el: Element & { [veiKey]?: Record<string, Invoker | undefined> },\n  rawName: string,\n  prevValue: EventValue | null,\n  nextValue: EventValue | unknown,\n  instance: ComponentInternalInstance | null = null,\n): void {\n  // vei = vue event invokers\n  const invokers = el[veiKey] || (el[veiKey] = {})\n  const existingInvoker = invokers[rawName]\n  if (nextValue && existingInvoker) {\n    // patch\n    existingInvoker.value = __DEV__\n      ? sanitizeEventValue(nextValue, rawName)\n      : (nextValue as EventValue)\n  } else {\n    const [name, options] = parseName(rawName)\n    if (nextValue) {\n      // add\n      const invoker = (invokers[rawName] = createInvoker(\n        __DEV__\n          ? sanitizeEventValue(nextValue, rawName)\n          : (nextValue as EventValue),\n        instance,\n      ))\n      addEventListener(el, name, invoker, options)\n    } else if (existingInvoker) {\n      // remove\n      removeEventListener(el, name, existingInvoker, options)\n      invokers[rawName] = undefined\n    }\n  }\n}\n\nconst optionsModifierRE = /(?:Once|Passive|Capture)$/\n\nfunction parseName(name: string): [string, EventListenerOptions | undefined] {\n  let options: EventListenerOptions | undefined\n  if (optionsModifierRE.test(name)) {\n    options = {}\n    let m\n    while ((m = name.match(optionsModifierRE))) {\n      name = name.slice(0, name.length - m[0].length)\n      ;(options as any)[m[0].toLowerCase()] = true\n    }\n  }\n  const event = name[2] === ':' ? name.slice(3) : hyphenate(name.slice(2))\n  return [event, options]\n}\n\n// To avoid the overhead of repeatedly calling Date.now(), we cache\n// and use the same timestamp for all event listeners attached in the same tick.\nlet cachedNow: number = 0\nconst p = /*@__PURE__*/ Promise.resolve()\nconst getNow = () =>\n  cachedNow || (p.then(() => (cachedNow = 0)), (cachedNow = Date.now()))\n\nfunction createInvoker(\n  initialValue: EventValue,\n  instance: ComponentInternalInstance | null,\n) {\n  const invoker: Invoker = (e: Event & { _vts?: number }) => {\n    // async edge case vuejs/vue#6566\n    // inner click event triggers patch, event handler\n    // attached to outer element during patch, and triggered again. This\n    // happens because browsers fire microtask ticks between event propagation.\n    // this no longer happens for templates in Vue 3, but could still be\n    // theoretically possible for hand-written render functions.\n    // the solution: we save the timestamp when a handler is attached,\n    // and also attach the timestamp to any event that was handled by vue\n    // for the first time (to avoid inconsistent event timestamp implementations\n    // or events fired from iframes, e.g. #2513)\n    // The handler would only fire if the event passed to it was fired\n    // AFTER it was attached.\n    if (!e._vts) {\n      e._vts = Date.now()\n    } else if (e._vts <= invoker.attached) {\n      return\n    }\n    callWithAsyncErrorHandling(\n      patchStopImmediatePropagation(e, invoker.value),\n      instance,\n      ErrorCodes.NATIVE_EVENT_HANDLER,\n      [e],\n    )\n  }\n  invoker.value = initialValue\n  invoker.attached = getNow()\n  return invoker\n}\n\nfunction sanitizeEventValue(value: unknown, propName: string): EventValue {\n  if (isFunction(value) || isArray(value)) {\n    return value as EventValue\n  }\n  warn(\n    `Wrong type passed as event handler to ${propName} - did you forget @ or : ` +\n      `in front of your prop?\\nExpected function or array of functions, received type ${typeof value}.`,\n  )\n  return NOOP\n}\n\nfunction patchStopImmediatePropagation(\n  e: Event,\n  value: EventValue,\n): EventValue {\n  if (isArray(value)) {\n    const originalStop = e.stopImmediatePropagation\n    e.stopImmediatePropagation = () => {\n      originalStop.call(e)\n      ;(e as any)._stopped = true\n    }\n    return (value as Function[]).map(\n      fn => (e: Event) => !(e as any)._stopped && fn && fn(e),\n    )\n  } else {\n    return value\n  }\n}\n"
  },
  {
    "path": "packages/runtime-dom/src/modules/props.ts",
    "content": "import { DeprecationTypes, compatUtils, warn } from '@vue/runtime-core'\nimport { includeBooleanAttr } from '@vue/shared'\nimport { unsafeToTrustedHTML } from '../nodeOps'\n\n// functions. The user is responsible for using them with only trusted content.\nexport function patchDOMProp(\n  el: any,\n  key: string,\n  value: any,\n  parentComponent: any,\n  attrName?: string,\n): void {\n  // __UNSAFE__\n  // Reason: potentially setting innerHTML.\n  // This can come from explicit usage of v-html or innerHTML as a prop in render\n  if (key === 'innerHTML' || key === 'textContent') {\n    // null value case is handled in renderer patchElement before patching\n    // children\n    if (value != null) {\n      el[key] = key === 'innerHTML' ? unsafeToTrustedHTML(value) : value\n    }\n    return\n  }\n\n  const tag = el.tagName\n\n  if (\n    key === 'value' &&\n    tag !== 'PROGRESS' &&\n    // custom elements may use _value internally\n    !tag.includes('-')\n  ) {\n    // #4956: <option> value will fallback to its text content so we need to\n    // compare against its attribute value instead.\n    const oldValue =\n      tag === 'OPTION' ? el.getAttribute('value') || '' : el.value\n    const newValue =\n      value == null\n        ? // #11647: value should be set as empty string for null and undefined,\n          // but <input type=\"checkbox\"> should be set as 'on'.\n          el.type === 'checkbox'\n          ? 'on'\n          : ''\n        : String(value)\n    if (oldValue !== newValue || !('_value' in el)) {\n      el.value = newValue\n    }\n    if (value == null) {\n      el.removeAttribute(key)\n    }\n    // store value as _value as well since\n    // non-string values will be stringified.\n    el._value = value\n    return\n  }\n\n  let needRemove = false\n  if (value === '' || value == null) {\n    const type = typeof el[key]\n    if (type === 'boolean') {\n      // e.g. <select multiple> compiles to { multiple: '' }\n      value = includeBooleanAttr(value)\n    } else if (value == null && type === 'string') {\n      // e.g. <div :id=\"null\">\n      value = ''\n      needRemove = true\n    } else if (type === 'number') {\n      // e.g. <img :width=\"null\">\n      value = 0\n      needRemove = true\n    }\n  } else {\n    if (\n      __COMPAT__ &&\n      value === false &&\n      compatUtils.isCompatEnabled(\n        DeprecationTypes.ATTR_FALSE_VALUE,\n        parentComponent,\n      )\n    ) {\n      const type = typeof el[key]\n      if (type === 'string' || type === 'number') {\n        __DEV__ &&\n          compatUtils.warnDeprecation(\n            DeprecationTypes.ATTR_FALSE_VALUE,\n            parentComponent,\n            key,\n          )\n        value = type === 'number' ? 0 : ''\n        needRemove = true\n      }\n    }\n  }\n\n  // some properties perform value validation and throw,\n  // some properties has getter, no setter, will error in 'use strict'\n  // eg. <select :type=\"null\"></select> <select :willValidate=\"null\"></select>\n  try {\n    el[key] = value\n  } catch (e: any) {\n    // do not warn if value is auto-coerced from nullish values\n    if (__DEV__ && !needRemove) {\n      warn(\n        `Failed setting prop \"${key}\" on <${tag.toLowerCase()}>: ` +\n          `value ${value} is invalid.`,\n        e,\n      )\n    }\n  }\n  needRemove && el.removeAttribute(attrName || key)\n}\n"
  },
  {
    "path": "packages/runtime-dom/src/modules/style.ts",
    "content": "import { capitalize, hyphenate, isArray, isString } from '@vue/shared'\nimport { camelize, warn } from '@vue/runtime-core'\nimport {\n  type VShowElement,\n  vShowHidden,\n  vShowOriginalDisplay,\n} from '../directives/vShow'\nimport { CSS_VAR_TEXT } from '../helpers/useCssVars'\n\ntype Style = string | Record<string, string | string[]> | null\n\nconst displayRE = /(?:^|;)\\s*display\\s*:/\n\nexport function patchStyle(el: Element, prev: Style, next: Style): void {\n  const style = (el as HTMLElement).style\n  const isCssString = isString(next)\n  let hasControlledDisplay = false\n  if (next && !isCssString) {\n    if (prev) {\n      if (!isString(prev)) {\n        for (const key in prev) {\n          if (next[key] == null) {\n            setStyle(style, key, '')\n          }\n        }\n      } else {\n        for (const prevStyle of prev.split(';')) {\n          const key = prevStyle.slice(0, prevStyle.indexOf(':')).trim()\n          if (next[key] == null) {\n            setStyle(style, key, '')\n          }\n        }\n      }\n    }\n    for (const key in next) {\n      if (key === 'display') {\n        hasControlledDisplay = true\n      }\n      setStyle(style, key, next[key])\n    }\n  } else {\n    if (isCssString) {\n      if (prev !== next) {\n        // #9821\n        const cssVarText = (style as any)[CSS_VAR_TEXT]\n        if (cssVarText) {\n          ;(next as string) += ';' + cssVarText\n        }\n        style.cssText = next as string\n        hasControlledDisplay = displayRE.test(next)\n      }\n    } else if (prev) {\n      el.removeAttribute('style')\n    }\n  }\n  // indicates the element also has `v-show`.\n  if (vShowOriginalDisplay in el) {\n    // make v-show respect the current v-bind style display when shown\n    el[vShowOriginalDisplay] = hasControlledDisplay ? style.display : ''\n    // if v-show is in hidden state, v-show has higher priority\n    if ((el as VShowElement)[vShowHidden]) {\n      style.display = 'none'\n    }\n  }\n}\n\nconst semicolonRE = /[^\\\\];\\s*$/\nconst importantRE = /\\s*!important$/\n\nfunction setStyle(\n  style: CSSStyleDeclaration,\n  name: string,\n  val: string | string[],\n) {\n  if (isArray(val)) {\n    val.forEach(v => setStyle(style, name, v))\n  } else {\n    if (val == null) val = ''\n    if (__DEV__) {\n      if (semicolonRE.test(val)) {\n        warn(\n          `Unexpected semicolon at the end of '${name}' style value: '${val}'`,\n        )\n      }\n    }\n    if (name.startsWith('--')) {\n      // custom property definition\n      style.setProperty(name, val)\n    } else {\n      const prefixed = autoPrefix(style, name)\n      if (importantRE.test(val)) {\n        // !important\n        style.setProperty(\n          hyphenate(prefixed),\n          val.replace(importantRE, ''),\n          'important',\n        )\n      } else {\n        style[prefixed as any] = val\n      }\n    }\n  }\n}\n\nconst prefixes = ['Webkit', 'Moz', 'ms']\nconst prefixCache: Record<string, string> = {}\n\nfunction autoPrefix(style: CSSStyleDeclaration, rawName: string): string {\n  const cached = prefixCache[rawName]\n  if (cached) {\n    return cached\n  }\n  let name = camelize(rawName)\n  if (name !== 'filter' && name in style) {\n    return (prefixCache[rawName] = name)\n  }\n  name = capitalize(name)\n  for (let i = 0; i < prefixes.length; i++) {\n    const prefixed = prefixes[i] + name\n    if (prefixed in style) {\n      return (prefixCache[rawName] = prefixed)\n    }\n  }\n  return rawName\n}\n"
  },
  {
    "path": "packages/runtime-dom/src/nodeOps.ts",
    "content": "import { warn } from '@vue/runtime-core'\nimport type { RendererOptions } from '@vue/runtime-core'\nimport type {\n  TrustedHTML,\n  TrustedTypePolicy,\n  TrustedTypesWindow,\n} from 'trusted-types/lib'\n\nlet policy: Pick<TrustedTypePolicy, 'name' | 'createHTML'> | undefined =\n  undefined\n\nconst tt =\n  typeof window !== 'undefined' &&\n  (window as unknown as TrustedTypesWindow).trustedTypes\n\nif (tt) {\n  try {\n    policy = /*@__PURE__*/ tt.createPolicy('vue', {\n      createHTML: val => val,\n    })\n  } catch (e: unknown) {\n    // `createPolicy` throws a TypeError if the name is a duplicate\n    // and the CSP trusted-types directive is not using `allow-duplicates`.\n    // So we have to catch that error.\n    __DEV__ && warn(`Error creating trusted types policy: ${e}`)\n  }\n}\n\n// __UNSAFE__\n// Reason: potentially setting innerHTML.\n// This function merely perform a type-level trusted type conversion\n// for use in `innerHTML` assignment, etc.\n// Be careful of whatever value passed to this function.\nexport const unsafeToTrustedHTML: (value: string) => TrustedHTML | string =\n  policy ? val => policy.createHTML(val) : val => val\n\nexport const svgNS = 'http://www.w3.org/2000/svg'\nexport const mathmlNS = 'http://www.w3.org/1998/Math/MathML'\n\nconst doc = (typeof document !== 'undefined' ? document : null) as Document\n\nconst templateContainer = doc && /*@__PURE__*/ doc.createElement('template')\n\nexport const nodeOps: Omit<RendererOptions<Node, Element>, 'patchProp'> = {\n  insert: (child, parent, anchor) => {\n    parent.insertBefore(child, anchor || null)\n  },\n\n  remove: child => {\n    const parent = child.parentNode\n    if (parent) {\n      parent.removeChild(child)\n    }\n  },\n\n  createElement: (tag, namespace, is, props): Element => {\n    const el =\n      namespace === 'svg'\n        ? doc.createElementNS(svgNS, tag)\n        : namespace === 'mathml'\n          ? doc.createElementNS(mathmlNS, tag)\n          : is\n            ? doc.createElement(tag, { is })\n            : doc.createElement(tag)\n\n    if (tag === 'select' && props && props.multiple != null) {\n      ;(el as HTMLSelectElement).setAttribute('multiple', props.multiple)\n    }\n\n    return el\n  },\n\n  createText: text => doc.createTextNode(text),\n\n  createComment: text => doc.createComment(text),\n\n  setText: (node, text) => {\n    node.nodeValue = text\n  },\n\n  setElementText: (el, text) => {\n    el.textContent = text\n  },\n\n  parentNode: node => node.parentNode as Element | null,\n\n  nextSibling: node => node.nextSibling,\n\n  querySelector: selector => doc.querySelector(selector),\n\n  setScopeId(el, id) {\n    el.setAttribute(id, '')\n  },\n\n  // __UNSAFE__\n  // Reason: innerHTML.\n  // Static content here can only come from compiled templates.\n  // As long as the user only uses trusted templates, this is safe.\n  insertStaticContent(content, parent, anchor, namespace, start, end) {\n    // <parent> before | first ... last | anchor </parent>\n    const before = anchor ? anchor.previousSibling : parent.lastChild\n    // #5308 can only take cached path if:\n    // - has a single root node\n    // - nextSibling info is still available\n    if (start && (start === end || start.nextSibling)) {\n      // cached\n      while (true) {\n        parent.insertBefore(start!.cloneNode(true), anchor)\n        if (start === end || !(start = start!.nextSibling)) break\n      }\n    } else {\n      // fresh insert\n      templateContainer.innerHTML = unsafeToTrustedHTML(\n        namespace === 'svg'\n          ? `<svg>${content}</svg>`\n          : namespace === 'mathml'\n            ? `<math>${content}</math>`\n            : content,\n      ) as string\n\n      const template = templateContainer.content\n      if (namespace === 'svg' || namespace === 'mathml') {\n        // remove outer svg/math wrapper\n        const wrapper = template.firstChild!\n        while (wrapper.firstChild) {\n          template.appendChild(wrapper.firstChild)\n        }\n        template.removeChild(wrapper)\n      }\n      parent.insertBefore(template, anchor)\n    }\n    return [\n      // first\n      before ? before.nextSibling! : parent.firstChild!,\n      // last\n      anchor ? anchor.previousSibling! : parent.lastChild!,\n    ]\n  },\n}\n"
  },
  {
    "path": "packages/runtime-dom/src/patchProp.ts",
    "content": "import { patchClass } from './modules/class'\nimport { patchStyle } from './modules/style'\nimport { patchAttr } from './modules/attrs'\nimport { patchDOMProp } from './modules/props'\nimport { patchEvent } from './modules/events'\nimport {\n  camelize,\n  isFunction,\n  isModelListener,\n  isOn,\n  isString,\n} from '@vue/shared'\nimport type { RendererOptions } from '@vue/runtime-core'\nimport type { VueElement } from './apiCustomElement'\n\nconst isNativeOn = (key: string) =>\n  key.charCodeAt(0) === 111 /* o */ &&\n  key.charCodeAt(1) === 110 /* n */ &&\n  // lowercase letter\n  key.charCodeAt(2) > 96 &&\n  key.charCodeAt(2) < 123\n\ntype DOMRendererOptions = RendererOptions<Node, Element>\n\nexport const patchProp: DOMRendererOptions['patchProp'] = (\n  el,\n  key,\n  prevValue,\n  nextValue,\n  namespace,\n  parentComponent,\n) => {\n  const isSVG = namespace === 'svg'\n  if (key === 'class') {\n    patchClass(el, nextValue, isSVG)\n  } else if (key === 'style') {\n    patchStyle(el, prevValue, nextValue)\n  } else if (isOn(key)) {\n    // ignore v-model listeners\n    if (!isModelListener(key)) {\n      patchEvent(el, key, prevValue, nextValue, parentComponent)\n    }\n  } else if (\n    key[0] === '.'\n      ? ((key = key.slice(1)), true)\n      : key[0] === '^'\n        ? ((key = key.slice(1)), false)\n        : shouldSetAsProp(el, key, nextValue, isSVG)\n  ) {\n    patchDOMProp(el, key, nextValue, parentComponent)\n    // #6007 also set form state as attributes so they work with\n    // <input type=\"reset\"> or libs / extensions that expect attributes\n    // #11163 custom elements may use value as an prop and set it as object\n    if (\n      !el.tagName.includes('-') &&\n      (key === 'value' || key === 'checked' || key === 'selected')\n    ) {\n      patchAttr(el, key, nextValue, isSVG, parentComponent, key !== 'value')\n    }\n  } else if (\n    // #11081 force set props for possible async custom element\n    (el as VueElement)._isVueCE &&\n    // #12408 check if it's declared prop or it's async custom element\n    (shouldSetAsPropForVueCE(el as VueElement, key) ||\n      // @ts-expect-error _def is private\n      ((el as VueElement)._def.__asyncLoader &&\n        (/[A-Z]/.test(key) || !isString(nextValue))))\n  ) {\n    patchDOMProp(el, camelize(key), nextValue, parentComponent, key)\n  } else {\n    // special case for <input v-model type=\"checkbox\"> with\n    // :true-value & :false-value\n    // store value as dom properties since non-string values will be\n    // stringified.\n    if (key === 'true-value') {\n      ;(el as any)._trueValue = nextValue\n    } else if (key === 'false-value') {\n      ;(el as any)._falseValue = nextValue\n    }\n    patchAttr(el, key, nextValue, isSVG, parentComponent)\n  }\n}\n\nfunction shouldSetAsProp(\n  el: Element,\n  key: string,\n  value: unknown,\n  isSVG: boolean,\n) {\n  if (isSVG) {\n    // most keys must be set as attribute on svg elements to work\n    // ...except innerHTML & textContent\n    if (key === 'innerHTML' || key === 'textContent') {\n      return true\n    }\n    // or native onclick with function values\n    if (key in el && isNativeOn(key) && isFunction(value)) {\n      return true\n    }\n    return false\n  }\n\n  // these are enumerated attrs, however their corresponding DOM properties\n  // are actually booleans - this leads to setting it with a string \"false\"\n  // value leading it to be coerced to `true`, so we need to always treat\n  // them as attributes.\n  // Note that `contentEditable` doesn't have this problem: its DOM\n  // property is also enumerated string values.\n  if (\n    key === 'spellcheck' ||\n    key === 'draggable' ||\n    key === 'translate' ||\n    key === 'autocorrect'\n  ) {\n    return false\n  }\n\n  // #13946 iframe.sandbox should always be set as attribute since setting\n  // the property to null results in 'null' string, and setting to empty string\n  // enables the most restrictive sandbox mode instead of no sandboxing.\n  if (key === 'sandbox' && el.tagName === 'IFRAME') {\n    return false\n  }\n\n  // #1787, #2840 form property on form elements is readonly and must be set as\n  // attribute.\n  if (key === 'form') {\n    return false\n  }\n\n  // #1526 <input list> must be set as attribute\n  if (key === 'list' && el.tagName === 'INPUT') {\n    return false\n  }\n\n  // #2766 <textarea type> must be set as attribute\n  if (key === 'type' && el.tagName === 'TEXTAREA') {\n    return false\n  }\n\n  // #8780 the width or height of embedded tags must be set as attribute\n  if (key === 'width' || key === 'height') {\n    const tag = el.tagName\n    if (\n      tag === 'IMG' ||\n      tag === 'VIDEO' ||\n      tag === 'CANVAS' ||\n      tag === 'SOURCE'\n    ) {\n      return false\n    }\n  }\n\n  // native onclick with string value, must be set as attribute\n  if (isNativeOn(key) && isString(value)) {\n    return false\n  }\n\n  return key in el\n}\n\nfunction shouldSetAsPropForVueCE(el: VueElement, key: string) {\n  const props = // @ts-expect-error _def is private\n    el._def.props as Record<string, unknown> | string[] | undefined\n  if (!props) {\n    return false\n  }\n\n  const camelKey = camelize(key)\n  return Array.isArray(props)\n    ? props.some(prop => camelize(prop) === camelKey)\n    : Object.keys(props).some(prop => camelize(prop) === camelKey)\n}\n"
  },
  {
    "path": "packages/runtime-test/LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2018-present, Yuxi (Evan) You\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "packages/runtime-test/README.md",
    "content": "# @vue/runtime-test\n\nThis is for Vue's own internal tests only - it ensures logic tested using this package is DOM-agnostic, and it runs faster than JSDOM.\n\nIt can also be used as a reference for implementing a custom renderer.\n\n```js\nimport { h, render, nodeOps, dumpOps } from '@vue/runtime-test'\n\nconst App = {\n  data() {\n    return {\n      msg: 'Hello World!',\n    }\n  },\n  render() {\n    return h('div', this.msg)\n  },\n}\n\n// root is of type `TestElement` as defined in src/nodeOps.ts\nconst root = nodeOps.createElement('div')\nrender(h(App), root)\n\nconst ops = dumpOps()\nconsole.log(ops)\n```\n"
  },
  {
    "path": "packages/runtime-test/__tests__/testRuntime.spec.ts",
    "content": "import {\n  NodeOpTypes,\n  type TestElement,\n  TestNodeTypes,\n  type TestText,\n  dumpOps,\n  h,\n  nextTick,\n  nodeOps,\n  reactive,\n  ref,\n  render,\n  resetOps,\n  serialize,\n  triggerEvent,\n} from '../src'\n\ndescribe('test renderer', () => {\n  it('should work', () => {\n    const root = nodeOps.createElement('div')\n    render(\n      h(\n        'div',\n        {\n          id: 'test',\n        },\n        'hello',\n      ),\n      root,\n    )\n\n    expect(root.children.length).toBe(1)\n\n    const el = root.children[0] as TestElement\n    expect(el.type).toBe(TestNodeTypes.ELEMENT)\n    expect(el.props.id).toBe('test')\n    expect(el.children.length).toBe(1)\n\n    const text = el.children[0] as TestText\n    expect(text.type).toBe(TestNodeTypes.TEXT)\n    expect(text.text).toBe('hello')\n  })\n\n  it('should record ops', async () => {\n    const state = reactive({\n      id: 'test',\n      text: 'hello',\n    })\n\n    const App = {\n      render() {\n        return h(\n          'div',\n          {\n            id: state.id,\n          },\n          state.text,\n        )\n      },\n    }\n    const root = nodeOps.createElement('div')\n\n    resetOps()\n    render(h(App), root)\n    const ops = dumpOps()\n\n    expect(ops.length).toBe(4)\n\n    expect(ops[0]).toEqual({\n      type: NodeOpTypes.CREATE,\n      nodeType: TestNodeTypes.ELEMENT,\n      tag: 'div',\n      targetNode: root.children[0],\n    })\n\n    expect(ops[1]).toEqual({\n      type: NodeOpTypes.SET_ELEMENT_TEXT,\n      text: 'hello',\n      targetNode: root.children[0],\n    })\n\n    expect(ops[2]).toEqual({\n      type: NodeOpTypes.PATCH,\n      targetNode: root.children[0],\n      propKey: 'id',\n      propPrevValue: null,\n      propNextValue: 'test',\n    })\n\n    expect(ops[3]).toEqual({\n      type: NodeOpTypes.INSERT,\n      targetNode: root.children[0],\n      parentNode: root,\n      refNode: null,\n    })\n\n    // test update ops\n    state.id = 'foo'\n    state.text = 'bar'\n    await nextTick()\n\n    const updateOps = dumpOps()\n    expect(updateOps.length).toBe(2)\n\n    expect(updateOps[0]).toEqual({\n      type: NodeOpTypes.SET_ELEMENT_TEXT,\n      targetNode: root.children[0],\n      text: 'bar',\n    })\n\n    expect(updateOps[1]).toEqual({\n      type: NodeOpTypes.PATCH,\n      targetNode: root.children[0],\n      propKey: 'id',\n      propPrevValue: 'test',\n      propNextValue: 'foo',\n    })\n  })\n\n  it('should be able to serialize nodes', () => {\n    const App = {\n      render() {\n        return h(\n          'div',\n          {\n            id: 'test',\n            boolean: '',\n          },\n          [h('span', 'foo'), 'hello'],\n        )\n      },\n    }\n    const root = nodeOps.createElement('div')\n    render(h(App), root)\n    expect(serialize(root)).toEqual(\n      `<div><div id=\"test\" boolean><span>foo</span>hello</div></div>`,\n    )\n    // indented output\n    expect(serialize(root, 2)).toEqual(\n      `<div>\n  <div id=\"test\" boolean>\n    <span>\n      foo\n    </span>\n    hello\n  </div>\n</div>`,\n    )\n  })\n\n  it('should be able to trigger events', async () => {\n    const count = ref(0)\n\n    const App = () => {\n      return h(\n        'span',\n        {\n          onClick: () => {\n            count.value++\n          },\n        },\n        count.value,\n      )\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(App), root)\n    triggerEvent(root.children[0] as TestElement, 'click')\n    expect(count.value).toBe(1)\n    await nextTick()\n    expect(serialize(root)).toBe(`<div><span>1</span></div>`)\n  })\n\n  it('should be able to trigger events with multiple listeners', async () => {\n    const count = ref(0)\n    const count2 = ref(1)\n\n    const App = () => {\n      return h(\n        'span',\n        {\n          onClick: [\n            () => {\n              count.value++\n            },\n            () => {\n              count2.value++\n            },\n          ],\n        },\n        `${count.value}, ${count2.value}`,\n      )\n    }\n\n    const root = nodeOps.createElement('div')\n    render(h(App), root)\n    triggerEvent(root.children[0] as TestElement, 'click')\n    expect(count.value).toBe(1)\n    expect(count2.value).toBe(2)\n    await nextTick()\n    expect(serialize(root)).toBe(`<div><span>1, 2</span></div>`)\n  })\n})\n"
  },
  {
    "path": "packages/runtime-test/index.js",
    "content": "'use strict'\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./dist/runtime-test.cjs.prod.js')\n} else {\n  module.exports = require('./dist/runtime-test.cjs.js')\n}\n"
  },
  {
    "path": "packages/runtime-test/package.json",
    "content": "{\n  \"name\": \"@vue/runtime-test\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"description\": \"@vue/runtime-test\",\n  \"main\": \"index.js\",\n  \"module\": \"dist/runtime-test.esm-bundler.js\",\n  \"types\": \"dist/runtime-test.d.ts\",\n  \"files\": [\n    \"index.js\",\n    \"dist\"\n  ],\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/vuejs/core.git\",\n    \"directory\": \"packages/runtime-test\"\n  },\n  \"keywords\": [\n    \"vue\"\n  ],\n  \"author\": \"Evan You\",\n  \"license\": \"MIT\",\n  \"bugs\": {\n    \"url\": \"https://github.com/vuejs/core/issues\"\n  },\n  \"homepage\": \"https://github.com/vuejs/core/tree/main/packages/runtime-test#readme\",\n  \"dependencies\": {\n    \"@vue/shared\": \"workspace:*\",\n    \"@vue/runtime-core\": \"workspace:*\"\n  }\n}\n"
  },
  {
    "path": "packages/runtime-test/src/index.ts",
    "content": "import {\n  type CreateAppFunction,\n  type RootRenderFunction,\n  type VNode,\n  createRenderer,\n} from '@vue/runtime-core'\nimport { type TestElement, nodeOps } from './nodeOps'\nimport { patchProp } from './patchProp'\nimport { serializeInner } from './serialize'\nimport { extend } from '@vue/shared'\n\nconst { render: baseRender, createApp: baseCreateApp } = createRenderer(\n  extend({ patchProp }, nodeOps),\n)\n\nexport const render = baseRender as RootRenderFunction<TestElement>\nexport const createApp = baseCreateApp as CreateAppFunction<TestElement>\n\n// convenience for one-off render validations\nexport function renderToString(vnode: VNode): string {\n  const root = nodeOps.createElement('div')\n  render(vnode, root)\n  return serializeInner(root)\n}\n\nexport * from './triggerEvent'\nexport * from './serialize'\nexport * from './nodeOps'\nexport * from '@vue/runtime-core'\n"
  },
  {
    "path": "packages/runtime-test/src/nodeOps.ts",
    "content": "import { markRaw } from '@vue/reactivity'\n\nexport enum TestNodeTypes {\n  TEXT = 'text',\n  ELEMENT = 'element',\n  COMMENT = 'comment',\n}\n\nexport enum NodeOpTypes {\n  CREATE = 'create',\n  INSERT = 'insert',\n  REMOVE = 'remove',\n  SET_TEXT = 'setText',\n  SET_ELEMENT_TEXT = 'setElementText',\n  PATCH = 'patch',\n}\n\nexport interface TestElement {\n  id: number\n  type: TestNodeTypes.ELEMENT\n  parentNode: TestElement | null\n  tag: string\n  children: TestNode[]\n  props: Record<string, any>\n  eventListeners: Record<string, Function | Function[]> | null\n}\n\nexport interface TestText {\n  id: number\n  type: TestNodeTypes.TEXT\n  parentNode: TestElement | null\n  text: string\n}\n\nexport interface TestComment {\n  id: number\n  type: TestNodeTypes.COMMENT\n  parentNode: TestElement | null\n  text: string\n}\n\nexport type TestNode = TestElement | TestText | TestComment\n\nexport interface NodeOp {\n  type: NodeOpTypes\n  nodeType?: TestNodeTypes\n  tag?: string\n  text?: string\n  targetNode?: TestNode\n  parentNode?: TestElement\n  refNode?: TestNode | null\n  propKey?: string\n  propPrevValue?: any\n  propNextValue?: any\n}\n\nlet nodeId: number = 0\nlet recordedNodeOps: NodeOp[] = []\n\nexport function logNodeOp(op: NodeOp): void {\n  recordedNodeOps.push(op)\n}\n\nexport function resetOps(): void {\n  recordedNodeOps = []\n}\n\nexport function dumpOps(): NodeOp[] {\n  const ops = recordedNodeOps.slice()\n  resetOps()\n  return ops\n}\n\nfunction createElement(tag: string): TestElement {\n  const node: TestElement = {\n    id: nodeId++,\n    type: TestNodeTypes.ELEMENT,\n    tag,\n    children: [],\n    props: {},\n    parentNode: null,\n    eventListeners: null,\n  }\n  logNodeOp({\n    type: NodeOpTypes.CREATE,\n    nodeType: TestNodeTypes.ELEMENT,\n    targetNode: node,\n    tag,\n  })\n  // avoid test nodes from being observed\n  markRaw(node)\n  return node\n}\n\nfunction createText(text: string): TestText {\n  const node: TestText = {\n    id: nodeId++,\n    type: TestNodeTypes.TEXT,\n    text,\n    parentNode: null,\n  }\n  logNodeOp({\n    type: NodeOpTypes.CREATE,\n    nodeType: TestNodeTypes.TEXT,\n    targetNode: node,\n    text,\n  })\n  // avoid test nodes from being observed\n  markRaw(node)\n  return node\n}\n\nfunction createComment(text: string): TestComment {\n  const node: TestComment = {\n    id: nodeId++,\n    type: TestNodeTypes.COMMENT,\n    text,\n    parentNode: null,\n  }\n  logNodeOp({\n    type: NodeOpTypes.CREATE,\n    nodeType: TestNodeTypes.COMMENT,\n    targetNode: node,\n    text,\n  })\n  // avoid test nodes from being observed\n  markRaw(node)\n  return node\n}\n\nfunction setText(node: TestText, text: string): void {\n  logNodeOp({\n    type: NodeOpTypes.SET_TEXT,\n    targetNode: node,\n    text,\n  })\n  node.text = text\n}\n\nfunction insert(\n  child: TestNode,\n  parent: TestElement,\n  ref?: TestNode | null,\n): void {\n  let refIndex\n  if (ref) {\n    refIndex = parent.children.indexOf(ref)\n    if (refIndex === -1) {\n      console.error('ref: ', ref)\n      console.error('parent: ', parent)\n      throw new Error('ref is not a child of parent')\n    }\n  }\n  logNodeOp({\n    type: NodeOpTypes.INSERT,\n    targetNode: child,\n    parentNode: parent,\n    refNode: ref,\n  })\n  // remove the node first, but don't log it as a REMOVE op\n  remove(child, false)\n  // re-calculate the ref index because the child's removal may have affected it\n  refIndex = ref ? parent.children.indexOf(ref) : -1\n  if (refIndex === -1) {\n    parent.children.push(child)\n    child.parentNode = parent\n  } else {\n    parent.children.splice(refIndex, 0, child)\n    child.parentNode = parent\n  }\n}\n\nfunction remove(child: TestNode, logOp = true): void {\n  const parent = child.parentNode\n  if (parent) {\n    if (logOp) {\n      logNodeOp({\n        type: NodeOpTypes.REMOVE,\n        targetNode: child,\n        parentNode: parent,\n      })\n    }\n    const i = parent.children.indexOf(child)\n    if (i > -1) {\n      parent.children.splice(i, 1)\n    } else {\n      console.error('target: ', child)\n      console.error('parent: ', parent)\n      throw Error('target is not a childNode of parent')\n    }\n    child.parentNode = null\n  }\n}\n\nfunction setElementText(el: TestElement, text: string): void {\n  logNodeOp({\n    type: NodeOpTypes.SET_ELEMENT_TEXT,\n    targetNode: el,\n    text,\n  })\n  el.children.forEach(c => {\n    c.parentNode = null\n  })\n  if (!text) {\n    el.children = []\n  } else {\n    el.children = [\n      {\n        id: nodeId++,\n        type: TestNodeTypes.TEXT,\n        text,\n        parentNode: el,\n      },\n    ]\n  }\n}\n\nfunction parentNode(node: TestNode): TestElement | null {\n  return node.parentNode\n}\n\nfunction nextSibling(node: TestNode): TestNode | null {\n  const parent = node.parentNode\n  if (!parent) {\n    return null\n  }\n  const i = parent.children.indexOf(node)\n  return parent.children[i + 1] || null\n}\n\nfunction querySelector(): never {\n  throw new Error('querySelector not supported in test renderer.')\n}\n\nfunction setScopeId(el: TestElement, id: string): void {\n  el.props[id] = ''\n}\n\nexport const nodeOps: {\n  insert: typeof insert\n  remove: typeof remove\n  createElement: typeof createElement\n  createText: typeof createText\n  createComment: typeof createComment\n  setText: typeof setText\n  setElementText: typeof setElementText\n  parentNode: typeof parentNode\n  nextSibling: typeof nextSibling\n  querySelector: typeof querySelector\n  setScopeId: typeof setScopeId\n} = {\n  insert,\n  remove,\n  createElement,\n  createText,\n  createComment,\n  setText,\n  setElementText,\n  parentNode,\n  nextSibling,\n  querySelector,\n  setScopeId,\n}\n"
  },
  {
    "path": "packages/runtime-test/src/patchProp.ts",
    "content": "import { NodeOpTypes, type TestElement, logNodeOp } from './nodeOps'\nimport { isOn } from '@vue/shared'\n\nexport function patchProp(\n  el: TestElement,\n  key: string,\n  prevValue: any,\n  nextValue: any,\n): void {\n  logNodeOp({\n    type: NodeOpTypes.PATCH,\n    targetNode: el,\n    propKey: key,\n    propPrevValue: prevValue,\n    propNextValue: nextValue,\n  })\n  el.props[key] = nextValue\n  if (isOn(key)) {\n    const event = key[2] === ':' ? key.slice(3) : key.slice(2).toLowerCase()\n    ;(el.eventListeners || (el.eventListeners = {}))[event] = nextValue\n  }\n}\n"
  },
  {
    "path": "packages/runtime-test/src/serialize.ts",
    "content": "import {\n  type TestComment,\n  type TestElement,\n  type TestNode,\n  TestNodeTypes,\n  type TestText,\n} from './nodeOps'\nimport { isOn } from '@vue/shared'\n\nexport function serialize(\n  node: TestNode,\n  indent: number = 0,\n  depth: number = 0,\n): string {\n  if (node.type === TestNodeTypes.ELEMENT) {\n    return serializeElement(node, indent, depth)\n  } else {\n    return serializeText(node, indent, depth)\n  }\n}\n\nexport function serializeInner(\n  node: TestElement,\n  indent: number = 0,\n  depth: number = 0,\n): string {\n  const newLine = indent ? `\\n` : ``\n  return node.children.length\n    ? newLine +\n        node.children.map(c => serialize(c, indent, depth + 1)).join(newLine) +\n        newLine\n    : ``\n}\n\nfunction serializeElement(\n  node: TestElement,\n  indent: number,\n  depth: number,\n): string {\n  const props = Object.keys(node.props)\n    .map(key => {\n      const value = node.props[key]\n      return isOn(key) || value == null\n        ? ``\n        : value === ``\n          ? key\n          : `${key}=${JSON.stringify(value)}`\n    })\n    .filter(Boolean)\n    .join(' ')\n  const padding = indent ? ` `.repeat(indent).repeat(depth) : ``\n  return (\n    `${padding}<${node.tag}${props ? ` ${props}` : ``}>` +\n    `${serializeInner(node, indent, depth)}` +\n    `${padding}</${node.tag}>`\n  )\n}\n\nfunction serializeText(\n  node: TestText | TestComment,\n  indent: number,\n  depth: number,\n): string {\n  const padding = indent ? ` `.repeat(indent).repeat(depth) : ``\n  return (\n    padding +\n    (node.type === TestNodeTypes.COMMENT ? `<!--${node.text}-->` : node.text)\n  )\n}\n"
  },
  {
    "path": "packages/runtime-test/src/triggerEvent.ts",
    "content": "import { isArray } from '@vue/shared'\nimport type { TestElement } from './nodeOps'\n\nexport function triggerEvent(\n  el: TestElement,\n  event: string,\n  payload: any[] = [],\n): void {\n  const { eventListeners } = el\n  if (eventListeners) {\n    const listener = eventListeners[event]\n    if (listener) {\n      if (isArray(listener)) {\n        for (let i = 0; i < listener.length; i++) {\n          listener[i](...payload)\n        }\n      } else {\n        listener(...payload)\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "packages/server-renderer/LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2018-present, Yuxi (Evan) You\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "packages/server-renderer/README.md",
    "content": "# @vue/server-renderer\n\n**Note: as of 3.2.13+, this package is included as a dependency of the main `vue` package and can be accessed as `vue/server-renderer`. This means you no longer need to explicitly install this package and ensure its version matches that of `vue`'s. Just use the `vue/server-renderer` deep import instead.**\n\n## Basic API\n\n### `renderToString`\n\n**Signature**\n\n```ts\nfunction renderToString(\n  input: App | VNode,\n  context?: SSRContext,\n): Promise<string>\n```\n\n**Usage**\n\n```js\nconst { createSSRApp } = require('vue')\nconst { renderToString } = require('@vue/server-renderer')\n\nconst app = createSSRApp({\n  data: () => ({ msg: 'hello' }),\n  template: `<div>{{ msg }}</div>`,\n})\n\n;(async () => {\n  const html = await renderToString(app)\n  console.log(html)\n})()\n```\n\n### Handling Teleports\n\nIf the rendered app contains teleports, the teleported content will not be part of the rendered string. Instead, they are exposed under the `teleports` property of the ssr context object:\n\n```js\nconst ctx = {}\nconst html = await renderToString(app, ctx)\n\nconsole.log(ctx.teleports) // { '#teleported': 'teleported content' }\n```\n\n## Streaming API\n\n### `renderToNodeStream`\n\nRenders input as a [Node.js Readable stream](https://nodejs.org/api/stream.html#stream_class_stream_readable).\n\n**Signature**\n\n```ts\nfunction renderToNodeStream(input: App | VNode, context?: SSRContext): Readable\n```\n\n**Usage**\n\n```js\n// inside a Node.js http handler\nrenderToNodeStream(app).pipe(res)\n```\n\n**Note:** This method is not supported in the ESM build of `@vue/server-renderer`, which is decoupled from Node.js environments. Use `pipeToNodeWritable` instead.\n\n### `pipeToNodeWritable`\n\nRender and pipe to an existing [Node.js Writable stream](https://nodejs.org/api/stream.html#stream_writable_streams) instance.\n\n**Signature**\n\n```ts\nfunction pipeToNodeWritable(\n  input: App | VNode,\n  context: SSRContext = {},\n  writable: Writable,\n): void\n```\n\n**Usage**\n\n```js\n// inside a Node.js http handler\npipeToNodeWritable(app, {}, res)\n```\n\n### `renderToWebStream`\n\nRenders input as a [Web ReadableStream](https://developer.mozilla.org/en-US/docs/Web/API/Streams_API).\n\n**Signature**\n\n```ts\nfunction renderToWebStream(\n  input: App | VNode,\n  context?: SSRContext,\n): ReadableStream\n```\n\n**Usage**\n\n```js\n// inside an environment with ReadableStream support\nreturn new Response(renderToWebStream(app))\n```\n\n**Note:** in environments that do not expose `ReadableStream` constructor in the global scope, `pipeToWebWritable` should be used instead.\n\n### `pipeToWebWritable`\n\nRender and pipe to an existing [Web WritableStream](https://developer.mozilla.org/en-US/docs/Web/API/WritableStream) instance.\n\n**Signature**\n\n```ts\nfunction pipeToWebWritable(\n  input: App | VNode,\n  context: SSRContext = {},\n  writable: WritableStream,\n): void\n```\n\n**Usage**\n\nThis is typically used in combination with [`TransformStream`](https://developer.mozilla.org/en-US/docs/Web/API/TransformStream):\n\n```js\n// TransformStream is available in environments such as CloudFlare workers.\n// in Node.js, TransformStream needs to be explicitly imported from 'stream/web'\nconst { readable, writable } = new TransformStream()\npipeToWebWritable(app, {}, writable)\n\nreturn new Response(readable)\n```\n\n### `renderToSimpleStream`\n\nRenders input in streaming mode using a simple readable interface.\n\n**Signature**\n\n```ts\nfunction renderToSimpleStream(\n  input: App | VNode,\n  context: SSRContext,\n  options: SimpleReadable,\n): SimpleReadable\n\ninterface SimpleReadable {\n  push(content: string | null): void\n  destroy(err: any): void\n}\n```\n\n**Usage**\n\n```js\nlet res = ''\n\nrenderToSimpleStream(\n  app,\n  {},\n  {\n    push(chunk) {\n      if (chunk === null) {\n        // done\n        console.log(`render complete: ${res}`)\n      } else {\n        res += chunk\n      }\n    },\n    destroy(err) {\n      // error encountered\n    },\n  },\n)\n```\n"
  },
  {
    "path": "packages/server-renderer/__tests__/createBuffer.bench.ts",
    "content": "import { bench, describe } from 'vitest'\n\nimport { createBuffer as _createBuffer } from '../src/render'\n\n// move to local const to avoid import access overhead\n// https://github.com/vitest-dev/vitest/issues/6903\nconst createBuffer = _createBuffer\n\ndescribe('createBuffer', () => {\n  let stringBuffer = createBuffer()\n\n  bench(\n    'string only',\n    () => {\n      for (let i = 0; i < 10; i += 1) {\n        stringBuffer.push('hello')\n      }\n    },\n    {\n      setup() {\n        stringBuffer = createBuffer()\n      },\n    },\n  )\n\n  let stringNestedBuffer = createBuffer()\n\n  bench(\n    'string with nested',\n    () => {\n      for (let i = 0; i < 10; i += 1) {\n        if (i % 3 === 0) {\n          stringNestedBuffer.push('hello')\n        } else {\n          const buffer = createBuffer()\n          buffer.push('hello')\n          stringNestedBuffer.push(buffer.getBuffer())\n        }\n      }\n    },\n    {\n      setup() {\n        stringNestedBuffer = createBuffer()\n      },\n    },\n  )\n\n  bench(\n    'string with nested async',\n    () => {\n      for (let i = 0; i < 10; i += 1) {\n        if (i % 3 === 0) {\n          const buffer = createBuffer()\n          buffer.push('hello')\n          stringNestedBuffer.push(Promise.resolve(buffer.getBuffer()))\n        } else {\n          const buffer = createBuffer()\n          buffer.push('hello')\n          stringNestedBuffer.push(buffer.getBuffer())\n        }\n      }\n    },\n    {\n      setup() {\n        stringNestedBuffer = createBuffer()\n      },\n    },\n  )\n})\n"
  },
  {
    "path": "packages/server-renderer/__tests__/render.spec.ts",
    "content": "import {\n  type ComponentOptions,\n  KeepAlive,\n  Transition,\n  computed,\n  createApp,\n  createCommentVNode,\n  createSSRApp,\n  createStaticVNode,\n  createTextVNode,\n  createVNode,\n  defineComponent,\n  getCurrentInstance,\n  h,\n  onErrorCaptured,\n  onServerPrefetch,\n  reactive,\n  ref,\n  renderSlot,\n  resolveComponent,\n  resolveDynamicComponent,\n  watchEffect,\n  withCtx,\n} from 'vue'\nimport { escapeHtml } from '@vue/shared'\nimport { renderToString } from '../src/renderToString'\nimport { pipeToNodeWritable, renderToNodeStream } from '../src/renderToStream'\nimport { type SSRSlot, ssrRenderSlot } from '../src/helpers/ssrRenderSlot'\nimport { ssrRenderComponent } from '../src/helpers/ssrRenderComponent'\nimport { type Readable, Transform } from 'node:stream'\nimport { ssrRenderVNode } from '../src'\n\nconst promisifyStream = (stream: Readable) => {\n  return new Promise<string>((resolve, reject) => {\n    let result = ''\n    stream.on('data', data => {\n      result += data\n    })\n    stream.on('error', () => {\n      reject(result)\n    })\n    stream.on('end', () => {\n      resolve(result)\n    })\n  })\n}\n\nconst renderToStream = (app: any, context?: any) => {\n  return promisifyStream(renderToNodeStream(app, context))\n}\n\nconst pipeToWritable = (app: any, context?: any) => {\n  const stream = new Transform({\n    transform(data, _encoding, cb) {\n      this.push(data)\n      cb()\n    },\n  })\n  pipeToNodeWritable(app, context, stream)\n  return promisifyStream(stream)\n}\n\n// we run the same tests twice, once for renderToString, once for renderToStream\ntestRender(`renderToString`, renderToString)\ntestRender(`renderToNodeStream`, renderToStream)\ntestRender(`pipeToNodeWritable`, pipeToWritable)\n\nfunction testRender(type: string, render: typeof renderToString) {\n  describe(`ssr: ${type}`, () => {\n    test('should apply app context', async () => {\n      const app = createApp({\n        render() {\n          const Foo = resolveComponent('foo') as ComponentOptions\n          return h(Foo)\n        },\n      })\n      app.component('foo', {\n        render: () => h('div', 'foo'),\n      })\n      const html = await render(app)\n      expect(html).toBe(`<div>foo</div>`)\n    })\n\n    test('warnings should be suppressed by app.config.warnHandler', async () => {\n      const app = createApp({\n        render() {\n          return h('div', this.foo)\n        },\n      })\n      app.config.warnHandler = vi.fn()\n      await render(app)\n      expect('not defined on instance').not.toHaveBeenWarned()\n      expect(app.config.warnHandler).toHaveBeenCalledTimes(1)\n    })\n\n    describe('components', () => {\n      test('vnode components', async () => {\n        expect(\n          await render(\n            createApp({\n              data() {\n                return { msg: 'hello' }\n              },\n              render(this: any) {\n                return h('div', this.msg)\n              },\n            }),\n          ),\n        ).toBe(`<div>hello</div>`)\n      })\n\n      test('option components returning render from setup', async () => {\n        expect(\n          await render(\n            createApp({\n              setup() {\n                const msg = ref('hello')\n                return () => h('div', msg.value)\n              },\n            }),\n          ),\n        ).toBe(`<div>hello</div>`)\n      })\n\n      test('setup components returning render from setup', async () => {\n        expect(\n          await render(\n            createApp(\n              defineComponent(() => {\n                const msg = ref('hello')\n                return () => h('div', msg.value)\n              }),\n            ),\n          ),\n        ).toBe(`<div>hello</div>`)\n      })\n\n      test('components using defineComponent with extends option', async () => {\n        expect(\n          await render(\n            createApp(\n              defineComponent({\n                extends: defineComponent({\n                  data() {\n                    return { msg: 'hello' }\n                  },\n                  render() {\n                    return h('div', this.msg)\n                  },\n                }),\n              }),\n            ),\n          ),\n        ).toBe(`<div>hello</div>`)\n      })\n\n      test('components using defineComponent with mixins option', async () => {\n        expect(\n          await render(\n            createApp(\n              defineComponent({\n                mixins: [\n                  defineComponent({\n                    data() {\n                      return { msg: 'hello' }\n                    },\n                    render() {\n                      return h('div', this.msg)\n                    },\n                  }),\n                ],\n              }),\n            ),\n          ),\n        ).toBe(`<div>hello</div>`)\n      })\n\n      test('optimized components', async () => {\n        expect(\n          await render(\n            createApp({\n              data() {\n                return { msg: 'hello' }\n              },\n              ssrRender(ctx, push) {\n                push(`<div>${ctx.msg}</div>`)\n              },\n            }),\n          ),\n        ).toBe(`<div>hello</div>`)\n      })\n\n      test('nested vnode components', async () => {\n        const Child = {\n          props: ['msg'],\n          render(this: any) {\n            return h('div', this.msg)\n          },\n        }\n\n        expect(\n          await render(\n            createApp({\n              render() {\n                return h('div', ['parent', h(Child, { msg: 'hello' })])\n              },\n            }),\n          ),\n        ).toBe(`<div>parent<div>hello</div></div>`)\n      })\n\n      test('nested optimized components', async () => {\n        const Child = {\n          props: ['msg'],\n          ssrRender(ctx: any, push: any) {\n            push(`<div>${ctx.msg}</div>`)\n          },\n        }\n\n        expect(\n          await render(\n            createApp({\n              ssrRender(_ctx, push, parent) {\n                push(`<div>parent`)\n                push(ssrRenderComponent(Child, { msg: 'hello' }, null, parent))\n                push(`</div>`)\n              },\n            }),\n          ),\n        ).toBe(`<div>parent<div>hello</div></div>`)\n      })\n\n      test('nested template components', async () => {\n        const Child = {\n          props: ['msg'],\n          template: `<div>{{ msg }}</div>`,\n        }\n        const app = createApp({\n          template: `<div>parent<Child msg=\"hello\" /></div>`,\n        })\n        app.component('Child', Child)\n\n        expect(await render(app)).toBe(`<div>parent<div>hello</div></div>`)\n      })\n\n      test('template components with dynamic class attribute after static', async () => {\n        const app = createApp({\n          template: `<div><div class=\"child\" :class=\"'dynamic'\"></div></div>`,\n        })\n        expect(await render(app)).toBe(\n          `<div><div class=\"dynamic child\"></div></div>`,\n        )\n      })\n\n      test('template components with dynamic class attribute before static', async () => {\n        const app = createApp({\n          template: `<div><div :class=\"'dynamic'\" class=\"child\"></div></div>`,\n        })\n        expect(await render(app)).toBe(\n          `<div><div class=\"dynamic child\"></div></div>`,\n        )\n      })\n\n      test('mixing optimized / vnode / template components', async () => {\n        const OptimizedChild = {\n          props: ['msg'],\n          ssrRender(ctx: any, push: any) {\n            push(`<div>${ctx.msg}</div>`)\n          },\n        }\n\n        const VNodeChild = {\n          props: ['msg'],\n          render(this: any) {\n            return h('div', this.msg)\n          },\n        }\n\n        const TemplateChild = {\n          props: ['msg'],\n          template: `<div>{{ msg }}</div>`,\n        }\n\n        expect(\n          await render(\n            createApp({\n              ssrRender(_ctx, push, parent) {\n                push(`<div>parent`)\n                push(\n                  ssrRenderComponent(\n                    OptimizedChild,\n                    { msg: 'opt' },\n                    null,\n                    parent,\n                  ),\n                )\n                push(\n                  ssrRenderComponent(\n                    VNodeChild,\n                    { msg: 'vnode' },\n                    null,\n                    parent,\n                  ),\n                )\n                push(\n                  ssrRenderComponent(\n                    TemplateChild,\n                    { msg: 'template' },\n                    null,\n                    parent,\n                  ),\n                )\n                push(`</div>`)\n              },\n            }),\n          ),\n        ).toBe(\n          `<div>parent<div>opt</div><div>vnode</div><div>template</div></div>`,\n        )\n      })\n\n      test('async components', async () => {\n        const Child = {\n          // should wait for resolved render context from setup()\n          async setup() {\n            return {\n              msg: 'hello',\n            }\n          },\n          ssrRender(ctx: any, push: any) {\n            push(`<div>${ctx.msg}</div>`)\n          },\n        }\n\n        expect(\n          await render(\n            createApp({\n              ssrRender(_ctx, push, parent) {\n                push(`<div>parent`)\n                push(ssrRenderComponent(Child, null, null, parent))\n                push(`</div>`)\n              },\n            }),\n          ),\n        ).toBe(`<div>parent<div>hello</div></div>`)\n      })\n\n      test('parallel async components', async () => {\n        const OptimizedChild = {\n          props: ['msg'],\n          async setup(props: any) {\n            return {\n              localMsg: props.msg + '!',\n            }\n          },\n          ssrRender(ctx: any, push: any) {\n            push(`<div>${ctx.localMsg}</div>`)\n          },\n        }\n\n        const VNodeChild = {\n          props: ['msg'],\n          async setup(props: any) {\n            return {\n              localMsg: props.msg + '!',\n            }\n          },\n          render(this: any) {\n            return h('div', this.localMsg)\n          },\n        }\n\n        expect(\n          await render(\n            createApp({\n              ssrRender(_ctx, push, parent) {\n                push(`<div>parent`)\n                push(\n                  ssrRenderComponent(\n                    OptimizedChild,\n                    { msg: 'opt' },\n                    null,\n                    parent,\n                  ),\n                )\n                push(\n                  ssrRenderComponent(\n                    VNodeChild,\n                    { msg: 'vnode' },\n                    null,\n                    parent,\n                  ),\n                )\n                push(`</div>`)\n              },\n            }),\n          ),\n        ).toBe(`<div>parent<div>opt!</div><div>vnode!</div></div>`)\n      })\n    })\n\n    describe('slots', () => {\n      test('nested components with optimized slots', async () => {\n        const Child = {\n          props: ['msg'],\n          ssrRender(ctx: any, push: any, parent: any) {\n            push(`<div class=\"child\">`)\n            ssrRenderSlot(\n              ctx.$slots,\n              'default',\n              { msg: 'from slot' },\n              () => {\n                push(`fallback`)\n              },\n              push,\n              parent,\n            )\n            push(`</div>`)\n          },\n        }\n\n        expect(\n          await render(\n            createApp({\n              ssrRender(_ctx, push, parent) {\n                push(`<div>parent`)\n                push(\n                  ssrRenderComponent(\n                    Child,\n                    { msg: 'hello' },\n                    {\n                      // optimized slot using string push\n                      default: (({ msg }, push, _p) => {\n                        push(`<span>${msg}</span>`)\n                      }) as SSRSlot,\n                      // important to avoid slots being normalized\n                      _: 1 as any,\n                    },\n                    parent,\n                  ),\n                )\n                push(`</div>`)\n              },\n            }),\n          ),\n        ).toBe(\n          `<div>parent<div class=\"child\">` +\n            `<!--[--><span>from slot</span><!--]-->` +\n            `</div></div>`,\n        )\n\n        // test fallback\n        expect(\n          await render(\n            createApp({\n              ssrRender(_ctx, push, parent) {\n                push(`<div>parent`)\n                push(ssrRenderComponent(Child, { msg: 'hello' }, null, parent))\n                push(`</div>`)\n              },\n            }),\n          ),\n        ).toBe(\n          `<div>parent<div class=\"child\"><!--[-->fallback<!--]--></div></div>`,\n        )\n      })\n\n      test('nested components with vnode slots', async () => {\n        const Child = {\n          props: ['msg'],\n          ssrRender(ctx: any, push: any, parent: any) {\n            push(`<div class=\"child\">`)\n            ssrRenderSlot(\n              ctx.$slots,\n              'default',\n              { msg: 'from slot' },\n              null,\n              push,\n              parent,\n            )\n            push(`</div>`)\n          },\n        }\n\n        expect(\n          await render(\n            createApp({\n              ssrRender(_ctx, push, parent) {\n                push(`<div>parent`)\n                push(\n                  ssrRenderComponent(\n                    Child,\n                    { msg: 'hello' },\n                    {\n                      // bailed slots returning raw vnodes\n                      default: ({ msg }: any) => {\n                        return h('span', msg)\n                      },\n                    },\n                    parent,\n                  ),\n                )\n                push(`</div>`)\n              },\n            }),\n          ),\n        ).toBe(\n          `<div>parent<div class=\"child\">` +\n            `<!--[--><span>from slot</span><!--]-->` +\n            `</div></div>`,\n        )\n      })\n\n      test('nested components with template slots', async () => {\n        const Child = {\n          props: ['msg'],\n          template: `<div class=\"child\"><slot msg=\"from slot\"></slot></div>`,\n        }\n\n        const app = createApp({\n          components: { Child },\n          template: `<div>parent<Child v-slot=\"{ msg }\"><span>{{ msg }}</span></Child></div>`,\n        })\n\n        expect(await render(app)).toBe(\n          `<div>parent<div class=\"child\">` +\n            `<!--[--><span>from slot</span><!--]-->` +\n            `</div></div>`,\n        )\n      })\n\n      test('nested render fn components with template slots', async () => {\n        const Child = {\n          props: ['msg'],\n          render(this: any) {\n            return h(\n              'div',\n              {\n                class: 'child',\n              },\n              this.$slots.default({ msg: 'from slot' }),\n            )\n          },\n        }\n\n        const app = createApp({\n          template: `<div>parent<Child v-slot=\"{ msg }\"><span>{{ msg }}</span></Child></div>`,\n        })\n        app.component('Child', Child)\n\n        expect(await render(app)).toBe(\n          `<div>parent<div class=\"child\">` +\n            // no comment anchors because slot is used directly as element children\n            `<span>from slot</span>` +\n            `</div></div>`,\n        )\n      })\n\n      test('template slots forwarding', async () => {\n        const Child = {\n          template: `<div><slot/></div>`,\n        }\n\n        const Parent = {\n          components: { Child },\n          template: `<Child><slot/></Child>`,\n        }\n\n        const app = createApp({\n          components: { Parent },\n          template: `<Parent>hello</Parent>`,\n        })\n\n        expect(await render(app)).toBe(\n          `<div><!--[--><!--[-->hello<!--]--><!--]--></div>`,\n        )\n      })\n\n      test('template slots forwarding, empty slot', async () => {\n        const Child = {\n          template: `<div><slot/></div>`,\n        }\n\n        const Parent = {\n          components: { Child },\n          template: `<Child><slot/></Child>`,\n        }\n\n        const app = createApp({\n          components: { Parent },\n          template: `<Parent></Parent>`,\n        })\n\n        expect(await render(app)).toBe(\n          // should only have a single fragment\n          `<div><!--[--><!--]--></div>`,\n        )\n      })\n\n      test('template slots forwarding, empty slot w/ fallback', async () => {\n        const Child = {\n          template: `<div><slot>fallback</slot></div>`,\n        }\n\n        const Parent = {\n          components: { Child },\n          template: `<Child><slot/></Child>`,\n        }\n\n        const app = createApp({\n          components: { Parent },\n          template: `<Parent></Parent>`,\n        })\n\n        expect(await render(app)).toBe(\n          // should only have a single fragment\n          `<div><!--[-->fallback<!--]--></div>`,\n        )\n      })\n    })\n\n    describe('vnode element', () => {\n      test('props', async () => {\n        expect(\n          await render(\n            h('div', { id: 'foo&', class: ['bar', 'baz'] }, 'hello'),\n          ),\n        ).toBe(`<div id=\"foo&amp;\" class=\"bar baz\">hello</div>`)\n      })\n\n      test('text children', async () => {\n        expect(await render(h('div', 'hello'))).toBe(`<div>hello</div>`)\n      })\n\n      test('array children', async () => {\n        expect(\n          await render(\n            h('div', [\n              'foo',\n              h('span', 'bar'),\n              [h('span', 'baz')],\n              createCommentVNode('qux'),\n            ]),\n          ),\n        ).toBe(\n          `<div>foo<span>bar</span><!--[--><span>baz</span><!--]--><!--qux--></div>`,\n        )\n      })\n\n      test('void elements', async () => {\n        expect(await render(h('input'))).toBe(`<input>`)\n      })\n\n      test('innerHTML', async () => {\n        expect(\n          await render(\n            h(\n              'div',\n              {\n                innerHTML: `<span>hello</span>`,\n              },\n              'ignored',\n            ),\n          ),\n        ).toBe(`<div><span>hello</span></div>`)\n      })\n\n      test('textContent', async () => {\n        expect(\n          await render(\n            h(\n              'div',\n              {\n                textContent: `<span>hello</span>`,\n              },\n              'ignored',\n            ),\n          ),\n        ).toBe(`<div>${escapeHtml(`<span>hello</span>`)}</div>`)\n      })\n\n      test('textarea value', async () => {\n        expect(\n          await render(\n            h(\n              'textarea',\n              {\n                value: `<span>hello</span>`,\n              },\n              'ignored',\n            ),\n          ),\n        ).toBe(`<textarea>${escapeHtml(`<span>hello</span>`)}</textarea>`)\n      })\n    })\n\n    describe('vnode component', () => {\n      test('KeepAlive', async () => {\n        const MyComp = {\n          render: () => h('p', 'hello'),\n        }\n        expect(await render(h(KeepAlive, () => h(MyComp)))).toBe(`<p>hello</p>`)\n      })\n\n      test('Transition', async () => {\n        const MyComp = {\n          render: () => h('p', 'hello'),\n        }\n        expect(await render(h(Transition, () => h(MyComp)))).toBe(\n          `<p>hello</p>`,\n        )\n      })\n    })\n\n    describe('raw vnode types', () => {\n      test('Text', async () => {\n        expect(await render(createTextVNode('hello <div>'))).toBe(\n          `hello &lt;div&gt;`,\n        )\n      })\n\n      test('Comment', async () => {\n        // https://www.w3.org/TR/html52/syntax.html#comments\n        expect(\n          await render(\n            h('div', [\n              createCommentVNode('>foo'),\n              createCommentVNode('->foo'),\n              createCommentVNode('<!--foo-->'),\n              createCommentVNode('--!>foo<!-'),\n            ]),\n          ),\n        ).toBe(`<div><!--foo--><!--foo--><!--foo--><!--foo--></div>`)\n      })\n\n      test('Static', async () => {\n        const content = `<div id=\"ok\">hello<span>world</span></div>`\n        expect(await render(createStaticVNode(content, 1))).toBe(content)\n      })\n    })\n\n    describe('scopeId', () => {\n      // note: here we are only testing scopeId handling for vdom serialization.\n      // compiled srr render functions will include scopeId directly in strings.\n\n      test('basic', async () => {\n        const Foo = {\n          __scopeId: 'data-v-test',\n          render() {\n            return h('div')\n          },\n        }\n        expect(await render(h(Foo))).toBe(`<div data-v-test></div>`)\n      })\n\n      test('with client-compiled vnode slots', async () => {\n        const Child = {\n          __scopeId: 'data-v-child',\n          render: function (this: any) {\n            return h('div', null, [renderSlot(this.$slots, 'default')])\n          },\n        }\n\n        const Parent = {\n          __scopeId: 'data-v-test',\n          render: () => {\n            return h(Child, null, {\n              default: withCtx(() => [h('span', 'slot')]),\n            })\n          },\n        }\n\n        expect(await render(h(Parent))).toBe(\n          `<div data-v-child data-v-test>` +\n            `<!--[--><span data-v-test data-v-child-s>slot</span><!--]-->` +\n            `</div>`,\n        )\n      })\n    })\n\n    describe('integration w/ compiled template', () => {\n      test('render', async () => {\n        expect(\n          await render(\n            createApp({\n              data() {\n                return { msg: 'hello' }\n              },\n              template: `<div>{{ msg }}</div>`,\n            }),\n          ),\n        ).toBe(`<div>hello</div>`)\n      })\n\n      test('handle compiler errors', async () => {\n        await render(\n          // render different content since compilation is cached\n          createApp({ template: `<div>${type}</` }),\n        )\n\n        expect(\n          `Template compilation error: Unexpected EOF in tag.`,\n        ).toHaveBeenWarned()\n        expect(`Element is missing end tag`).toHaveBeenWarned()\n      })\n\n      // #6110\n      test('reset current instance after rendering error', async () => {\n        const prev = getCurrentInstance()\n        expect(prev).toBe(null)\n        try {\n          await render(\n            createApp({\n              data() {\n                return { msg: null }\n              },\n              template: `<div>{{ msg.text }}</div>`,\n            }),\n          )\n        } catch {}\n        expect(getCurrentInstance()).toBe(prev)\n      })\n\n      // #7733\n      test('reset current instance after error in data', async () => {\n        const prev = getCurrentInstance()\n        expect(prev).toBe(null)\n        try {\n          await render(\n            createApp({\n              data() {\n                throw new Error()\n              },\n              template: `<div>hello</div>`,\n            }),\n          )\n        } catch {}\n        expect(getCurrentInstance()).toBe(null)\n      })\n    })\n\n    // #7733\n    test('reset current instance after error in errorCaptured', async () => {\n      const prev = getCurrentInstance()\n\n      expect(prev).toBe(null)\n\n      const Child = {\n        created() {\n          throw new Error()\n        },\n      }\n      try {\n        await render(\n          createApp({\n            errorCaptured() {\n              throw new Error()\n            },\n            render: () => h(Child),\n          }),\n        )\n      } catch {}\n      expect(\n        'Unhandled error during execution of errorCaptured hook',\n      ).toHaveBeenWarned()\n      expect(getCurrentInstance()).toBe(null)\n    })\n\n    test('serverPrefetch', async () => {\n      const msg = Promise.resolve('hello')\n      const app = createApp({\n        data() {\n          return {\n            msg: '',\n          }\n        },\n        async serverPrefetch() {\n          this.msg = await msg\n        },\n        render() {\n          return h('div', this.msg)\n        },\n      })\n      const html = await render(app)\n      expect(html).toBe(`<div>hello</div>`)\n    })\n\n    test('serverPrefetch w/ async setup', async () => {\n      const msg = Promise.resolve('hello')\n      const app = createApp({\n        data() {\n          return {\n            msg: '',\n          }\n        },\n        async serverPrefetch() {\n          this.msg = await msg\n        },\n        render() {\n          return h('div', this.msg)\n        },\n        async setup() {},\n      })\n      const html = await render(app)\n      expect(html).toBe(`<div>hello</div>`)\n    })\n\n    // #2763\n    test('error handling w/ async setup', async () => {\n      const fn = vi.fn()\n      const fn2 = vi.fn()\n\n      const asyncChildren = defineComponent({\n        async setup() {\n          return Promise.reject('async child error')\n        },\n        template: `<div>asyncChildren</div>`,\n      })\n      const app = createApp({\n        name: 'App',\n        components: {\n          asyncChildren,\n        },\n        template: `<div class=\"app\"><async-children /></div>`,\n        errorCaptured(error) {\n          fn(error)\n        },\n      })\n\n      app.config.errorHandler = error => {\n        fn2(error)\n      }\n\n      const html = await renderToString(app)\n      expect(html).toBe(`<div class=\"app\"><div>asyncChildren</div></div>`)\n\n      expect(fn).toHaveBeenCalledTimes(1)\n      expect(fn).toBeCalledWith('async child error')\n\n      expect(fn2).toHaveBeenCalledTimes(1)\n      expect(fn2).toBeCalledWith('async child error')\n    })\n\n    // https://github.com/vuejs/core/issues/3322\n    test('effect onInvalidate does not error', async () => {\n      const noop = () => {}\n      const app = createApp({\n        setup: () => {\n          watchEffect(onInvalidate => onInvalidate(noop))\n        },\n        render: noop,\n      })\n      expect(await render(app)).toBe('<!---->')\n    })\n\n    // #2863\n    test('assets should be resolved correctly', async () => {\n      expect(\n        await render(\n          createApp({\n            components: {\n              A: {\n                ssrRender(_ctx, _push) {\n                  _push(`<div>A</div>`)\n                },\n              },\n              B: {\n                render: () => h('div', 'B'),\n              },\n            },\n            ssrRender(_ctx, _push, _parent) {\n              const A: any = resolveComponent('A')\n              _push(ssrRenderComponent(A, null, null, _parent))\n              ssrRenderVNode(\n                _push,\n                createVNode(resolveDynamicComponent('B'), null, null),\n                _parent,\n              )\n            },\n          }),\n        ),\n      ).toBe(`<div>A</div><div>B</div>`)\n    })\n\n    test('onServerPrefetch', async () => {\n      const msg = Promise.resolve('hello')\n      const app = createApp({\n        setup() {\n          const message = ref('')\n          onServerPrefetch(async () => {\n            message.value = await msg\n          })\n          return {\n            message,\n          }\n        },\n        render() {\n          return h('div', this.message)\n        },\n      })\n      const html = await render(app)\n      expect(html).toBe(`<div>hello</div>`)\n    })\n\n    test('multiple onServerPrefetch', async () => {\n      const msg = Promise.resolve('hello')\n      const msg2 = Promise.resolve('hi')\n      const msg3 = Promise.resolve('bonjour')\n      const app = createApp({\n        setup() {\n          const message = ref('')\n          const message2 = ref('')\n          const message3 = ref('')\n          onServerPrefetch(async () => {\n            message.value = await msg\n          })\n          onServerPrefetch(async () => {\n            message2.value = await msg2\n          })\n          onServerPrefetch(async () => {\n            message3.value = await msg3\n          })\n          return {\n            message,\n            message2,\n            message3,\n          }\n        },\n        render() {\n          return h('div', `${this.message} ${this.message2} ${this.message3}`)\n        },\n      })\n      const html = await render(app)\n      expect(html).toBe(`<div>hello hi bonjour</div>`)\n    })\n\n    test('onServerPrefetch are run in parallel', async () => {\n      const first = vi.fn(() => Promise.resolve())\n      const second = vi.fn(() => Promise.resolve())\n      let checkOther = [false, false]\n      let done = [false, false]\n      const app = createApp({\n        setup() {\n          onServerPrefetch(async () => {\n            checkOther[0] = done[1]\n            await first()\n            done[0] = true\n          })\n          onServerPrefetch(async () => {\n            checkOther[1] = done[0]\n            await second()\n            done[1] = true\n          })\n        },\n        render() {\n          return h('div', '')\n        },\n      })\n      await render(app)\n      expect(first).toHaveBeenCalled()\n      expect(second).toHaveBeenCalled()\n      expect(checkOther).toEqual([false, false])\n      expect(done).toEqual([true, true])\n    })\n\n    test('onServerPrefetch with serverPrefetch option', async () => {\n      const msg = Promise.resolve('hello')\n      const msg2 = Promise.resolve('hi')\n      const app = createApp({\n        data() {\n          return {\n            message: '',\n          }\n        },\n\n        async serverPrefetch() {\n          this.message = await msg\n        },\n\n        setup() {\n          const message2 = ref('')\n          onServerPrefetch(async () => {\n            message2.value = await msg2\n          })\n          return {\n            message2,\n          }\n        },\n        render() {\n          return h('div', `${this.message} ${this.message2}`)\n        },\n      })\n      const html = await render(app)\n      expect(html).toBe(`<div>hello hi</div>`)\n    })\n\n    test('mixed in serverPrefetch', async () => {\n      const msg = Promise.resolve('hello')\n      const app = createApp({\n        data() {\n          return {\n            msg: '',\n          }\n        },\n        mixins: [\n          {\n            async serverPrefetch() {\n              this.msg = await msg\n            },\n          },\n        ],\n        render() {\n          return h('div', this.msg)\n        },\n      })\n      const html = await render(app)\n      expect(html).toBe(`<div>hello</div>`)\n    })\n\n    test('many serverPrefetch', async () => {\n      const foo = Promise.resolve('foo')\n      const bar = Promise.resolve('bar')\n      const baz = Promise.resolve('baz')\n      const app = createApp({\n        data() {\n          return {\n            foo: '',\n            bar: '',\n            baz: '',\n          }\n        },\n        mixins: [\n          {\n            async serverPrefetch() {\n              this.foo = await foo\n            },\n          },\n          {\n            async serverPrefetch() {\n              this.bar = await bar\n            },\n          },\n        ],\n        async serverPrefetch() {\n          this.baz = await baz\n        },\n        render() {\n          return h('div', `${this.foo}${this.bar}${this.baz}`)\n        },\n      })\n      const html = await render(app)\n      expect(html).toBe(`<div>foobarbaz</div>`)\n    })\n\n    test('onServerPrefetch throwing error', async () => {\n      let renderError: Error | null = null\n      let capturedError: Error | null = null\n\n      const Child = {\n        setup() {\n          onServerPrefetch(async () => {\n            throw new Error('An error')\n          })\n        },\n        render() {\n          return h('span')\n        },\n      }\n\n      const app = createApp({\n        setup() {\n          onErrorCaptured(e => {\n            capturedError = e\n            return false\n          })\n        },\n        render() {\n          return h('div', h(Child))\n        },\n      })\n\n      try {\n        await render(app)\n      } catch (e: any) {\n        renderError = e\n      }\n      expect(renderError).toBe(null)\n      expect((capturedError as unknown as Error).message).toBe('An error')\n    })\n\n    test('computed reactivity during SSR with onServerPrefetch', async () => {\n      const store = {\n        // initial state could be hydrated\n        state: reactive({ items: null as null | string[] }),\n\n        // pretend to fetch some data from an api\n        async fetchData() {\n          this.state.items = ['hello', 'world']\n        },\n      }\n\n      const getterSpy = vi.fn()\n\n      const App = defineComponent(() => {\n        const msg = computed(() => {\n          getterSpy()\n          return store.state.items?.join(' ')\n        })\n\n        // If msg value is falsy then we are either in ssr context or on the client\n        // and the initial state was not modified/hydrated.\n        // In both cases we need to fetch data.\n        onServerPrefetch(() => store.fetchData())\n\n        // simulate the read from a composable (e.g. filtering a list of results)\n        msg.value\n\n        return () => h('div', null, msg.value)\n      })\n\n      const app = createSSRApp(App)\n\n      // in real world serve this html and append store state for hydration on client\n      const html = await renderToString(app)\n\n      expect(html).toMatch('hello world')\n\n      // should only be called twice since access should be cached\n      // during the render phase\n      expect(getterSpy).toHaveBeenCalledTimes(2)\n    })\n\n    test('props modifiers in render attrs', async () => {\n      const app = createApp({\n        setup() {\n          return () =>\n            h(\n              'div',\n              {\n                '^attr': 'attr',\n                '.prop': 'prop',\n              },\n              'Functional Component',\n            )\n        },\n      })\n      const html = await render(app)\n      expect(html).toBe(`<div attr=\"attr\">Functional Component</div>`)\n    })\n  })\n}\n"
  },
  {
    "path": "packages/server-renderer/__tests__/ssrAttrFallthrough.spec.ts",
    "content": "import { createApp } from 'vue'\nimport { renderToString } from '../src/renderToString'\n\ndescribe('ssr: attr fallthrough', () => {\n  test('basic', async () => {\n    const Child = {\n      template: `<div class=\"foo\" />`,\n    }\n    const Parent = {\n      components: { Child },\n      template: `<child class=\"bar\"/>`,\n    }\n    const app = createApp(Parent)\n    expect(await renderToString(app)).toBe(`<div class=\"foo bar\"></div>`)\n  })\n\n  test('with v-if', async () => {\n    const Child = {\n      props: ['ok'],\n      template: `<div v-if=\"ok\" class=\"foo\" /><span v-else />`,\n    }\n    const Parent = {\n      props: ['ok'],\n      components: { Child },\n      template: `<child :ok=\"ok\" class=\"bar\"/>`,\n    }\n    expect(await renderToString(createApp(Parent, { ok: true }))).toBe(\n      `<div class=\"foo bar\"></div>`,\n    )\n    expect(await renderToString(createApp(Parent, { ok: false }))).toBe(\n      `<span class=\"bar\"></span>`,\n    )\n  })\n\n  test('with v-model', async () => {\n    const Child = {\n      props: ['text'],\n      template: `<input v-model=\"text\">`,\n    }\n    const Parent = {\n      components: { Child },\n      template: `<child text=\"hello\" class=\"bar\"/>`,\n    }\n    expect(await renderToString(createApp(Parent))).toBe(\n      `<input class=\"bar\" value=\"hello\">`,\n    )\n  })\n\n  test('with v-bind', async () => {\n    const Child = {\n      props: ['obj'],\n      template: `<div v-bind=\"obj\" />`,\n    }\n    const Parent = {\n      components: { Child },\n      template: `<child :obj=\"{ class: 'foo' }\" class=\"bar\"/>`,\n    }\n    expect(await renderToString(createApp(Parent))).toBe(\n      `<div class=\"foo bar\"></div>`,\n    )\n  })\n\n  test('nested fallthrough', async () => {\n    const Child = {\n      props: ['id'],\n      template: `<div :id=\"id\"></div>`,\n    }\n    const Parent = {\n      components: { Child },\n      template: `<child id=\"foo\" class=\"bar\"/>`,\n    }\n    // pass to parent, fallthrough to child and merge\n    const app = createApp(Parent, { class: 'baz' })\n    expect(await renderToString(app)).toBe(\n      `<div id=\"foo\" class=\"bar baz\"></div>`,\n    )\n  })\n})\n"
  },
  {
    "path": "packages/server-renderer/__tests__/ssrCompilerOptions.spec.ts",
    "content": "import { createApp } from 'vue'\nimport { renderToString } from '../src/renderToString'\n\ndescribe('ssr: compiler options', () => {\n  test('config.isCustomElement (deprecated)', async () => {\n    const app = createApp({\n      template: `<div><x-button/></div>`,\n    })\n    app.config.isCustomElement = tag => tag.startsWith('x-')\n    expect(await renderToString(app)).toBe(`<div><x-button></x-button></div>`)\n  })\n\n  test('config.compilerOptions.isCustomElement', async () => {\n    const app = createApp({\n      template: `<div><x-panel/></div>`,\n    })\n    app.config.compilerOptions.isCustomElement = tag => tag.startsWith('x-')\n    expect(await renderToString(app)).toBe(`<div><x-panel></x-panel></div>`)\n  })\n\n  test('component.compilerOptions.isCustomElement', async () => {\n    const app = createApp({\n      template: `<div><x-card/><y-child/></div>`,\n      compilerOptions: {\n        isCustomElement: (tag: string) => tag.startsWith('x-'),\n      },\n      components: {\n        YChild: {\n          template: `<div><y-button/></div>`,\n        },\n      },\n    })\n    app.config.compilerOptions.isCustomElement = tag => tag.startsWith('y-')\n    expect(await renderToString(app)).toBe(\n      `<div><x-card></x-card><div><y-button></y-button></div></div>`,\n    )\n  })\n\n  test('component.delimiters (deprecated)', async () => {\n    const app = createApp({\n      template: `<div>[[ 1 + 1 ]]</div>`,\n      delimiters: ['[[', ']]'],\n    })\n    expect(await renderToString(app)).toBe(`<div>2</div>`)\n  })\n\n  test('config.compilerOptions.delimiters', async () => {\n    const app = createApp({\n      template: `<div>[( 1 + 1 )]</div>`,\n    })\n    app.config.compilerOptions.delimiters = ['[(', ')]']\n    expect(await renderToString(app)).toBe(`<div>2</div>`)\n  })\n\n  test('component.compilerOptions.delimiters', async () => {\n    const app = createApp({\n      template: `<div>[[ 1 + 1 ]]<ChildComponent/></div>`,\n      compilerOptions: {\n        delimiters: ['[[', ']]'],\n      },\n      components: {\n        ChildComponent: {\n          template: `<div>(( 2 + 2 ))</div>`,\n        },\n      },\n    })\n    app.config.compilerOptions.delimiters = ['((', '))']\n    expect(await renderToString(app)).toBe(`<div>2<div>4</div></div>`)\n  })\n\n  test('compilerOptions.whitespace', async () => {\n    const app = createApp({\n      template: `<div><span>Hello   world</span><ChildComponent/></div>`,\n      compilerOptions: {\n        whitespace: 'condense',\n      },\n      components: {\n        ChildComponent: {\n          template: `<span>Hello   world</span>`,\n        },\n      },\n    })\n    app.config.compilerOptions.whitespace = 'preserve'\n    expect(await renderToString(app)).toBe(\n      `<div><span>Hello world</span><span>Hello   world</span></div>`,\n    )\n  })\n\n  test('caching with compilerOptions', async () => {\n    const template = `<div>{{1 + 1}}   [[1 + 1]]</div>`\n\n    const app = createApp({\n      template: `<div><ChildOne/><ChildTwo/><ChildThree/></div>`,\n      components: {\n        ChildOne: {\n          template,\n        },\n        ChildTwo: {\n          template,\n          compilerOptions: {\n            whitespace: 'preserve',\n          },\n        },\n        ChildThree: {\n          template,\n          compilerOptions: {\n            delimiters: ['[[', ']]'],\n          },\n        },\n      },\n    })\n    expect(await renderToString(app)).toBe(\n      `<div><div>2 [[1 + 1]]</div><div>2   [[1 + 1]]</div><div>{{1 + 1}} 2</div></div>`,\n    )\n  })\n\n  test('caching with isCustomElement', async () => {\n    const template = `<div><MyChild/></div>`\n\n    const app = createApp({\n      template,\n      // No compilerOptions on the root\n      components: {\n        MyChild: {\n          template,\n          compilerOptions: {\n            isCustomElement: tag => tag.startsWith('x-'),\n          },\n          components: {\n            MyChild: {\n              template,\n              compilerOptions: {\n                isCustomElement: tag => tag.startsWith('My'),\n              },\n            },\n          },\n        },\n      },\n    })\n    expect(await renderToString(app)).toBe(\n      `<div><div><div><MyChild></MyChild></div></div></div>`,\n    )\n  })\n})\n"
  },
  {
    "path": "packages/server-renderer/__tests__/ssrComputed.spec.ts",
    "content": "import { computed, createSSRApp, defineComponent, h, reactive, ref } from 'vue'\nimport { renderToString } from '../src/renderToString'\n\n// #5208 reported memory leak of keeping computed alive during SSR\n// so we made computed properties created during SSR non-reactive in\n// https://github.com/vuejs/core/commit/f4f0966b33863ac0fca6a20cf9e8ddfbb311ae87\n// However, the default caching leads to #5300 which is tested below.\n// In Vue 2, computed properties are simple getters during SSR - this can be\n// inefficient if an expensive computed is accessed multiple times during render,\n// but because of potential mutations, we cannot cache it until we enter the\n// render phase (where no mutations can happen anymore)\ntest('computed reactivity during SSR', async () => {\n  const store = {\n    // initial state could be hydrated\n    state: reactive({ items: null }) as any,\n\n    // pretend to fetch some data from an api\n    async fetchData() {\n      this.state.items = ['hello', 'world']\n    },\n  }\n\n  const getterSpy = vi.fn()\n\n  const App = defineComponent(async () => {\n    const msg = computed(() => {\n      getterSpy()\n      return store.state.items?.join(' ')\n    })\n\n    // If msg value is falsy then we are either in ssr context or on the client\n    // and the initial state was not modified/hydrated.\n    // In both cases we need to fetch data.\n    if (!msg.value) await store.fetchData()\n\n    return () => h('div', null, msg.value + msg.value + msg.value)\n  })\n\n  const app = createSSRApp(App)\n\n  const html = await renderToString(app)\n  expect(html).toMatch('hello world')\n\n  // should only be called twice since access should be cached\n  // during the render phase\n  expect(getterSpy).toHaveBeenCalledTimes(2)\n})\n\n// although we technically shouldn't allow state mutation during render,\n// it does sometimes happen\ntest('computed mutation during render', async () => {\n  const App = defineComponent(async () => {\n    const n = ref(0)\n    const m = computed(() => n.value + 1)\n\n    m.value // force non-dirty\n\n    return () => {\n      n.value++\n      return h('div', null, `value: ${m.value}`)\n    }\n  })\n\n  const app = createSSRApp(App)\n  const html = await renderToString(app)\n  expect(html).toMatch('value: 2')\n})\n"
  },
  {
    "path": "packages/server-renderer/__tests__/ssrDirectives.spec.ts",
    "content": "import { renderToString } from '../src/renderToString'\nimport {\n  createApp,\n  h,\n  mergeProps,\n  ref,\n  resolveDirective,\n  unref,\n  vModelCheckbox,\n  vModelDynamic,\n  vModelRadio,\n  vModelText,\n  vShow,\n  withDirectives,\n} from 'vue'\nimport { ssrGetDirectiveProps, ssrRenderAttrs } from '../src'\n\ndescribe('ssr: directives', () => {\n  describe('template v-show', () => {\n    test('basic', async () => {\n      expect(\n        await renderToString(\n          createApp({\n            template: `<div v-show=\"true\"/>`,\n          }),\n        ),\n      ).toBe(`<div style=\"\"></div>`)\n\n      expect(\n        await renderToString(\n          createApp({\n            template: `<div v-show=\"false\"/>`,\n          }),\n        ),\n      ).toBe(`<div style=\"display:none;\"></div>`)\n    })\n\n    test('with static style', async () => {\n      expect(\n        await renderToString(\n          createApp({\n            template: `<div style=\"color:red\" v-show=\"false\"/>`,\n          }),\n        ),\n      ).toBe(`<div style=\"color:red;display:none;\"></div>`)\n    })\n\n    test('with dynamic style', async () => {\n      expect(\n        await renderToString(\n          createApp({\n            data: () => ({ style: { color: 'red' } }),\n            template: `<div :style=\"style\" v-show=\"false\"/>`,\n          }),\n        ),\n      ).toBe(`<div style=\"color:red;display:none;\"></div>`)\n    })\n\n    test('with static + dynamic style', async () => {\n      expect(\n        await renderToString(\n          createApp({\n            data: () => ({ style: { color: 'red' } }),\n            template: `<div :style=\"style\" style=\"font-size:12;\" v-show=\"false\"/>`,\n          }),\n        ),\n      ).toBe(`<div style=\"color:red;font-size:12;display:none;\"></div>`)\n    })\n  })\n\n  describe('template v-model', () => {\n    test('text', async () => {\n      expect(\n        await renderToString(\n          createApp({\n            data: () => ({ text: 'hello' }),\n            template: `<input v-model=\"text\">`,\n          }),\n        ),\n      ).toBe(`<input value=\"hello\">`)\n    })\n\n    test('radio', async () => {\n      expect(\n        await renderToString(\n          createApp({\n            data: () => ({ selected: 'foo' }),\n            template: `<input type=\"radio\" value=\"foo\" v-model=\"selected\">`,\n          }),\n        ),\n      ).toBe(`<input type=\"radio\" value=\"foo\" checked>`)\n\n      expect(\n        await renderToString(\n          createApp({\n            data: () => ({ selected: 'foo' }),\n            template: `<input type=\"radio\" value=\"bar\" v-model=\"selected\">`,\n          }),\n        ),\n      ).toBe(`<input type=\"radio\" value=\"bar\">`)\n\n      // non-string values\n      expect(\n        await renderToString(\n          createApp({\n            data: () => ({ selected: 'foo' }),\n            template: `<input type=\"radio\" :value=\"{}\" v-model=\"selected\">`,\n          }),\n        ),\n      ).toBe(`<input type=\"radio\">`)\n    })\n\n    test('select', async () => {\n      expect(\n        await renderToString(\n          createApp({\n            data: () => ({ model: 1 }),\n            template: `<select v-model=\"model\"><option value=\"0\"></option><option value=\"1\"></option></select>`,\n          }),\n        ),\n      ).toBe(\n        `<select><option value=\"0\"></option><option value=\"1\" selected></option></select>`,\n      )\n\n      expect(\n        await renderToString(\n          createApp({\n            data: () => ({ model: [0, 1] }),\n            template: `<select multiple v-model=\"model\"><option value=\"0\"></option><option value=\"1\"></option></select>`,\n          }),\n        ),\n      ).toBe(\n        `<select multiple><option value=\"0\" selected></option><option value=\"1\" selected></option></select>`,\n      )\n    })\n\n    test('checkbox', async () => {\n      expect(\n        await renderToString(\n          createApp({\n            data: () => ({ checked: true }),\n            template: `<input type=\"checkbox\" v-model=\"checked\">`,\n          }),\n        ),\n      ).toBe(`<input type=\"checkbox\" checked>`)\n\n      expect(\n        await renderToString(\n          createApp({\n            data: () => ({ checked: false }),\n            template: `<input type=\"checkbox\" v-model=\"checked\">`,\n          }),\n        ),\n      ).toBe(`<input type=\"checkbox\">`)\n\n      expect(\n        await renderToString(\n          createApp({\n            data: () => ({ checked: ['foo'] }),\n            template: `<input type=\"checkbox\" value=\"foo\" v-model=\"checked\">`,\n          }),\n        ),\n      ).toBe(`<input type=\"checkbox\" value=\"foo\" checked>`)\n\n      expect(\n        await renderToString(\n          createApp({\n            data: () => ({ checked: [] }),\n            template: `<input type=\"checkbox\" value=\"foo\" v-model=\"checked\">`,\n          }),\n        ),\n      ).toBe(`<input type=\"checkbox\" value=\"foo\">`)\n    })\n\n    test('textarea', async () => {\n      expect(\n        await renderToString(\n          createApp({\n            data: () => ({ foo: 'hello' }),\n            template: `<textarea v-model=\"foo\"/>`,\n          }),\n        ),\n      ).toBe(`<textarea>hello</textarea>`)\n    })\n\n    test('dynamic type', async () => {\n      expect(\n        await renderToString(\n          createApp({\n            data: () => ({ type: 'text', model: 'hello' }),\n            template: `<input :type=\"type\" v-model=\"model\">`,\n          }),\n        ),\n      ).toBe(`<input type=\"text\" value=\"hello\">`)\n\n      expect(\n        await renderToString(\n          createApp({\n            data: () => ({ type: 'checkbox', model: true }),\n            template: `<input :type=\"type\" v-model=\"model\">`,\n          }),\n        ),\n      ).toBe(`<input type=\"checkbox\" checked>`)\n\n      expect(\n        await renderToString(\n          createApp({\n            data: () => ({ type: 'checkbox', model: false }),\n            template: `<input :type=\"type\" v-model=\"model\">`,\n          }),\n        ),\n      ).toBe(`<input type=\"checkbox\">`)\n\n      expect(\n        await renderToString(\n          createApp({\n            data: () => ({ type: 'checkbox', model: ['hello'] }),\n            template: `<input :type=\"type\" value=\"hello\" v-model=\"model\">`,\n          }),\n        ),\n      ).toBe(`<input type=\"checkbox\" value=\"hello\" checked>`)\n\n      expect(\n        await renderToString(\n          createApp({\n            data: () => ({ type: 'checkbox', model: [] }),\n            template: `<input :type=\"type\" value=\"hello\" v-model=\"model\">`,\n          }),\n        ),\n      ).toBe(`<input type=\"checkbox\" value=\"hello\">`)\n\n      expect(\n        await renderToString(\n          createApp({\n            data: () => ({ type: 'radio', model: 'hello' }),\n            template: `<input :type=\"type\" value=\"hello\" v-model=\"model\">`,\n          }),\n        ),\n      ).toBe(`<input type=\"radio\" value=\"hello\" checked>`)\n\n      expect(\n        await renderToString(\n          createApp({\n            data: () => ({ type: 'radio', model: 'hello' }),\n            template: `<input :type=\"type\" value=\"bar\" v-model=\"model\">`,\n          }),\n        ),\n      ).toBe(`<input type=\"radio\" value=\"bar\">`)\n    })\n\n    test('with v-bind', async () => {\n      expect(\n        await renderToString(\n          createApp({\n            data: () => ({\n              obj: { type: 'radio', value: 'hello' },\n              model: 'hello',\n            }),\n            template: `<input v-bind=\"obj\" v-model=\"model\">`,\n          }),\n        ),\n      ).toBe(`<input type=\"radio\" value=\"hello\" checked>`)\n    })\n  })\n\n  describe('template with v-text / v-html', () => {\n    test('element with v-html', async () => {\n      expect(\n        await renderToString(\n          createApp({\n            data: () => ({ foo: 'hello' }),\n            template: `<span v-html=\"foo\"/>`,\n          }),\n        ),\n      ).toBe(`<span>hello</span>`)\n    })\n\n    test('textarea with v-text', async () => {\n      expect(\n        await renderToString(\n          createApp({\n            data: () => ({ foo: 'hello' }),\n            template: `<textarea v-text=\"foo\"/>`,\n          }),\n        ),\n      ).toBe(`<textarea>hello</textarea>`)\n    })\n\n    test('textarea with v-html', async () => {\n      expect(\n        await renderToString(\n          createApp({\n            data: () => ({ foo: 'hello' }),\n            template: `<textarea v-html=\"foo\"/>`,\n          }),\n        ),\n      ).toBe(`<textarea>hello</textarea>`)\n    })\n  })\n\n  describe('vnode v-show', () => {\n    test('basic', async () => {\n      expect(\n        await renderToString(\n          createApp({\n            render() {\n              return withDirectives(h('div'), [[vShow, true]])\n            },\n          }),\n        ),\n      ).toBe(`<div></div>`)\n\n      expect(\n        await renderToString(\n          createApp({\n            render() {\n              return withDirectives(h('div'), [[vShow, false]])\n            },\n          }),\n        ),\n      ).toBe(`<div style=\"display:none;\"></div>`)\n    })\n\n    test('with merge', async () => {\n      expect(\n        await renderToString(\n          createApp({\n            render() {\n              return withDirectives(\n                h('div', {\n                  style: {\n                    color: 'red',\n                  },\n                }),\n                [[vShow, false]],\n              )\n            },\n          }),\n        ),\n      ).toBe(`<div style=\"color:red;display:none;\"></div>`)\n    })\n  })\n\n  describe('vnode v-model', () => {\n    test('text', async () => {\n      expect(\n        await renderToString(\n          createApp({\n            render() {\n              return withDirectives(h('input'), [[vModelText, 'hello']])\n            },\n          }),\n        ),\n      ).toBe(`<input value=\"hello\">`)\n    })\n\n    test('radio', async () => {\n      expect(\n        await renderToString(\n          createApp({\n            render() {\n              return withDirectives(\n                h('input', { type: 'radio', value: 'hello' }),\n                [[vModelRadio, 'hello']],\n              )\n            },\n          }),\n        ),\n      ).toBe(`<input type=\"radio\" value=\"hello\" checked>`)\n\n      expect(\n        await renderToString(\n          createApp({\n            render() {\n              return withDirectives(\n                h('input', { type: 'radio', value: 'hello' }),\n                [[vModelRadio, 'foo']],\n              )\n            },\n          }),\n        ),\n      ).toBe(`<input type=\"radio\" value=\"hello\">`)\n    })\n\n    test('checkbox', async () => {\n      expect(\n        await renderToString(\n          createApp({\n            render() {\n              return withDirectives(h('input', { type: 'checkbox' }), [\n                [vModelCheckbox, true],\n              ])\n            },\n          }),\n        ),\n      ).toBe(`<input type=\"checkbox\" checked>`)\n\n      expect(\n        await renderToString(\n          createApp({\n            render() {\n              return withDirectives(h('input', { type: 'checkbox' }), [\n                [vModelCheckbox, false],\n              ])\n            },\n          }),\n        ),\n      ).toBe(`<input type=\"checkbox\">`)\n\n      expect(\n        await renderToString(\n          createApp({\n            render() {\n              return withDirectives(\n                h('input', { type: 'checkbox', value: 'foo' }),\n                [[vModelCheckbox, ['foo']]],\n              )\n            },\n          }),\n        ),\n      ).toBe(`<input type=\"checkbox\" value=\"foo\" checked>`)\n\n      expect(\n        await renderToString(\n          createApp({\n            render() {\n              return withDirectives(\n                h('input', { type: 'checkbox', value: 'foo' }),\n                [[vModelCheckbox, []]],\n              )\n            },\n          }),\n        ),\n      ).toBe(`<input type=\"checkbox\" value=\"foo\">`)\n    })\n  })\n\n  describe('vnode v-model dynamic', () => {\n    test('text', async () => {\n      expect(\n        await renderToString(\n          createApp({\n            render() {\n              return withDirectives(h('input'), [[vModelDynamic, 'hello']])\n            },\n          }),\n        ),\n      ).toBe(`<input value=\"hello\">`)\n    })\n\n    test('radio', async () => {\n      expect(\n        await renderToString(\n          createApp({\n            render() {\n              return withDirectives(\n                h('input', { type: 'radio', value: 'hello' }),\n                [[vModelDynamic, 'hello']],\n              )\n            },\n          }),\n        ),\n      ).toBe(`<input type=\"radio\" value=\"hello\" checked>`)\n\n      expect(\n        await renderToString(\n          createApp({\n            render() {\n              return withDirectives(\n                h('input', { type: 'radio', value: 'hello' }),\n                [[vModelDynamic, 'foo']],\n              )\n            },\n          }),\n        ),\n      ).toBe(`<input type=\"radio\" value=\"hello\">`)\n    })\n\n    test('checkbox', async () => {\n      expect(\n        await renderToString(\n          createApp({\n            render() {\n              return withDirectives(h('input', { type: 'checkbox' }), [\n                [vModelDynamic, true],\n              ])\n            },\n          }),\n        ),\n      ).toBe(`<input type=\"checkbox\" checked>`)\n\n      expect(\n        await renderToString(\n          createApp({\n            render() {\n              return withDirectives(h('input', { type: 'checkbox' }), [\n                [vModelDynamic, false],\n              ])\n            },\n          }),\n        ),\n      ).toBe(`<input type=\"checkbox\">`)\n\n      expect(\n        await renderToString(\n          createApp({\n            render() {\n              return withDirectives(\n                h('input', { type: 'checkbox', value: 'foo' }),\n                [[vModelDynamic, ['foo']]],\n              )\n            },\n          }),\n        ),\n      ).toBe(`<input type=\"checkbox\" value=\"foo\" checked>`)\n\n      expect(\n        await renderToString(\n          createApp({\n            render() {\n              return withDirectives(\n                h('input', { type: 'checkbox', value: 'foo' }),\n                [[vModelDynamic, []]],\n              )\n            },\n          }),\n        ),\n      ).toBe(`<input type=\"checkbox\" value=\"foo\">`)\n    })\n  })\n\n  test('custom directive w/ getSSRProps (vdom)', async () => {\n    expect(\n      await renderToString(\n        createApp({\n          render() {\n            return withDirectives(h('div'), [\n              [\n                {\n                  getSSRProps({ value }) {\n                    return { id: value }\n                  },\n                },\n                'foo',\n              ],\n            ])\n          },\n        }),\n      ),\n    ).toBe(`<div id=\"foo\"></div>`)\n  })\n\n  test('custom directive w/ getSSRProps (optimized)', async () => {\n    expect(\n      await renderToString(\n        createApp({\n          data() {\n            return {\n              x: 'foo',\n            }\n          },\n          directives: {\n            xxx: {\n              getSSRProps({ value, arg, modifiers }) {\n                return { id: [value, arg, modifiers.ok].join('-') }\n              },\n            },\n          },\n          ssrRender(_ctx, _push, _parent, _attrs) {\n            const _directive_xxx = resolveDirective('xxx')!\n            _push(\n              `<div${ssrRenderAttrs(\n                ssrGetDirectiveProps(_ctx, _directive_xxx, _ctx.x, 'arg', {\n                  ok: true,\n                }),\n              )}></div>`,\n            )\n          },\n        }),\n      ),\n    ).toBe(`<div id=\"foo-arg-true\"></div>`)\n  })\n\n  // #7499\n  test('custom directive w/ getSSRProps (expose)', async () => {\n    let exposeVars: null | string | undefined = null\n    const useTestDirective = () => ({\n      vTest: {\n        getSSRProps({ instance }: any) {\n          if (instance) {\n            exposeVars = instance.x\n          }\n          return { id: exposeVars }\n        },\n      },\n    })\n    const { vTest } = useTestDirective()\n\n    const renderString = await renderToString(\n      createApp({\n        setup(props, { expose }) {\n          const x = ref('foo')\n          expose({ x })\n          const __returned__ = { useTestDirective, vTest, ref, x }\n          Object.defineProperty(__returned__, '__isScriptSetup', {\n            enumerable: false,\n            value: true,\n          })\n          return __returned__\n        },\n        ssrRender(_ctx, _push, _parent, _attrs) {\n          _push(\n            `<div${ssrRenderAttrs(\n              mergeProps(_attrs!, ssrGetDirectiveProps(_ctx, unref(vTest))),\n            )}></div>`,\n          )\n        },\n      }),\n    )\n    expect(renderString).toBe(`<div id=\"foo\"></div>`)\n    expect(exposeVars).toBe('foo')\n  })\n})\n"
  },
  {
    "path": "packages/server-renderer/__tests__/ssrDynamicComponent.spec.ts",
    "content": "import { createApp, createVNode } from 'vue'\nimport { renderToString } from '../src'\n\ndescribe('ssr: dynamic component', () => {\n  test('resolved to component', async () => {\n    expect(\n      await renderToString(\n        createApp({\n          components: {\n            one: {\n              template: `<div><slot/></div>`,\n            },\n          },\n          template: `<component :is=\"'one'\"><span>slot</span></component>`,\n        }),\n      ),\n    ).toBe(`<div><!--[--><span>slot</span><!--]--></div>`)\n  })\n\n  test('resolved to component with v-show', async () => {\n    expect(\n      await renderToString(\n        createApp({\n          components: {\n            one: {\n              template: `<component is=\"div\"><slot/></component>`,\n            },\n          },\n          template: `<one><one v-show=\"false\">hi</one></one>`,\n        }),\n      ),\n    ).toBe(\n      `<div><!--[--><div style=\\\"display:none;\\\"><!--[-->hi<!--]--></div><!--]--></div>`,\n    )\n  })\n\n  test('resolve to element', async () => {\n    expect(\n      await renderToString(\n        createApp({\n          template: `<component :is=\"'p'\"><span>slot</span></component>`,\n        }),\n      ),\n    ).toBe(`<p><span>slot</span></p>`)\n  })\n\n  test('resolve to component vnode', async () => {\n    const Child = {\n      props: ['id'],\n      template: `<div>{{ id }}<slot/></div>`,\n    }\n    expect(\n      await renderToString(\n        createApp({\n          setup() {\n            return {\n              vnode: createVNode(Child, { id: 'test' }),\n            }\n          },\n          template: `<component :is=\"vnode\"><span>slot</span></component>`,\n        }),\n      ),\n    ).toBe(`<div>test<!--[--><span>slot</span><!--]--></div>`)\n  })\n\n  test('resolve to element vnode', async () => {\n    expect(\n      await renderToString(\n        createApp({\n          setup() {\n            return {\n              vnode: createVNode('div', { id: 'test' }),\n            }\n          },\n          template: `<component :is=\"vnode\"><span>slot</span></component>`,\n        }),\n      ),\n    ).toBe(`<div id=\"test\"><span>slot</span></div>`)\n  })\n})\n"
  },
  {
    "path": "packages/server-renderer/__tests__/ssrInterpolate.spec.ts",
    "content": "import { ssrInterpolate } from '../src/helpers/ssrInterpolate'\nimport { escapeHtml } from '@vue/shared'\n\ntest('ssr: interpolate', () => {\n  expect(ssrInterpolate(0)).toBe(`0`)\n  expect(ssrInterpolate(`foo`)).toBe(`foo`)\n  expect(ssrInterpolate(`<div>`)).toBe(`&lt;div&gt;`)\n  // should escape interpolated values\n  expect(ssrInterpolate([1, 2, 3])).toBe(\n    escapeHtml(JSON.stringify([1, 2, 3], null, 2)),\n  )\n  expect(\n    ssrInterpolate({\n      foo: 1,\n      bar: `<div>`,\n    }),\n  ).toBe(\n    escapeHtml(\n      JSON.stringify(\n        {\n          foo: 1,\n          bar: `<div>`,\n        },\n        null,\n        2,\n      ),\n    ),\n  )\n})\n"
  },
  {
    "path": "packages/server-renderer/__tests__/ssrRenderAttrs.spec.ts",
    "content": "import {\n  ssrRenderAttr,\n  ssrRenderAttrs,\n  ssrRenderClass,\n  ssrRenderStyle,\n} from '../src/helpers/ssrRenderAttrs'\nimport { escapeHtml } from '@vue/shared'\n\ndescribe('ssr: renderAttrs', () => {\n  test('ignore reserved props', () => {\n    expect(\n      ssrRenderAttrs({\n        key: 1,\n        ref_key: 'foo',\n        ref_for: 'bar',\n        ref: () => {},\n        onClick: () => {},\n      }),\n    ).toBe('')\n  })\n\n  test('normal attrs', () => {\n    expect(\n      ssrRenderAttrs({\n        id: 'foo',\n        title: 'bar',\n      }),\n    ).toBe(` id=\"foo\" title=\"bar\"`)\n  })\n\n  test('empty value attrs', () => {\n    expect(\n      ssrRenderAttrs({\n        'data-v-abc': '',\n      }),\n    ).toBe(` data-v-abc`)\n  })\n\n  test('escape attrs', () => {\n    expect(\n      ssrRenderAttrs({\n        id: '\"><script',\n      }),\n    ).toBe(` id=\"&quot;&gt;&lt;script\"`)\n  })\n\n  test('boolean attrs', () => {\n    expect(\n      ssrRenderAttrs({\n        checked: true,\n        multiple: false,\n        readonly: 0,\n        disabled: '',\n      }),\n    ).toBe(` checked disabled`) // boolean attr w/ false should be ignored\n  })\n\n  test('ignore falsy values', () => {\n    expect(\n      ssrRenderAttrs({\n        foo: false,\n        title: null,\n        baz: undefined,\n      }),\n    ).toBe(` foo=\"false\"`) // non boolean should render `false` as is\n  })\n\n  test('ignore non-renderable values', () => {\n    expect(\n      ssrRenderAttrs({\n        foo: {},\n        bar: [],\n        baz: () => {},\n      }),\n    ).toBe(``)\n  })\n\n  test('props to attrs', () => {\n    expect(\n      ssrRenderAttrs({\n        readOnly: true, // simple lower case conversion\n        htmlFor: 'foobar', // special cases\n      }),\n    ).toBe(` readonly for=\"foobar\"`)\n  })\n\n  test('preserve name on custom element', () => {\n    expect(\n      ssrRenderAttrs(\n        {\n          fooBar: 'ok',\n        },\n        'my-el',\n      ),\n    ).toBe(` fooBar=\"ok\"`)\n  })\n\n  test('preserve name on svg elements', () => {\n    expect(\n      ssrRenderAttrs(\n        {\n          viewBox: 'foo',\n        },\n        'svg',\n      ),\n    ).toBe(` viewBox=\"foo\"`)\n  })\n})\n\ndescribe('ssr: renderAttr', () => {\n  test('basic', () => {\n    expect(ssrRenderAttr('foo', 'bar')).toBe(` foo=\"bar\"`)\n  })\n\n  test('null and undefined', () => {\n    expect(ssrRenderAttr('foo', null)).toBe(``)\n    expect(ssrRenderAttr('foo', undefined)).toBe(``)\n  })\n\n  test('escape', () => {\n    expect(ssrRenderAttr('foo', '<script>')).toBe(\n      ` foo=\"${escapeHtml(`<script>`)}\"`,\n    )\n  })\n})\n\ndescribe('ssr: renderClass', () => {\n  test('via renderProps', () => {\n    expect(\n      ssrRenderAttrs({\n        class: ['foo', 'bar'],\n      }),\n    ).toBe(` class=\"foo bar\"`)\n  })\n\n  test('standalone', () => {\n    expect(ssrRenderClass(`foo`)).toBe(`foo`)\n    expect(ssrRenderClass([`foo`, `bar`])).toBe(`foo bar`)\n    expect(ssrRenderClass({ foo: true, bar: false })).toBe(`foo`)\n    expect(ssrRenderClass([{ foo: true, bar: false }, `baz`])).toBe(`foo baz`)\n  })\n\n  test('escape class values', () => {\n    expect(ssrRenderClass(`\"><script`)).toBe(`&quot;&gt;&lt;script`)\n  })\n\n  test('className', () => {\n    expect(\n      ssrRenderAttrs({\n        className: 'foo',\n      }),\n    ).toBe(` class=\"foo\"`)\n    expect(\n      ssrRenderAttrs({\n        className: ['foo', 'bar'],\n      }),\n    ).toBe(` class=\"foo,bar\"`)\n  })\n})\n\ndescribe('ssr: renderStyle', () => {\n  test('via renderProps', () => {\n    expect(\n      ssrRenderAttrs({\n        style: {\n          color: 'red',\n          '--a': 2,\n          '-webkit-line-clamp': 1,\n        },\n      }),\n    ).toBe(` style=\"color:red;--a:2;-webkit-line-clamp:1;\"`)\n  })\n\n  test('standalone', () => {\n    expect(ssrRenderStyle(`color:red`)).toBe(`color:red`)\n    expect(\n      ssrRenderStyle({\n        color: `red`,\n      }),\n    ).toBe(`color:red;`)\n    expect(\n      ssrRenderStyle([\n        { color: `red` },\n        { fontSize: `15px` }, // case conversion\n      ]),\n    ).toBe(`color:red;font-size:15px;`)\n  })\n\n  test('number handling', () => {\n    expect(\n      ssrRenderStyle({\n        fontSize: null, // invalid value should be ignored\n        opacity: 0.5,\n      }),\n    ).toBe(`opacity:0.5;`)\n  })\n\n  test('escape inline CSS', () => {\n    expect(ssrRenderStyle(`\"><script`)).toBe(`&quot;&gt;&lt;script`)\n    expect(\n      ssrRenderStyle({\n        color: `\"><script`,\n      }),\n    ).toBe(`color:&quot;&gt;&lt;script;`)\n  })\n\n  test('useCssVars handling', () => {\n    expect(\n      ssrRenderStyle({\n        fontSize: null,\n        ':--v1': undefined,\n        ':--v2': null,\n        ':--v3': '',\n        ':--v4': '  ',\n        ':--v5': 'foo',\n        ':--v6': 0,\n        '--foo': 1,\n      }),\n    ).toBe(`--v1:initial;--v2:initial;--v3: ;--v4:  ;--v5:foo;--v6:0;--foo:1;`)\n  })\n})\n"
  },
  {
    "path": "packages/server-renderer/__tests__/ssrRenderList.spec.ts",
    "content": "import { ssrRenderList } from '../src/helpers/ssrRenderList'\n\ndescribe('ssr: renderList', () => {\n  let stack: string[] = []\n\n  beforeEach(() => {\n    stack = []\n  })\n\n  it('should render items in an array', () => {\n    ssrRenderList(['1', '2', '3'], (item, index) =>\n      stack.push(`node ${index}: ${item}`),\n    )\n    expect(stack).toEqual(['node 0: 1', 'node 1: 2', 'node 2: 3'])\n  })\n\n  it('should render characters of a string', () => {\n    ssrRenderList('abc', (item, index) => stack.push(`node ${index}: ${item}`))\n    expect(stack).toEqual(['node 0: a', 'node 1: b', 'node 2: c'])\n  })\n\n  it('should render integers 1 through N when given a number N', () => {\n    ssrRenderList(3, (item, index) => stack.push(`node ${index}: ${item}`))\n    expect(stack).toEqual(['node 0: 1', 'node 1: 2', 'node 2: 3'])\n  })\n\n  it('should warn when given a non-integer N', () => {\n    ssrRenderList(3.1, () => {})\n    expect(\n      `The v-for range expects a positive integer value but got 3.1.`,\n    ).toHaveBeenWarned()\n  })\n\n  it('should warn when given a negative N', () => {\n    ssrRenderList(-1, () => {})\n    expect(\n      `The v-for range expects a positive integer value but got -1.`,\n    ).toHaveBeenWarned()\n  })\n\n  it('should not warn when given 0', () => {\n    ssrRenderList(0, () => {})\n    expect(\n      `The v-for range expects a positive integer value but got 0.`,\n    ).not.toHaveBeenWarned()\n  })\n\n  it('should render properties in an object', () => {\n    ssrRenderList({ a: 1, b: 2, c: 3 }, (item, key, index) =>\n      stack.push(`node ${index}/${key}: ${item}`),\n    )\n    expect(stack).toEqual(['node 0/a: 1', 'node 1/b: 2', 'node 2/c: 3'])\n  })\n\n  it('should render an item for entry in an iterable', () => {\n    const iterable = function* () {\n      yield 1\n      yield 2\n      yield 3\n    }\n\n    ssrRenderList(iterable(), (item, index) =>\n      stack.push(`node ${index}: ${item}`),\n    )\n    expect(stack).toEqual(['node 0: 1', 'node 1: 2', 'node 2: 3'])\n  })\n\n  it('should not render items when source is 0', () => {\n    ssrRenderList(0, (item, index) => stack.push(`node ${index}: ${item}`))\n    expect(stack).toEqual([])\n  })\n\n  it('should not render items when source is undefined', () => {\n    ssrRenderList(undefined, (item, index) =>\n      stack.push(`node ${index}: ${item}`),\n    )\n    expect(stack).toEqual([])\n  })\n})\n"
  },
  {
    "path": "packages/server-renderer/__tests__/ssrScopeId.spec.ts",
    "content": "import { createApp, h, mergeProps, withCtx } from 'vue'\nimport { renderToString } from '../src/renderToString'\nimport { ssrRenderAttrs, ssrRenderComponent, ssrRenderSlot } from '../src'\n\ndescribe('ssr: scopedId runtime behavior', () => {\n  test('id on component root', async () => {\n    const Child = {\n      ssrRender: (ctx: any, push: any, parent: any, attrs: any) => {\n        push(`<div${ssrRenderAttrs(attrs)}></div>`)\n      },\n    }\n\n    const Comp = {\n      __scopeId: 'parent',\n      ssrRender: (ctx: any, push: any, parent: any) => {\n        push(ssrRenderComponent(Child), null, null, parent)\n      },\n    }\n\n    const result = await renderToString(createApp(Comp))\n    expect(result).toBe(`<div parent></div>`)\n  })\n\n  test('id and :slotted on component root', async () => {\n    const Child = {\n      // <div></div>\n      ssrRender: (_: any, push: any, _parent: any, attrs: any) => {\n        push(`<div${ssrRenderAttrs(attrs)} child></div>`)\n      },\n    }\n\n    const Wrapper = {\n      __scopeId: 'wrapper',\n      ssrRender: (ctx: any, push: any, parent: any) => {\n        // <slot/>\n        ssrRenderSlot(\n          ctx.$slots,\n          'default',\n          {},\n          null,\n          push,\n          parent,\n          'wrapper-s',\n        )\n      },\n    }\n\n    const Comp = {\n      __scopeId: 'parent',\n      ssrRender: (_: any, push: any, parent: any) => {\n        // <Wrapper><Child/></Wrapper>\n        push(\n          ssrRenderComponent(\n            Wrapper,\n            null,\n            {\n              default: withCtx(\n                (_: any, push: any, parent: any, scopeId: string) => {\n                  push(ssrRenderComponent(Child, null, null, parent, scopeId))\n                },\n              ),\n              _: 1,\n            } as any,\n            parent,\n          ),\n        )\n      },\n    }\n\n    const result = await renderToString(createApp(Comp))\n    expect(result).toBe(`<!--[--><div parent wrapper-s child></div><!--]-->`)\n  })\n\n  // #2892\n  test(':slotted on forwarded slots', async () => {\n    const Wrapper = {\n      __scopeId: 'wrapper',\n      ssrRender: (ctx: any, push: any, parent: any, attrs: any) => {\n        // <div class=\"wrapper\"><slot/></div>\n        push(\n          `<div${ssrRenderAttrs(\n            mergeProps({ class: 'wrapper' }, attrs),\n          )} wrapper>`,\n        )\n        ssrRenderSlot(\n          ctx.$slots,\n          'default',\n          {},\n          null,\n          push,\n          parent,\n          'wrapper-s',\n        )\n        push(`</div>`)\n      },\n    }\n\n    const Slotted = {\n      __scopeId: 'slotted',\n      ssrRender: (ctx: any, push: any, parent: any, attrs: any) => {\n        // <Wrapper><slot/></Wrapper>\n        push(\n          ssrRenderComponent(\n            Wrapper,\n            attrs,\n            {\n              default: withCtx(\n                (_: any, push: any, parent: any, scopeId: string) => {\n                  ssrRenderSlot(\n                    ctx.$slots,\n                    'default',\n                    {},\n                    null,\n                    push,\n                    parent,\n                    'slotted-s' + scopeId,\n                  )\n                },\n              ),\n              _: 1,\n            } as any,\n            parent,\n          ),\n        )\n      },\n    }\n\n    const Root = {\n      __scopeId: 'root',\n      // <Slotted><div></div></Slotted>\n      ssrRender: (_: any, push: any, parent: any, attrs: any) => {\n        push(\n          ssrRenderComponent(\n            Slotted,\n            attrs,\n            {\n              default: withCtx(\n                (_: any, push: any, parent: any, scopeId: string) => {\n                  push(`<div root${scopeId}></div>`)\n                },\n              ),\n              _: 1,\n            } as any,\n            parent,\n          ),\n        )\n      },\n    }\n\n    const result = await renderToString(createApp(Root))\n    expect(result).toBe(\n      `<div class=\"wrapper\" root slotted wrapper>` +\n        `<!--[--><!--[--><div root slotted-s wrapper-s></div><!--]--><!--]-->` +\n        `</div>`,\n    )\n  })\n\n  // #3513\n  test('scopeId inheritance across ssr-compiled and on-ssr compiled parent chain', async () => {\n    const Child = {\n      ssrRender: (ctx: any, push: any, parent: any, attrs: any) => {\n        push(`<div${ssrRenderAttrs(attrs)}></div>`)\n      },\n    }\n\n    const Middle = {\n      render() {\n        return h(Child)\n      },\n    }\n\n    const Comp = {\n      __scopeId: 'parent',\n      ssrRender: (ctx: any, push: any, parent: any) => {\n        push(ssrRenderComponent(Middle, null, null, parent))\n      },\n    }\n\n    const result = await renderToString(createApp(Comp)) // output: `<div></div>`\n    expect(result).toBe(`<div parent></div>`)\n  })\n\n  // #6093\n  test(':slotted on forwarded slots on component', async () => {\n    const Wrapper = {\n      __scopeId: 'wrapper',\n      ssrRender: (ctx: any, push: any, parent: any, attrs: any) => {\n        // <div class=\"wrapper\"><slot/></div>\n        push(\n          `<div${ssrRenderAttrs(\n            mergeProps({ class: 'wrapper' }, attrs),\n          )} wrapper>`,\n        )\n        ssrRenderSlot(\n          ctx.$slots,\n          'default',\n          {},\n          null,\n          push,\n          parent,\n          'wrapper-s',\n        )\n        push(`</div>`)\n      },\n    }\n\n    const Slotted = {\n      __scopeId: 'slotted',\n      ssrRender: (ctx: any, push: any, parent: any, attrs: any) => {\n        // <Wrapper><slot/></Wrapper>\n        push(\n          ssrRenderComponent(\n            Wrapper,\n            attrs,\n            {\n              default: withCtx(\n                (_: any, push: any, parent: any, scopeId: string) => {\n                  ssrRenderSlot(\n                    ctx.$slots,\n                    'default',\n                    {},\n                    null,\n                    push,\n                    parent,\n                    'slotted-s' + scopeId,\n                  )\n                },\n              ),\n              _: 1,\n            } as any,\n            parent,\n          ),\n        )\n      },\n    }\n\n    const Child = {\n      ssrRender: (ctx: any, push: any, parent: any, attrs: any) => {\n        push(`<div${ssrRenderAttrs(attrs)}></div>`)\n      },\n    }\n\n    const Root = {\n      __scopeId: 'root',\n      // <Slotted><Child></Child></Slotted>\n      ssrRender: (_: any, push: any, parent: any, attrs: any) => {\n        push(\n          ssrRenderComponent(\n            Slotted,\n            attrs,\n            {\n              default: withCtx(\n                (_: any, push: any, parent: any, scopeId: string) => {\n                  push(ssrRenderComponent(Child, null, null, parent, scopeId))\n                },\n              ),\n              _: 1,\n            } as any,\n            parent,\n          ),\n        )\n      },\n    }\n\n    const result = await renderToString(createApp(Root))\n    expect(result).toBe(\n      `<div class=\"wrapper\" root slotted wrapper>` +\n        `<!--[--><!--[--><div root slotted-s wrapper-s></div><!--]--><!--]-->` +\n        `</div>`,\n    )\n  })\n})\n"
  },
  {
    "path": "packages/server-renderer/__tests__/ssrSlot.spec.ts",
    "content": "import { createApp, defineAsyncComponent, h } from 'vue'\nimport { renderToString } from '../src/renderToString'\n\nconst components = {\n  one: {\n    template: `<div><slot/></div>`,\n  },\n}\n\ndescribe('ssr: slot', () => {\n  test('text slot', async () => {\n    expect(\n      await renderToString(\n        createApp({\n          components,\n          template: `<one>hello</one>`,\n        }),\n      ),\n    ).toBe(`<div><!--[-->hello<!--]--></div>`)\n  })\n\n  test('element slot', async () => {\n    expect(\n      await renderToString(\n        createApp({\n          components,\n          template: `<one><div>hi</div></one>`,\n        }),\n      ),\n    ).toBe(`<div><!--[--><div>hi</div><!--]--></div>`)\n  })\n\n  test('empty slot', async () => {\n    expect(\n      await renderToString(\n        createApp({\n          components: {\n            one: {\n              template: `<div><slot/></div>`,\n            },\n          },\n          template: `<one><template v-if=\"false\"/></one>`,\n        }),\n      ),\n    ).toBe(`<div><!--[--><!--]--></div>`)\n  })\n\n  test('empty slot (manual comments)', async () => {\n    expect(\n      await renderToString(\n        createApp({\n          components: {\n            one: {\n              template: `<div><slot/></div>`,\n            },\n          },\n          template: `<one><!--hello--></one>`,\n        }),\n      ),\n    ).toBe(`<div><!--[--><!--]--></div>`)\n  })\n\n  test('empty slot (multi-line comments)', async () => {\n    expect(\n      await renderToString(\n        createApp({\n          components: {\n            one: {\n              template: `<div><slot/></div>`,\n            },\n          },\n          template: `<one><!--he\\nllo--></one>`,\n        }),\n      ),\n    ).toBe(`<div><!--[--><!--]--></div>`)\n  })\n\n  test('multiple elements', async () => {\n    expect(\n      await renderToString(\n        createApp({\n          components,\n          template: `<one><div>one</div><div>two</div></one>`,\n        }),\n      ),\n    ).toBe(`<div><!--[--><div>one</div><div>two</div><!--]--></div>`)\n  })\n\n  test('fragment slot (template v-if)', async () => {\n    expect(\n      await renderToString(\n        createApp({\n          components,\n          template: `<one><template v-if=\"true\">hello</template></one>`,\n        }),\n      ),\n    ).toBe(`<div><!--[--><!--[-->hello<!--]--><!--]--></div>`)\n  })\n\n  test('fragment slot (template v-if + multiple elements)', async () => {\n    expect(\n      await renderToString(\n        createApp({\n          components,\n          template: `<one><template v-if=\"true\"><div>one</div><div>two</div></template></one>`,\n        }),\n      ),\n    ).toBe(\n      `<div><!--[--><!--[--><div>one</div><div>two</div><!--]--><!--]--></div>`,\n    )\n  })\n\n  test('transition slot', async () => {\n    const ReusableTransition = {\n      template: `<transition><slot/></transition>`,\n    }\n\n    const ReusableTransitionWithAppear = {\n      template: `<transition appear><slot/></transition>`,\n    }\n\n    expect(\n      await renderToString(\n        createApp({\n          components: {\n            one: ReusableTransition,\n          },\n          template: `<one><div v-if=\"false\">foo</div></one>`,\n        }),\n      ),\n    ).toBe(`<!---->`)\n\n    expect(await renderToString(createApp(ReusableTransition))).toBe(`<!---->`)\n\n    expect(await renderToString(createApp(ReusableTransitionWithAppear))).toBe(\n      `<template><!----></template>`,\n    )\n\n    expect(\n      await renderToString(\n        createApp({\n          components: {\n            one: ReusableTransition,\n          },\n          template: `<one><slot/></one>`,\n        }),\n      ),\n    ).toBe(`<!---->`)\n\n    expect(\n      await renderToString(\n        createApp({\n          components: {\n            one: ReusableTransitionWithAppear,\n          },\n          template: `<one><slot/></one>`,\n        }),\n      ),\n    ).toBe(`<template><!----></template>`)\n\n    expect(\n      await renderToString(\n        createApp({\n          render() {\n            return h(ReusableTransition, null, {\n              default: () => null,\n            })\n          },\n        }),\n      ),\n    ).toBe(`<!---->`)\n\n    expect(\n      await renderToString(\n        createApp({\n          render() {\n            return h(ReusableTransitionWithAppear, null, {\n              default: () => null,\n            })\n          },\n        }),\n      ),\n    ).toBe(`<template><!----></template>`)\n\n    expect(\n      await renderToString(\n        createApp({\n          render() {\n            return h(ReusableTransitionWithAppear, null, {\n              default: () => [],\n            })\n          },\n        }),\n      ),\n    ).toBe(`<template><!----></template>`)\n\n    expect(\n      await renderToString(\n        createApp({\n          render() {\n            return h(ReusableTransition, null, {\n              default: () => [],\n            })\n          },\n        }),\n      ),\n    ).toBe(`<!---->`)\n\n    expect(\n      await renderToString(\n        createApp({\n          components: {\n            one: ReusableTransition,\n          },\n          template: `<one><div v-if=\"true\">foo</div></one>`,\n        }),\n      ),\n    ).toBe(`<div>foo</div>`)\n  })\n\n  // #9933\n  test('transition-group slot', async () => {\n    expect(\n      await renderToString(\n        createApp({\n          components: {\n            one: {\n              template: `<TransitionGroup tag=\"div\"><slot/></TransitionGroup>`,\n            },\n          },\n          template: `<one><p v-for=\"i in 2\">{{i}}</p></one>`,\n        }),\n      ),\n    ).toBe(`<div><p>1</p><p>2</p></div>`)\n  })\n\n  // #12438\n  test('async component slot with v-if true', async () => {\n    const Layout = defineAsyncComponent(() =>\n      Promise.resolve({\n        template: `<div><slot name=\"header\">default header</slot></div>`,\n      }),\n    )\n    const LayoutLoader = {\n      setup(_: any, context: any) {\n        return () => h(Layout, {}, context.slots)\n      },\n    }\n    expect(\n      await renderToString(\n        createApp({\n          components: {\n            LayoutLoader,\n          },\n          template: `\n            <Suspense>\n              <LayoutLoader>\n                <template v-if=\"true\" #header>\n                  new header\n                </template>\n              </LayoutLoader>\n            </Suspense>\n          `,\n        }),\n      ),\n    ).toBe(`<div><!--[--> new header <!--]--></div>`)\n  })\n\n  // #11326\n  test('dynamic component slot', async () => {\n    expect(\n      await renderToString(\n        createApp({\n          components: {\n            ButtonComp: {\n              template: `<component is=\"button\"><slot/></component>`,\n            },\n            Wrap: {\n              template: `<div><slot/></div>`,\n            },\n          },\n          template: `<ButtonComp><Wrap><div v-if=\"false\">hello</div></Wrap></ButtonComp>`,\n        }),\n      ),\n    ).toBe(`<button><!--[--><div><!--[--><!--]--></div><!--]--></button>`)\n\n    expect(\n      await renderToString(\n        createApp({\n          components: {\n            ButtonComp: {\n              template: `<component is=\"button\"><slot/></component>`,\n            },\n            Wrap: {\n              template: `<div><slot/></div>`,\n            },\n          },\n          template: `<ButtonComp><Wrap><div v-if=\"true\">hello</div></Wrap></ButtonComp>`,\n        }),\n      ),\n    ).toBe(\n      `<button><!--[--><div><!--[--><div>hello</div><!--]--></div><!--]--></button>`,\n    )\n\n    expect(\n      await renderToString(\n        createApp({\n          components: {\n            ButtonComp: {\n              template: `<component is=\"button\"><slot/></component>`,\n            },\n          },\n          template: `<ButtonComp><template v-if=\"false\">hello</template></ButtonComp>`,\n        }),\n      ),\n    ).toBe(`<button><!--[--><!--]--></button>`)\n  })\n})\n"
  },
  {
    "path": "packages/server-renderer/__tests__/ssrSuspense.spec.ts",
    "content": "import { Suspense, createApp, h } from 'vue'\nimport { renderToString } from '../src/renderToString'\n\ndescribe('SSR Suspense', () => {\n  const ResolvingAsync = {\n    async setup() {\n      return () => h('div', 'async')\n    },\n  }\n\n  const RejectingAsync = {\n    setup() {\n      return new Promise((_, reject) => reject('foo'))\n    },\n  }\n\n  test('content', async () => {\n    const Comp = {\n      render() {\n        return h(Suspense, null, {\n          default: h(ResolvingAsync),\n          fallback: h('div', 'fallback'),\n        })\n      },\n    }\n\n    expect(await renderToString(createApp(Comp))).toBe(`<div>async</div>`)\n  })\n\n  test('reject', async () => {\n    const Comp = {\n      errorCaptured: vi.fn(() => false),\n      render() {\n        return h(Suspense, null, {\n          default: h(RejectingAsync),\n          fallback: h('div', 'fallback'),\n        })\n      },\n    }\n\n    expect(await renderToString(createApp(Comp))).toBe(`<!---->`)\n\n    expect(Comp.errorCaptured).toHaveBeenCalledTimes(1)\n    expect('missing template').toHaveBeenWarned()\n  })\n\n  test('2 components', async () => {\n    const Comp = {\n      render() {\n        return h(Suspense, null, {\n          default: h('div', [h(ResolvingAsync), h(ResolvingAsync)]),\n          fallback: h('div', 'fallback'),\n        })\n      },\n    }\n\n    expect(await renderToString(createApp(Comp))).toBe(\n      `<div><div>async</div><div>async</div></div>`,\n    )\n  })\n\n  test('resolving component + rejecting component', async () => {\n    const Comp = {\n      errorCaptured: vi.fn(() => false),\n      render() {\n        return h(Suspense, null, {\n          default: h('div', [h(ResolvingAsync), h(RejectingAsync)]),\n          fallback: h('div', 'fallback'),\n        })\n      },\n    }\n\n    expect(await renderToString(createApp(Comp))).toBe(\n      `<div><div>async</div><!----></div>`,\n    )\n\n    expect(Comp.errorCaptured).toHaveBeenCalledTimes(1)\n    expect('missing template or render function').toHaveBeenWarned()\n  })\n\n  test('failing suspense in passing suspense', async () => {\n    const Comp = {\n      errorCaptured: vi.fn(() => false),\n      render() {\n        return h(Suspense, null, {\n          default: h('div', [\n            h(ResolvingAsync),\n            h(Suspense, null, {\n              default: h('div', [h(RejectingAsync)]),\n              fallback: h('div', 'fallback 2'),\n            }),\n          ]),\n          fallback: h('div', 'fallback 1'),\n        })\n      },\n    }\n\n    expect(await renderToString(createApp(Comp))).toBe(\n      `<div><div>async</div><div><!----></div></div>`,\n    )\n\n    expect(Comp.errorCaptured).toHaveBeenCalledTimes(1)\n    expect('missing template').toHaveBeenWarned()\n  })\n\n  test('passing suspense in failing suspense', async () => {\n    const Comp = {\n      errorCaptured: vi.fn(() => false),\n      render() {\n        return h(Suspense, null, {\n          default: h('div', [\n            h(RejectingAsync),\n            h(Suspense, null, {\n              default: h('div', [h(ResolvingAsync)]),\n              fallback: h('div', 'fallback 2'),\n            }),\n          ]),\n          fallback: h('div', 'fallback 1'),\n        })\n      },\n    }\n\n    expect(await renderToString(createApp(Comp))).toBe(\n      `<div><!----><div><div>async</div></div></div>`,\n    )\n    expect(Comp.errorCaptured).toHaveBeenCalledTimes(1)\n    expect('missing template').toHaveBeenWarned()\n  })\n})\n"
  },
  {
    "path": "packages/server-renderer/__tests__/ssrTeleport.spec.ts",
    "content": "import { Teleport, createApp, h } from 'vue'\nimport { renderToString } from '../src/renderToString'\nimport { renderToSimpleStream } from '../src/renderToStream'\nimport type { SSRContext } from '../src/render'\nimport { ssrRenderTeleport } from '../src/helpers/ssrRenderTeleport'\n\ndescribe('ssrRenderTeleport', () => {\n  test('teleport rendering (compiled)', async () => {\n    const ctx: SSRContext = {}\n    const html = await renderToString(\n      createApp({\n        data() {\n          return { msg: 'hello' }\n        },\n        ssrRender(_ctx, _push, _parent) {\n          ssrRenderTeleport(\n            _push,\n            _push => {\n              _push(`<div>content</div>`)\n            },\n            '#target',\n            false,\n            _parent,\n          )\n        },\n      }),\n      ctx,\n    )\n    expect(html).toBe('<!--teleport start--><!--teleport end-->')\n    expect(ctx.teleports!['#target']).toBe(\n      `<!--teleport start anchor--><div>content</div><!--teleport anchor-->`,\n    )\n  })\n\n  test('teleport rendering (compiled + disabled)', async () => {\n    const ctx: SSRContext = {}\n    const html = await renderToString(\n      createApp({\n        data() {\n          return { msg: 'hello' }\n        },\n        ssrRender(_ctx, _push, _parent) {\n          ssrRenderTeleport(\n            _push,\n            _push => {\n              _push(`<div>content</div>`)\n            },\n            '#target',\n            true,\n            _parent,\n          )\n        },\n      }),\n      ctx,\n    )\n    expect(html).toBe(\n      '<!--teleport start--><div>content</div><!--teleport end-->',\n    )\n    expect(ctx.teleports!['#target']).toBe(\n      `<!--teleport start anchor--><!--teleport anchor-->`,\n    )\n  })\n\n  test('teleport rendering (vnode)', async () => {\n    const ctx: SSRContext = {}\n    const html = await renderToString(\n      h(\n        Teleport,\n        {\n          to: `#target`,\n        },\n        h('span', 'hello'),\n      ),\n      ctx,\n    )\n    expect(html).toBe('<!--teleport start--><!--teleport end-->')\n    expect(ctx.teleports!['#target']).toBe(\n      '<!--teleport start anchor--><span>hello</span><!--teleport anchor-->',\n    )\n  })\n\n  test('teleport rendering (vnode + disabled)', async () => {\n    const ctx: SSRContext = {}\n    const html = await renderToString(\n      h(\n        Teleport,\n        {\n          to: `#target`,\n          disabled: true,\n        },\n        h('span', 'hello'),\n      ),\n      ctx,\n    )\n    expect(html).toBe(\n      '<!--teleport start--><span>hello</span><!--teleport end-->',\n    )\n    expect(ctx.teleports!['#target']).toBe(\n      `<!--teleport start anchor--><!--teleport anchor-->`,\n    )\n  })\n\n  test('multiple teleports with same target', async () => {\n    const ctx: SSRContext = {}\n    const html = await renderToString(\n      h('div', [\n        h(\n          Teleport,\n          {\n            to: `#target`,\n          },\n          h('span', 'hello'),\n        ),\n        h(Teleport, { to: `#target` }, 'world'),\n      ]),\n      ctx,\n    )\n    expect(html).toBe(\n      '<div><!--teleport start--><!--teleport end--><!--teleport start--><!--teleport end--></div>',\n    )\n    expect(ctx.teleports!['#target']).toBe(\n      '<!--teleport start anchor--><span>hello</span><!--teleport anchor-->' +\n        '<!--teleport start anchor-->world<!--teleport anchor-->',\n    )\n  })\n\n  test('teleport inside async component', async () => {\n    const ctx: SSRContext = {}\n    const asyncComponent = {\n      template: '<teleport to=\"#target\"><div>content</div></teleport>',\n      async setup() {},\n    }\n    const html = await renderToString(\n      h({\n        template: '<async-component />',\n        components: { asyncComponent },\n      }),\n      ctx,\n    )\n    expect(html).toBe('<!--teleport start--><!--teleport end-->')\n    expect(ctx.teleports!['#target']).toBe(\n      `<!--teleport start anchor--><div>content</div><!--teleport anchor-->`,\n    )\n  })\n\n  test('teleport inside async component (stream)', async () => {\n    const ctx: SSRContext = {}\n    const asyncComponent = {\n      template: '<teleport to=\"#target\"><div>content</div></teleport>',\n      async setup() {},\n    }\n    let html = ''\n    let resolve: any\n    const p = new Promise(r => (resolve = r))\n    renderToSimpleStream(\n      h({\n        template: '<async-component />',\n        components: { asyncComponent },\n      }),\n      ctx,\n      {\n        push(chunk) {\n          if (chunk === null) {\n            resolve()\n          } else {\n            html += chunk\n          }\n        },\n        destroy(err) {\n          throw err\n        },\n      },\n    )\n    await p\n    expect(html).toBe('<!--teleport start--><!--teleport end-->')\n    expect(ctx.teleports!['#target']).toBe(\n      `<!--teleport start anchor--><div>content</div><!--teleport anchor-->`,\n    )\n  })\n})\n"
  },
  {
    "path": "packages/server-renderer/__tests__/ssrVModelHelpers.spec.ts",
    "content": "import {\n  ssrGetDynamicModelProps,\n  ssrRenderDynamicModel,\n  // ssrGetDynamicModelProps\n} from '../src/helpers/ssrVModelHelpers'\n\ndescribe('ssr: v-model helpers', () => {\n  test('ssrRenderDynamicModel', () => {\n    expect(ssrRenderDynamicModel(null, 'foo', null)).toBe(` value=\"foo\"`)\n    expect(ssrRenderDynamicModel('text', 'foo', null)).toBe(` value=\"foo\"`)\n    expect(ssrRenderDynamicModel('email', 'foo', null)).toBe(` value=\"foo\"`)\n\n    expect(ssrRenderDynamicModel('checkbox', true, null)).toBe(` checked`)\n    expect(ssrRenderDynamicModel('checkbox', false, null)).toBe(``)\n    expect(ssrRenderDynamicModel('checkbox', [1], '1')).toBe(` checked`)\n    expect(ssrRenderDynamicModel('checkbox', [1], 1)).toBe(` checked`)\n    expect(ssrRenderDynamicModel('checkbox', [1], 0)).toBe(``)\n\n    expect(ssrRenderDynamicModel('radio', 'foo', 'foo')).toBe(` checked`)\n    expect(ssrRenderDynamicModel('radio', 1, '1')).toBe(` checked`)\n    expect(ssrRenderDynamicModel('radio', 1, 0)).toBe(``)\n  })\n\n  test('ssrGetDynamicModelProps', () => {\n    expect(ssrGetDynamicModelProps({}, 'foo')).toMatchObject({ value: 'foo' })\n    expect(\n      ssrGetDynamicModelProps(\n        {\n          type: 'text',\n        },\n        'foo',\n      ),\n    ).toMatchObject({ value: 'foo' })\n    expect(\n      ssrGetDynamicModelProps(\n        {\n          type: 'email',\n        },\n        'foo',\n      ),\n    ).toMatchObject({ value: 'foo' })\n\n    expect(\n      ssrGetDynamicModelProps(\n        {\n          type: 'checkbox',\n        },\n        true,\n      ),\n    ).toMatchObject({ checked: true })\n    expect(\n      ssrGetDynamicModelProps(\n        {\n          type: 'checkbox',\n        },\n        false,\n      ),\n    ).toBe(null)\n    expect(\n      ssrGetDynamicModelProps(\n        {\n          type: 'checkbox',\n          value: '1',\n        },\n        [1],\n      ),\n    ).toMatchObject({ checked: true })\n    expect(\n      ssrGetDynamicModelProps(\n        {\n          type: 'checkbox',\n          value: 1,\n        },\n        [1],\n      ),\n    ).toMatchObject({ checked: true })\n    expect(\n      ssrGetDynamicModelProps(\n        {\n          type: 'checkbox',\n          value: 0,\n        },\n        [1],\n      ),\n    ).toBe(null)\n\n    expect(\n      ssrGetDynamicModelProps(\n        {\n          type: 'radio',\n          value: 'foo',\n        },\n        'foo',\n      ),\n    ).toMatchObject({ checked: true })\n    expect(\n      ssrGetDynamicModelProps(\n        {\n          type: 'radio',\n          value: '1',\n        },\n        1,\n      ),\n    ).toMatchObject({ checked: true })\n    expect(\n      ssrGetDynamicModelProps(\n        {\n          type: 'radio',\n          value: 0,\n        },\n        1,\n      ),\n    ).toBe(null)\n  })\n})\n"
  },
  {
    "path": "packages/server-renderer/__tests__/ssrWatch.spec.ts",
    "content": "import {\n  createSSRApp,\n  defineComponent,\n  h,\n  nextTick,\n  ref,\n  watch,\n  watchEffect,\n  withAsyncContext,\n} from 'vue'\nimport { type SSRContext, renderToString } from '../src'\n\ndescribe('ssr: watch', () => {\n  // #6013\n  test('should work w/ flush:sync', async () => {\n    const App = defineComponent(() => {\n      const count = ref(0)\n      let msg = ''\n      watch(\n        count,\n        () => {\n          msg = 'hello world'\n        },\n        { flush: 'sync' },\n      )\n      count.value = 1\n      expect(msg).toBe('hello world')\n      return () => h('div', null, msg)\n    })\n\n    const app = createSSRApp(App)\n    const ctx: SSRContext = {}\n    const html = await renderToString(app, ctx)\n\n    expect(ctx.__watcherHandles!.length).toBe(1)\n\n    expect(html).toMatch('hello world')\n  })\n\n  test('should work with flush: sync and immediate: true', async () => {\n    const text = ref('start')\n    let msg = 'unchanged'\n\n    const App = defineComponent(() => {\n      watch(\n        text,\n        () => {\n          msg = text.value\n        },\n        { flush: 'sync', immediate: true },\n      )\n      expect(msg).toBe('start')\n      text.value = 'changed'\n      expect(msg).toBe('changed')\n      text.value = 'changed again'\n      expect(msg).toBe('changed again')\n      return () => h('div', null, msg)\n    })\n\n    const app = createSSRApp(App)\n    const ctx: SSRContext = {}\n    const html = await renderToString(app, ctx)\n\n    expect(ctx.__watcherHandles!.length).toBe(1)\n    expect(html).toMatch('changed again')\n    await nextTick()\n    expect(msg).toBe('changed again')\n  })\n\n  test('should run once with immediate: true', async () => {\n    const text = ref('start')\n    let msg = 'unchanged'\n\n    const App = defineComponent(() => {\n      watch(\n        text,\n        () => {\n          msg = String(text.value)\n        },\n        { immediate: true },\n      )\n      text.value = 'changed'\n      expect(msg).toBe('start')\n      return () => h('div', null, msg)\n    })\n\n    const app = createSSRApp(App)\n    const ctx: SSRContext = {}\n    const html = await renderToString(app, ctx)\n\n    expect(ctx.__watcherHandles).toBeUndefined()\n    expect(html).toMatch('start')\n    await nextTick()\n    expect(msg).toBe('start')\n  })\n\n  test('should run once with immediate: true and flush: post', async () => {\n    const text = ref('start')\n    let msg = 'unchanged'\n\n    const App = defineComponent(() => {\n      watch(\n        text,\n        () => {\n          msg = String(text.value)\n        },\n        { immediate: true, flush: 'post' },\n      )\n      text.value = 'changed'\n      expect(msg).toBe('start')\n      return () => h('div', null, msg)\n    })\n\n    const app = createSSRApp(App)\n    const ctx: SSRContext = {}\n    const html = await renderToString(app, ctx)\n\n    expect(ctx.__watcherHandles).toBeUndefined()\n    expect(html).toMatch('start')\n    await nextTick()\n    expect(msg).toBe('start')\n  })\n\n  test('should not run non-immediate watchers registered after async context restore', async () => {\n    const text = ref('start')\n    let beforeAwaitTriggered = false\n    let afterAwaitTriggered = false\n\n    const App = defineComponent({\n      async setup() {\n        let __temp: any, __restore: any\n\n        watch(text, () => {\n          beforeAwaitTriggered = true\n        })\n        ;[__temp, __restore] = withAsyncContext(() => Promise.resolve())\n        __temp = await __temp\n        __restore()\n\n        watch(text, () => {\n          afterAwaitTriggered = true\n        })\n\n        text.value = 'changed'\n        expect(beforeAwaitTriggered).toBe(false)\n        expect(afterAwaitTriggered).toBe(false)\n\n        return () => h('div', null, text.value)\n      },\n    })\n\n    const app = createSSRApp(App)\n    const ctx: SSRContext = {}\n    const html = await renderToString(app, ctx)\n\n    expect(ctx.__watcherHandles).toBeUndefined()\n    expect(html).toMatch('changed')\n    await nextTick()\n    expect(beforeAwaitTriggered).toBe(false)\n    expect(afterAwaitTriggered).toBe(false)\n  })\n\n  test('should not run non-immediate watchers registered after async context restore on rejection', async () => {\n    const text = ref('start')\n    let beforeAwaitTriggered = false\n    let afterAwaitTriggered = false\n\n    const App = defineComponent({\n      async setup() {\n        let __temp: any, __restore: any\n\n        watch(text, () => {\n          beforeAwaitTriggered = true\n        })\n\n        try {\n          ;[__temp, __restore] = withAsyncContext(() =>\n            Promise.reject(new Error('failed')),\n          )\n          __temp = await __temp\n          __restore()\n        } catch {}\n\n        watch(text, () => {\n          afterAwaitTriggered = true\n        })\n\n        text.value = 'changed'\n        expect(beforeAwaitTriggered).toBe(false)\n        expect(afterAwaitTriggered).toBe(false)\n\n        return () => h('div', null, text.value)\n      },\n    })\n\n    const app = createSSRApp(App)\n    const ctx: SSRContext = {}\n    const html = await renderToString(app, ctx)\n\n    expect(ctx.__watcherHandles).toBeUndefined()\n    expect(html).toMatch('changed')\n    await nextTick()\n    expect(beforeAwaitTriggered).toBe(false)\n    expect(afterAwaitTriggered).toBe(false)\n  })\n})\n\ndescribe('ssr: watchEffect', () => {\n  test('should run with flush: sync', async () => {\n    const text = ref('start')\n    let msg = 'unchanged'\n\n    const App = defineComponent(() => {\n      watchEffect(\n        () => {\n          msg = text.value\n        },\n        { flush: 'sync' },\n      )\n      expect(msg).toBe('start')\n      text.value = 'changed'\n      expect(msg).toBe('changed')\n      text.value = 'changed again'\n      expect(msg).toBe('changed again')\n      return () => h('div', null, msg)\n    })\n\n    const app = createSSRApp(App)\n    const ctx: SSRContext = {}\n    const html = await renderToString(app, ctx)\n\n    expect(ctx.__watcherHandles!.length).toBe(1)\n    expect(html).toMatch('changed again')\n    await nextTick()\n    expect(msg).toBe('changed again')\n  })\n\n  test('should run once with default flush (pre)', async () => {\n    const text = ref('start')\n    let msg = 'unchanged'\n\n    const App = defineComponent(() => {\n      watchEffect(() => {\n        msg = text.value\n      })\n      text.value = 'changed'\n      expect(msg).toBe('start')\n      return () => h('div', null, msg)\n    })\n\n    const app = createSSRApp(App)\n    const ctx: SSRContext = {}\n    const html = await renderToString(app, ctx)\n\n    expect(ctx.__watcherHandles).toBeUndefined()\n    expect(html).toMatch('start')\n    await nextTick()\n    expect(msg).toBe('start')\n  })\n\n  test('should not run for flush: post', async () => {\n    const text = ref('start')\n    let msg = 'unchanged'\n\n    const App = defineComponent(() => {\n      watchEffect(\n        () => {\n          msg = text.value\n        },\n        { flush: 'post' },\n      )\n      text.value = 'changed'\n      expect(msg).toBe('unchanged')\n      return () => h('div', null, msg)\n    })\n\n    const app = createSSRApp(App)\n    const ctx: SSRContext = {}\n    const html = await renderToString(app, ctx)\n\n    expect(ctx.__watcherHandles).toBeUndefined()\n    expect(html).toMatch('unchanged')\n    await nextTick()\n    expect(msg).toBe('unchanged')\n  })\n})\n"
  },
  {
    "path": "packages/server-renderer/__tests__/unrollBuffer.bench.ts",
    "content": "import { bench, describe } from 'vitest'\n\nimport { type SSRBuffer, createBuffer } from '../src/render'\nimport { unrollBuffer as _unrollBuffer } from '../src/renderToString'\n\n// move to local const to avoid import access overhead\n// https://github.com/vitest-dev/vitest/issues/6903\nconst unrollBuffer = _unrollBuffer\n\nfunction createSyncBuffer(levels: number, itemsPerLevel: number): SSRBuffer {\n  const buffer = createBuffer()\n\n  function addItems(buf: ReturnType<typeof createBuffer>, level: number) {\n    for (let i = 1; i <= levels * itemsPerLevel; i++) {\n      buf.push(`sync${level}.${i}`)\n    }\n    if (level < levels) {\n      const subBuffer = createBuffer()\n      addItems(subBuffer, level + 1)\n      buf.push(subBuffer.getBuffer())\n    }\n  }\n\n  addItems(buffer, 1)\n  return buffer.getBuffer()\n}\n\nfunction createMixedBuffer(levels: number, itemsPerLevel: number): SSRBuffer {\n  const buffer = createBuffer()\n\n  function addItems(buf: ReturnType<typeof createBuffer>, level: number) {\n    for (let i = 1; i <= levels * itemsPerLevel; i++) {\n      if (i % 3 === 0) {\n        // @ts-expect-error testing...\n        buf.push(Promise.resolve(`async${level}.${i}`))\n      } else {\n        buf.push(`sync${level}.${i}`)\n      }\n    }\n    if (level < levels) {\n      const subBuffer = createBuffer()\n      addItems(subBuffer, level + 1)\n      buf.push(subBuffer.getBuffer())\n    }\n  }\n\n  addItems(buffer, 1)\n  return buffer.getBuffer()\n}\n\ndescribe('unrollBuffer', () => {\n  let syncBuffer = createBuffer().getBuffer()\n  let mixedBuffer = createBuffer().getBuffer()\n\n  bench(\n    'sync',\n    () => {\n      return unrollBuffer(syncBuffer) as any\n    },\n    {\n      setup() {\n        syncBuffer = createSyncBuffer(5, 3)\n      },\n    },\n  )\n\n  bench(\n    'mixed',\n    () => {\n      return unrollBuffer(mixedBuffer) as any\n    },\n    {\n      setup() {\n        mixedBuffer = createMixedBuffer(5, 3)\n      },\n    },\n  )\n})\n"
  },
  {
    "path": "packages/server-renderer/__tests__/webStream.spec.ts",
    "content": "import { createApp, defineAsyncComponent, h } from 'vue'\nimport { ReadableStream, TransformStream } from 'node:stream/web'\nimport { pipeToWebWritable, renderToWebStream } from '../src'\n\nbeforeEach(() => {\n  // @ts-expect-error\n  global.ReadableStream = ReadableStream\n})\n\nafterEach(() => {\n  // @ts-expect-error\n  delete global.ReadableStream\n})\n\ntest('renderToWebStream', async () => {\n  const Async = defineAsyncComponent(() =>\n    Promise.resolve({\n      render: () => h('div', 'async'),\n    }),\n  )\n  const App = {\n    render: () => [h('div', 'parent'), h(Async)],\n  }\n\n  const stream = renderToWebStream(createApp(App))\n\n  const reader = stream.getReader()\n  const decoder = new TextDecoder()\n\n  let res = ''\n  await reader.read().then(function read({ done, value }): any {\n    if (!done) {\n      res += decoder.decode(value)\n      return reader.read().then(read)\n    }\n  })\n\n  expect(res).toBe(`<!--[--><div>parent</div><div>async</div><!--]-->`)\n})\n\ntest('pipeToWebWritable', async () => {\n  const Async = defineAsyncComponent(() =>\n    Promise.resolve({\n      render: () => h('div', 'async'),\n    }),\n  )\n  const App = {\n    render: () => [h('div', 'parent'), h(Async)],\n  }\n\n  const { readable, writable } = new TransformStream()\n  pipeToWebWritable(createApp(App), {}, writable as any)\n\n  const reader = readable.getReader()\n  const decoder = new TextDecoder()\n\n  let res = ''\n  await reader.read().then(function read({ done, value }): any {\n    if (!done) {\n      res += decoder.decode(value)\n      return reader.read().then(read)\n    }\n  })\n\n  expect(res).toBe(`<!--[--><div>parent</div><div>async</div><!--]-->`)\n})\n"
  },
  {
    "path": "packages/server-renderer/index.js",
    "content": "'use strict'\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./dist/server-renderer.cjs.prod.js')\n} else {\n  module.exports = require('./dist/server-renderer.cjs.js')\n}\n"
  },
  {
    "path": "packages/server-renderer/package.json",
    "content": "{\n  \"name\": \"@vue/server-renderer\",\n  \"version\": \"3.5.30\",\n  \"description\": \"@vue/server-renderer\",\n  \"main\": \"index.js\",\n  \"module\": \"dist/server-renderer.esm-bundler.js\",\n  \"types\": \"dist/server-renderer.d.ts\",\n  \"files\": [\n    \"index.js\",\n    \"dist\"\n  ],\n  \"exports\": {\n    \".\": {\n      \"types\": \"./dist/server-renderer.d.ts\",\n      \"node\": {\n        \"production\": \"./dist/server-renderer.cjs.prod.js\",\n        \"development\": \"./dist/server-renderer.cjs.js\",\n        \"default\": \"./index.js\"\n      },\n      \"module\": \"./dist/server-renderer.esm-bundler.js\",\n      \"import\": \"./dist/server-renderer.esm-bundler.js\",\n      \"require\": \"./index.js\"\n    },\n    \"./*\": \"./*\"\n  },\n  \"buildOptions\": {\n    \"name\": \"VueServerRenderer\",\n    \"formats\": [\n      \"esm-bundler\",\n      \"esm-browser\",\n      \"cjs\"\n    ]\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/vuejs/core.git\",\n    \"directory\": \"packages/server-renderer\"\n  },\n  \"keywords\": [\n    \"vue\"\n  ],\n  \"author\": \"Evan You\",\n  \"license\": \"MIT\",\n  \"bugs\": {\n    \"url\": \"https://github.com/vuejs/core/issues\"\n  },\n  \"homepage\": \"https://github.com/vuejs/core/tree/main/packages/server-renderer#readme\",\n  \"peerDependencies\": {\n    \"vue\": \"workspace:*\"\n  },\n  \"dependencies\": {\n    \"@vue/shared\": \"workspace:*\",\n    \"@vue/compiler-ssr\": \"workspace:*\"\n  }\n}\n"
  },
  {
    "path": "packages/server-renderer/src/helpers/ssrCompile.ts",
    "content": "import {\n  type ComponentInternalInstance,\n  type ComponentOptions,\n  warn,\n} from 'vue'\nimport { compile } from '@vue/compiler-ssr'\nimport { NO, extend, generateCodeFrame, isFunction } from '@vue/shared'\nimport type { CompilerError, CompilerOptions } from '@vue/compiler-core'\nimport type { PushFn } from '../render'\n\nimport * as Vue from 'vue'\nimport * as helpers from '../internal'\n\ntype SSRRenderFunction = (\n  context: any,\n  push: PushFn,\n  parentInstance: ComponentInternalInstance,\n) => void\n\nconst compileCache: Record<string, SSRRenderFunction> = Object.create(null)\n\nexport function ssrCompile(\n  template: string,\n  instance: ComponentInternalInstance,\n): SSRRenderFunction {\n  // TODO: this branch should now work in ESM builds, enable it in a minor\n  if (!__CJS__) {\n    throw new Error(\n      `On-the-fly template compilation is not supported in the ESM build of ` +\n        `@vue/server-renderer. All templates must be pre-compiled into ` +\n        `render functions.`,\n    )\n  }\n\n  // TODO: This is copied from runtime-core/src/component.ts and should probably be refactored\n  const Component = instance.type as ComponentOptions\n  const { isCustomElement, compilerOptions } = instance.appContext.config\n  const { delimiters, compilerOptions: componentCompilerOptions } = Component\n\n  const finalCompilerOptions: CompilerOptions = extend(\n    extend(\n      {\n        isCustomElement,\n        delimiters,\n      },\n      compilerOptions,\n    ),\n    componentCompilerOptions,\n  )\n\n  finalCompilerOptions.isCustomElement =\n    finalCompilerOptions.isCustomElement || NO\n  finalCompilerOptions.isNativeTag = finalCompilerOptions.isNativeTag || NO\n\n  const cacheKey = JSON.stringify(\n    {\n      template,\n      compilerOptions: finalCompilerOptions,\n    },\n    (key, value) => {\n      return isFunction(value) ? value.toString() : value\n    },\n  )\n\n  const cached = compileCache[cacheKey]\n  if (cached) {\n    return cached\n  }\n\n  finalCompilerOptions.onError = (err: CompilerError) => {\n    if (__DEV__) {\n      const message = `[@vue/server-renderer] Template compilation error: ${err.message}`\n      const codeFrame =\n        err.loc &&\n        generateCodeFrame(\n          template as string,\n          err.loc.start.offset,\n          err.loc.end.offset,\n        )\n      warn(codeFrame ? `${message}\\n${codeFrame}` : message)\n    } else {\n      throw err\n    }\n  }\n\n  const { code } = compile(template, finalCompilerOptions)\n  const requireMap = {\n    vue: Vue,\n    'vue/server-renderer': helpers,\n  }\n  const fakeRequire = (id: 'vue' | 'vue/server-renderer') => requireMap[id]\n  return (compileCache[cacheKey] = Function('require', code)(fakeRequire))\n}\n"
  },
  {
    "path": "packages/server-renderer/src/helpers/ssrGetDirectiveProps.ts",
    "content": "import { type ComponentPublicInstance, type Directive, ssrUtils } from 'vue'\n\nexport function ssrGetDirectiveProps(\n  instance: ComponentPublicInstance,\n  dir: Directive,\n  value?: any,\n  arg?: string,\n  modifiers: Record<string, boolean> = {},\n): Record<string, any> {\n  if (typeof dir !== 'function' && dir.getSSRProps) {\n    return (\n      dir.getSSRProps(\n        {\n          dir,\n          instance: ssrUtils.getComponentPublicInstance(instance.$),\n          value,\n          oldValue: undefined,\n          arg,\n          modifiers,\n        },\n        null as any,\n      ) || {}\n    )\n  }\n  return {}\n}\n"
  },
  {
    "path": "packages/server-renderer/src/helpers/ssrInterpolate.ts",
    "content": "import { escapeHtml, toDisplayString } from '@vue/shared'\n\nexport function ssrInterpolate(value: unknown): string {\n  return escapeHtml(toDisplayString(value))\n}\n"
  },
  {
    "path": "packages/server-renderer/src/helpers/ssrRenderAttrs.ts",
    "content": "import {\n  escapeHtml,\n  isArray,\n  isObject,\n  isRenderableAttrValue,\n  isSVGTag,\n  stringifyStyle,\n} from '@vue/shared'\nimport {\n  includeBooleanAttr,\n  isBooleanAttr,\n  isOn,\n  isSSRSafeAttrName,\n  isString,\n  makeMap,\n  normalizeClass,\n  normalizeCssVarValue,\n  normalizeStyle,\n  propsToAttrMap,\n} from '@vue/shared'\n\n// leading comma for empty string \"\"\nconst shouldIgnoreProp = /*@__PURE__*/ makeMap(\n  `,key,ref,innerHTML,textContent,ref_key,ref_for`,\n)\n\nexport function ssrRenderAttrs(\n  props: Record<string, unknown>,\n  tag?: string,\n): string {\n  let ret = ''\n  for (let key in props) {\n    if (\n      shouldIgnoreProp(key) ||\n      isOn(key) ||\n      (tag === 'textarea' && key === 'value') ||\n      // force as property (not rendered in SSR)\n      key.startsWith('.')\n    ) {\n      continue\n    }\n    const value = props[key]\n    // force as attribute\n    if (key.startsWith('^')) key = key.slice(1)\n    if (key === 'class') {\n      ret += ` class=\"${ssrRenderClass(value)}\"`\n    } else if (key === 'style') {\n      ret += ` style=\"${ssrRenderStyle(value)}\"`\n    } else if (key === 'className') {\n      // className should not go through ssrRenderClass which normalizes non-string\n      // values into strings. it should coerce directly into strings\n      if (value != null) {\n        ret += ` class=\"${escapeHtml(String(value))}\"`\n      }\n    } else {\n      ret += ssrRenderDynamicAttr(key, value, tag)\n    }\n  }\n  return ret\n}\n\n// render an attr with dynamic (unknown) key.\nexport function ssrRenderDynamicAttr(\n  key: string,\n  value: unknown,\n  tag?: string,\n): string {\n  if (!isRenderableAttrValue(value)) {\n    return ``\n  }\n  const attrKey =\n    tag && (tag.indexOf('-') > 0 || isSVGTag(tag))\n      ? key // preserve raw name on custom elements and svg\n      : propsToAttrMap[key] || key.toLowerCase()\n  if (isBooleanAttr(attrKey)) {\n    return includeBooleanAttr(value) ? ` ${attrKey}` : ``\n  } else if (isSSRSafeAttrName(attrKey)) {\n    return value === '' ? ` ${attrKey}` : ` ${attrKey}=\"${escapeHtml(value)}\"`\n  } else {\n    console.warn(\n      `[@vue/server-renderer] Skipped rendering unsafe attribute name: ${attrKey}`,\n    )\n    return ``\n  }\n}\n\n// Render a v-bind attr with static key. The key is pre-processed at compile\n// time and we only need to check and escape value.\nexport function ssrRenderAttr(key: string, value: unknown): string {\n  if (!isRenderableAttrValue(value)) {\n    return ``\n  }\n  return ` ${key}=\"${escapeHtml(value)}\"`\n}\n\nexport function ssrRenderClass(raw: unknown): string {\n  return escapeHtml(normalizeClass(raw))\n}\n\nexport function ssrRenderStyle(raw: unknown): string {\n  if (!raw) {\n    return ''\n  }\n  if (isString(raw)) {\n    return escapeHtml(raw)\n  }\n  const styles = normalizeStyle(ssrResetCssVars(raw))\n  return escapeHtml(stringifyStyle(styles))\n}\n\nfunction ssrResetCssVars(raw: unknown) {\n  if (!isArray(raw) && isObject(raw)) {\n    const res: Record<string, unknown> = {}\n    for (const key in raw) {\n      // `:` prefixed keys are coming from `ssrCssVars`\n      if (key.startsWith(':--')) {\n        res[key.slice(1)] = normalizeCssVarValue(raw[key])\n      } else {\n        res[key] = raw[key]\n      }\n    }\n    return res\n  }\n  return raw\n}\n"
  },
  {
    "path": "packages/server-renderer/src/helpers/ssrRenderComponent.ts",
    "content": "import {\n  type Component,\n  type ComponentInternalInstance,\n  type Slots,\n  createVNode,\n} from 'vue'\nimport { type Props, type SSRBuffer, renderComponentVNode } from '../render'\nimport type { SSRSlots } from './ssrRenderSlot'\n\nexport function ssrRenderComponent(\n  comp: Component,\n  props: Props | null = null,\n  children: Slots | SSRSlots | null = null,\n  parentComponent: ComponentInternalInstance | null = null,\n  slotScopeId?: string,\n): SSRBuffer | Promise<SSRBuffer> {\n  return renderComponentVNode(\n    createVNode(comp, props, children),\n    parentComponent,\n    slotScopeId,\n  )\n}\n"
  },
  {
    "path": "packages/server-renderer/src/helpers/ssrRenderList.ts",
    "content": "import { isArray, isObject, isString } from '@vue/shared'\nimport { warn } from '@vue/runtime-core'\n\nexport function ssrRenderList(\n  source: unknown,\n  renderItem: (value: unknown, key: string | number, index?: number) => void,\n): void {\n  if (isArray(source) || isString(source)) {\n    for (let i = 0, l = source.length; i < l; i++) {\n      renderItem(source[i], i)\n    }\n  } else if (typeof source === 'number') {\n    if (__DEV__ && (!Number.isInteger(source) || source < 0)) {\n      warn(\n        `The v-for range expects a positive integer value but got ${source}.`,\n      )\n      return\n    }\n    for (let i = 0; i < source; i++) {\n      renderItem(i + 1, i)\n    }\n  } else if (isObject(source)) {\n    if (source[Symbol.iterator as any]) {\n      const arr = Array.from(source as Iterable<any>)\n      for (let i = 0, l = arr.length; i < l; i++) {\n        renderItem(arr[i], i)\n      }\n    } else {\n      const keys = Object.keys(source)\n      for (let i = 0, l = keys.length; i < l; i++) {\n        const key = keys[i]\n        renderItem(source[key], key, i)\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "packages/server-renderer/src/helpers/ssrRenderSlot.ts",
    "content": "import { type ComponentInternalInstance, type Slots, ssrUtils } from 'vue'\nimport {\n  type Props,\n  type PushFn,\n  type SSRBufferItem,\n  renderVNodeChildren,\n} from '../render'\nimport { isArray } from '@vue/shared'\n\nconst { ensureValidVNode } = ssrUtils\n\nexport type SSRSlots = Record<string, SSRSlot>\nexport type SSRSlot = (\n  props: Props,\n  push: PushFn,\n  parentComponent: ComponentInternalInstance | null,\n  scopeId: string | null,\n) => void\n\nexport function ssrRenderSlot(\n  slots: Slots | SSRSlots,\n  slotName: string,\n  slotProps: Props,\n  fallbackRenderFn: (() => void) | null,\n  push: PushFn,\n  parentComponent: ComponentInternalInstance,\n  slotScopeId?: string,\n): void {\n  // template-compiled slots are always rendered as fragments\n  push(`<!--[-->`)\n  ssrRenderSlotInner(\n    slots,\n    slotName,\n    slotProps,\n    fallbackRenderFn,\n    push,\n    parentComponent,\n    slotScopeId,\n  )\n  push(`<!--]-->`)\n}\n\nexport function ssrRenderSlotInner(\n  slots: Slots | SSRSlots,\n  slotName: string,\n  slotProps: Props,\n  fallbackRenderFn: (() => void) | null,\n  push: PushFn,\n  parentComponent: ComponentInternalInstance,\n  slotScopeId?: string,\n  transition?: boolean,\n): void {\n  const slotFn = slots[slotName]\n  if (slotFn) {\n    const slotBuffer: SSRBufferItem[] = []\n    const bufferedPush = (item: SSRBufferItem) => {\n      slotBuffer.push(item)\n    }\n    const ret = slotFn(\n      slotProps,\n      bufferedPush,\n      parentComponent,\n      slotScopeId ? ' ' + slotScopeId : '',\n    )\n    if (isArray(ret)) {\n      const validSlotContent = ensureValidVNode(ret)\n      if (validSlotContent) {\n        // normal slot\n        renderVNodeChildren(\n          push,\n          validSlotContent,\n          parentComponent,\n          slotScopeId,\n        )\n      } else if (fallbackRenderFn) {\n        fallbackRenderFn()\n      } else if (transition) {\n        push(`<!---->`)\n      }\n    } else {\n      // ssr slot.\n      // check if the slot renders all comments, in which case use the fallback\n      let isEmptySlot = true\n      if (transition) {\n        isEmptySlot = false\n      } else {\n        for (let i = 0; i < slotBuffer.length; i++) {\n          if (!isComment(slotBuffer[i])) {\n            isEmptySlot = false\n            break\n          }\n        }\n      }\n      if (isEmptySlot) {\n        if (fallbackRenderFn) {\n          fallbackRenderFn()\n        }\n      } else {\n        // #9933\n        // Although we handle Transition/TransitionGroup in the transform stage\n        // without rendering it as a fragment, the content passed into the slot\n        // may still be a fragment.\n        // Therefore, here we need to avoid rendering it as a fragment again.\n        let start = 0\n        let end = slotBuffer.length\n        if (\n          transition &&\n          slotBuffer[0] === '<!--[-->' &&\n          slotBuffer[end - 1] === '<!--]-->'\n        ) {\n          start++\n          end--\n        }\n\n        if (start < end) {\n          for (let i = start; i < end; i++) {\n            push(slotBuffer[i])\n          }\n        } else if (transition) {\n          push(`<!---->`)\n        }\n      }\n    }\n  } else if (fallbackRenderFn) {\n    fallbackRenderFn()\n  } else if (transition) {\n    push(`<!---->`)\n  }\n}\n\nconst commentTestRE = /^<!--[\\s\\S]*-->$/\nconst commentRE = /<!--[^]*?-->/gm\nfunction isComment(item: SSRBufferItem) {\n  if (typeof item !== 'string' || !commentTestRE.test(item)) return false\n  // if item is '<!---->' or '<!--[-->' or '<!--]-->', return true directly\n  if (item.length <= 8) return true\n  return !item.replace(commentRE, '').trim()\n}\n"
  },
  {
    "path": "packages/server-renderer/src/helpers/ssrRenderSuspense.ts",
    "content": "import type { PushFn } from '../render'\n\nexport async function ssrRenderSuspense(\n  push: PushFn,\n  { default: renderContent }: Record<string, (() => void) | undefined>,\n): Promise<void> {\n  if (renderContent) {\n    renderContent()\n  } else {\n    push(`<!---->`)\n  }\n}\n"
  },
  {
    "path": "packages/server-renderer/src/helpers/ssrRenderTeleport.ts",
    "content": "import { type ComponentInternalInstance, ssrContextKey } from 'vue'\nimport {\n  type PushFn,\n  type SSRBufferItem,\n  type SSRContext,\n  createBuffer,\n} from '../render'\n\nexport function ssrRenderTeleport(\n  parentPush: PushFn,\n  contentRenderFn: (push: PushFn) => void,\n  target: string,\n  disabled: boolean,\n  parentComponent: ComponentInternalInstance,\n): void {\n  parentPush('<!--teleport start-->')\n\n  const context = parentComponent.appContext.provides[\n    ssrContextKey as any\n  ] as SSRContext\n  const teleportBuffers =\n    context.__teleportBuffers || (context.__teleportBuffers = {})\n  const targetBuffer = teleportBuffers[target] || (teleportBuffers[target] = [])\n  // record current index of the target buffer to handle nested teleports\n  // since the parent needs to be rendered before the child\n  const bufferIndex = targetBuffer.length\n\n  let teleportContent: SSRBufferItem\n\n  if (disabled) {\n    contentRenderFn(parentPush)\n    teleportContent = `<!--teleport start anchor--><!--teleport anchor-->`\n  } else {\n    const { getBuffer, push } = createBuffer()\n    push(`<!--teleport start anchor-->`)\n    contentRenderFn(push)\n    push(`<!--teleport anchor-->`)\n    teleportContent = getBuffer()\n  }\n\n  targetBuffer.splice(bufferIndex, 0, teleportContent)\n  parentPush('<!--teleport end-->')\n}\n"
  },
  {
    "path": "packages/server-renderer/src/helpers/ssrVModelHelpers.ts",
    "content": "import { isArray, looseEqual, looseIndexOf } from '@vue/shared'\nimport { ssrRenderAttr } from './ssrRenderAttrs'\n\nexport const ssrLooseEqual = looseEqual as (a: unknown, b: unknown) => boolean\n\nexport function ssrLooseContain(arr: unknown[], value: unknown): boolean {\n  return looseIndexOf(arr, value) > -1\n}\n\n// for <input :type=\"type\" v-model=\"model\" value=\"value\">\nexport function ssrRenderDynamicModel(\n  type: unknown,\n  model: unknown,\n  value: unknown,\n): string {\n  switch (type) {\n    case 'radio':\n      return looseEqual(model, value) ? ' checked' : ''\n    case 'checkbox':\n      return (isArray(model) ? ssrLooseContain(model, value) : model)\n        ? ' checked'\n        : ''\n    default:\n      // text types\n      return ssrRenderAttr('value', model)\n  }\n}\n\n// for <input v-bind=\"obj\" v-model=\"model\">\nexport function ssrGetDynamicModelProps(\n  existingProps: any = {},\n  model: unknown,\n): { checked: true } | { value: any } | null {\n  const { type, value } = existingProps\n  switch (type) {\n    case 'radio':\n      return looseEqual(model, value) ? { checked: true } : null\n    case 'checkbox':\n      return (isArray(model) ? ssrLooseContain(model, value) : model)\n        ? { checked: true }\n        : null\n    default:\n      // text types\n      return { value: model }\n  }\n}\n"
  },
  {
    "path": "packages/server-renderer/src/index.ts",
    "content": "import { initDirectivesForSSR } from 'vue'\ninitDirectivesForSSR()\n\n// public\nexport type { SSRContext } from './render'\nexport { renderToString } from './renderToString'\nexport {\n  renderToSimpleStream,\n  renderToNodeStream,\n  pipeToNodeWritable,\n  renderToWebStream,\n  pipeToWebWritable,\n  type SimpleReadable,\n  // deprecated\n  renderToStream,\n} from './renderToStream'\n\n// internal runtime helpers\nexport * from './internal'\n"
  },
  {
    "path": "packages/server-renderer/src/internal.ts",
    "content": "// internal runtime helpers\nexport { renderVNode as ssrRenderVNode } from './render'\nexport { ssrRenderComponent } from './helpers/ssrRenderComponent'\nexport { ssrRenderSlot, ssrRenderSlotInner } from './helpers/ssrRenderSlot'\nexport { ssrRenderTeleport } from './helpers/ssrRenderTeleport'\nexport {\n  ssrRenderClass,\n  ssrRenderStyle,\n  ssrRenderAttrs,\n  ssrRenderAttr,\n  ssrRenderDynamicAttr,\n} from './helpers/ssrRenderAttrs'\nexport { ssrInterpolate } from './helpers/ssrInterpolate'\nexport { ssrRenderList } from './helpers/ssrRenderList'\nexport { ssrRenderSuspense } from './helpers/ssrRenderSuspense'\nexport { ssrGetDirectiveProps } from './helpers/ssrGetDirectiveProps'\nexport { includeBooleanAttr as ssrIncludeBooleanAttr } from '@vue/shared'\n\n// v-model helpers\nexport {\n  ssrLooseEqual,\n  ssrLooseContain,\n  ssrRenderDynamicModel,\n  ssrGetDynamicModelProps,\n} from './helpers/ssrVModelHelpers'\n"
  },
  {
    "path": "packages/server-renderer/src/render.ts",
    "content": "import {\n  Comment,\n  type Component,\n  type ComponentInternalInstance,\n  type DirectiveBinding,\n  Fragment,\n  type FunctionalComponent,\n  Static,\n  Text,\n  type VNode,\n  type VNodeArrayChildren,\n  type VNodeProps,\n  mergeProps,\n  ssrUtils,\n  warn,\n} from 'vue'\nimport {\n  NOOP,\n  ShapeFlags,\n  escapeHtml,\n  escapeHtmlComment,\n  isArray,\n  isFunction,\n  isPromise,\n  isString,\n  isVoidTag,\n} from '@vue/shared'\nimport { ssrRenderAttrs } from './helpers/ssrRenderAttrs'\nimport { ssrCompile } from './helpers/ssrCompile'\nimport { ssrRenderTeleport } from './helpers/ssrRenderTeleport'\n\nconst {\n  createComponentInstance,\n  setCurrentRenderingInstance,\n  setupComponent,\n  renderComponentRoot,\n  normalizeVNode,\n  pushWarningContext,\n  popWarningContext,\n} = ssrUtils\n\nexport type SSRBuffer = SSRBufferItem[] & { hasAsync?: boolean }\nexport type SSRBufferItem = string | SSRBuffer | Promise<SSRBuffer>\nexport type PushFn = (item: SSRBufferItem) => void\nexport type Props = Record<string, unknown>\n\nexport type SSRContext = {\n  [key: string]: any\n  teleports?: Record<string, string>\n  /**\n   * @internal\n   */\n  __teleportBuffers?: Record<string, SSRBuffer>\n  /**\n   * @internal\n   */\n  __watcherHandles?: (() => void)[]\n}\n\n// Each component has a buffer array.\n// A buffer array can contain one of the following:\n// - plain string\n// - A resolved buffer (recursive arrays of strings that can be unrolled\n//   synchronously)\n// - An async buffer (a Promise that resolves to a resolved buffer)\nexport function createBuffer() {\n  let appendable = false\n  const buffer: SSRBuffer = []\n  return {\n    getBuffer(): SSRBuffer {\n      // Return static buffer and await on items during unroll stage\n      return buffer\n    },\n    push(item: SSRBufferItem): void {\n      const isStringItem = isString(item)\n      if (appendable && isStringItem) {\n        buffer[buffer.length - 1] += item as string\n        return\n      }\n      buffer.push(item)\n      appendable = isStringItem\n      if (isPromise(item) || (isArray(item) && item.hasAsync)) {\n        // promise, or child buffer with async, mark as async.\n        // this allows skipping unnecessary await ticks during unroll stage\n        buffer.hasAsync = true\n      }\n    },\n  }\n}\n\nexport function renderComponentVNode(\n  vnode: VNode,\n  parentComponent: ComponentInternalInstance | null = null,\n  slotScopeId?: string,\n): SSRBuffer | Promise<SSRBuffer> {\n  const instance = (vnode.component = createComponentInstance(\n    vnode,\n    parentComponent,\n    null,\n  ))\n  if (__DEV__) pushWarningContext(vnode)\n  const res = setupComponent(instance, true /* isSSR */)\n  if (__DEV__) popWarningContext()\n  const hasAsyncSetup = isPromise(res)\n  let prefetches = instance.sp /* LifecycleHooks.SERVER_PREFETCH */\n  if (hasAsyncSetup || prefetches) {\n    const p: Promise<unknown> = Promise.resolve(res as Promise<void>)\n      .then(() => {\n        // instance.sp may be null until an async setup resolves, so evaluate it here\n        if (hasAsyncSetup) prefetches = instance.sp\n        if (prefetches) {\n          return Promise.all(\n            prefetches.map(prefetch => prefetch.call(instance.proxy)),\n          )\n        }\n      })\n      // Note: error display is already done by the wrapped lifecycle hook function.\n      .catch(NOOP)\n    return p.then(() => renderComponentSubTree(instance, slotScopeId))\n  } else {\n    return renderComponentSubTree(instance, slotScopeId)\n  }\n}\n\nfunction renderComponentSubTree(\n  instance: ComponentInternalInstance,\n  slotScopeId?: string,\n): SSRBuffer | Promise<SSRBuffer> {\n  if (__DEV__) pushWarningContext(instance.vnode)\n  const comp = instance.type as Component\n  const { getBuffer, push } = createBuffer()\n  if (isFunction(comp)) {\n    let root = renderComponentRoot(instance)\n    // #5817 scope ID attrs not falling through if functional component doesn't\n    // have props\n    if (!(comp as FunctionalComponent).props) {\n      for (const key in instance.attrs) {\n        if (key.startsWith(`data-v-`)) {\n          ;(root.props || (root.props = {}))[key] = ``\n        }\n      }\n    }\n    renderVNode(push, (instance.subTree = root), instance, slotScopeId)\n  } else {\n    if (\n      (!instance.render || instance.render === NOOP) &&\n      !instance.ssrRender &&\n      !comp.ssrRender &&\n      isString(comp.template)\n    ) {\n      comp.ssrRender = ssrCompile(comp.template, instance)\n    }\n\n    const ssrRender = instance.ssrRender || comp.ssrRender\n    if (ssrRender) {\n      // optimized\n      // resolve fallthrough attrs\n      let attrs = instance.inheritAttrs !== false ? instance.attrs : undefined\n      let hasCloned = false\n\n      let cur = instance\n      while (true) {\n        const scopeId = cur.vnode.scopeId\n        if (scopeId) {\n          if (!hasCloned) {\n            attrs = { ...attrs }\n            hasCloned = true\n          }\n          attrs![scopeId] = ''\n        }\n        const parent = cur.parent\n        if (parent && parent.subTree && parent.subTree === cur.vnode) {\n          // parent is a non-SSR compiled component and is rendering this\n          // component as root. inherit its scopeId if present.\n          cur = parent\n        } else {\n          break\n        }\n      }\n\n      if (slotScopeId) {\n        if (!hasCloned) attrs = { ...attrs }\n        const slotScopeIdList = slotScopeId.trim().split(' ')\n        for (let i = 0; i < slotScopeIdList.length; i++) {\n          attrs![slotScopeIdList[i]] = ''\n        }\n      }\n\n      // set current rendering instance for asset resolution\n      const prev = setCurrentRenderingInstance(instance)\n      try {\n        ssrRender(\n          instance.proxy,\n          push,\n          instance,\n          attrs,\n          // compiler-optimized bindings\n          instance.props,\n          instance.setupState,\n          instance.data,\n          instance.ctx,\n        )\n      } finally {\n        setCurrentRenderingInstance(prev)\n      }\n    } else if (instance.render && instance.render !== NOOP) {\n      renderVNode(\n        push,\n        (instance.subTree = renderComponentRoot(instance)),\n        instance,\n        slotScopeId,\n      )\n    } else {\n      const componentName = comp.name || comp.__file || `<Anonymous>`\n      warn(`Component ${componentName} is missing template or render function.`)\n      push(`<!---->`)\n    }\n  }\n  if (__DEV__) popWarningContext()\n  return getBuffer()\n}\n\nexport function renderVNode(\n  push: PushFn,\n  vnode: VNode,\n  parentComponent: ComponentInternalInstance,\n  slotScopeId?: string,\n): void {\n  const { type, shapeFlag, children, dirs, props } = vnode\n  if (dirs) {\n    vnode.props = applySSRDirectives(vnode, props, dirs)\n  }\n\n  switch (type) {\n    case Text:\n      push(escapeHtml(children as string))\n      break\n    case Comment:\n      push(\n        children\n          ? `<!--${escapeHtmlComment(children as string)}-->`\n          : `<!---->`,\n      )\n      break\n    case Static:\n      push(children as string)\n      break\n    case Fragment:\n      if (vnode.slotScopeIds) {\n        slotScopeId =\n          (slotScopeId ? slotScopeId + ' ' : '') + vnode.slotScopeIds.join(' ')\n      }\n      push(`<!--[-->`) // open\n      renderVNodeChildren(\n        push,\n        children as VNodeArrayChildren,\n        parentComponent,\n        slotScopeId,\n      )\n      push(`<!--]-->`) // close\n      break\n    default:\n      if (shapeFlag & ShapeFlags.ELEMENT) {\n        renderElementVNode(push, vnode, parentComponent, slotScopeId)\n      } else if (shapeFlag & ShapeFlags.COMPONENT) {\n        push(renderComponentVNode(vnode, parentComponent, slotScopeId))\n      } else if (shapeFlag & ShapeFlags.TELEPORT) {\n        renderTeleportVNode(push, vnode, parentComponent, slotScopeId)\n      } else if (shapeFlag & ShapeFlags.SUSPENSE) {\n        renderVNode(push, vnode.ssContent!, parentComponent, slotScopeId)\n      } else {\n        warn(\n          '[@vue/server-renderer] Invalid VNode type:',\n          type,\n          `(${typeof type})`,\n        )\n      }\n  }\n}\n\nexport function renderVNodeChildren(\n  push: PushFn,\n  children: VNodeArrayChildren,\n  parentComponent: ComponentInternalInstance,\n  slotScopeId?: string,\n): void {\n  for (let i = 0; i < children.length; i++) {\n    renderVNode(push, normalizeVNode(children[i]), parentComponent, slotScopeId)\n  }\n}\n\nfunction renderElementVNode(\n  push: PushFn,\n  vnode: VNode,\n  parentComponent: ComponentInternalInstance,\n  slotScopeId?: string,\n) {\n  const tag = vnode.type as string\n  let { props, children, shapeFlag, scopeId } = vnode\n  let openTag = `<${tag}`\n\n  if (props) {\n    openTag += ssrRenderAttrs(props, tag)\n  }\n\n  if (scopeId) {\n    openTag += ` ${scopeId}`\n  }\n  // inherit parent chain scope id if this is the root node\n  let curParent: ComponentInternalInstance | null = parentComponent\n  let curVnode = vnode\n  while (curParent && curVnode === curParent.subTree) {\n    curVnode = curParent.vnode\n    if (curVnode.scopeId) {\n      openTag += ` ${curVnode.scopeId}`\n    }\n    curParent = curParent.parent\n  }\n  if (slotScopeId) {\n    openTag += ` ${slotScopeId}`\n  }\n\n  push(openTag + `>`)\n  if (!isVoidTag(tag)) {\n    let hasChildrenOverride = false\n    if (props) {\n      if (props.innerHTML) {\n        hasChildrenOverride = true\n        push(props.innerHTML)\n      } else if (props.textContent) {\n        hasChildrenOverride = true\n        push(escapeHtml(props.textContent))\n      } else if (tag === 'textarea' && props.value) {\n        hasChildrenOverride = true\n        push(escapeHtml(props.value))\n      }\n    }\n    if (!hasChildrenOverride) {\n      if (shapeFlag & ShapeFlags.TEXT_CHILDREN) {\n        push(escapeHtml(children as string))\n      } else if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) {\n        renderVNodeChildren(\n          push,\n          children as VNodeArrayChildren,\n          parentComponent,\n          slotScopeId,\n        )\n      }\n    }\n    push(`</${tag}>`)\n  }\n}\n\nfunction applySSRDirectives(\n  vnode: VNode,\n  rawProps: VNodeProps | null,\n  dirs: DirectiveBinding[],\n): VNodeProps {\n  const toMerge: VNodeProps[] = []\n  for (let i = 0; i < dirs.length; i++) {\n    const binding = dirs[i]\n    const {\n      dir: { getSSRProps },\n    } = binding\n    if (getSSRProps) {\n      const props = getSSRProps(binding, vnode)\n      if (props) toMerge.push(props)\n    }\n  }\n  return mergeProps(rawProps || {}, ...toMerge)\n}\n\nfunction renderTeleportVNode(\n  push: PushFn,\n  vnode: VNode,\n  parentComponent: ComponentInternalInstance,\n  slotScopeId?: string,\n) {\n  const target = vnode.props && vnode.props.to\n  const disabled = vnode.props && vnode.props.disabled\n  if (!target) {\n    if (!disabled) {\n      warn(`[@vue/server-renderer] Teleport is missing target prop.`)\n    }\n    return []\n  }\n  if (!isString(target)) {\n    warn(\n      `[@vue/server-renderer] Teleport target must be a query selector string.`,\n    )\n    return []\n  }\n  ssrRenderTeleport(\n    push,\n    push => {\n      renderVNodeChildren(\n        push,\n        vnode.children as VNodeArrayChildren,\n        parentComponent,\n        slotScopeId,\n      )\n    },\n    target,\n    disabled || disabled === '',\n    parentComponent,\n  )\n}\n"
  },
  {
    "path": "packages/server-renderer/src/renderToStream.ts",
    "content": "import {\n  type App,\n  type VNode,\n  createApp,\n  createVNode,\n  ssrContextKey,\n  ssrUtils,\n} from 'vue'\nimport { isPromise, isString } from '@vue/shared'\nimport { type SSRBuffer, type SSRContext, renderComponentVNode } from './render'\nimport type { Readable, Writable } from 'node:stream'\nimport { resolveTeleports } from './renderToString'\n\nconst { isVNode } = ssrUtils\n\nexport interface SimpleReadable {\n  push(chunk: string | null): void\n  destroy(err: any): void\n}\n\nasync function unrollBuffer(\n  buffer: SSRBuffer,\n  stream: SimpleReadable,\n): Promise<void> {\n  if (buffer.hasAsync) {\n    for (let i = 0; i < buffer.length; i++) {\n      let item = buffer[i]\n      if (isPromise(item)) {\n        item = await item\n      }\n      if (isString(item)) {\n        stream.push(item)\n      } else {\n        await unrollBuffer(item, stream)\n      }\n    }\n  } else {\n    // sync buffer can be more efficiently unrolled without unnecessary await\n    // ticks\n    unrollBufferSync(buffer, stream)\n  }\n}\n\nfunction unrollBufferSync(buffer: SSRBuffer, stream: SimpleReadable) {\n  for (let i = 0; i < buffer.length; i++) {\n    let item = buffer[i]\n    if (isString(item)) {\n      stream.push(item)\n    } else {\n      // since this is a sync buffer, child buffers are never promises\n      unrollBufferSync(item as SSRBuffer, stream)\n    }\n  }\n}\n\nexport function renderToSimpleStream<T extends SimpleReadable>(\n  input: App | VNode,\n  context: SSRContext,\n  stream: T,\n): T {\n  if (isVNode(input)) {\n    // raw vnode, wrap with app (for context)\n    return renderToSimpleStream(\n      createApp({ render: () => input }),\n      context,\n      stream,\n    )\n  }\n\n  // rendering an app\n  const vnode = createVNode(input._component, input._props)\n  vnode.appContext = input._context\n  // provide the ssr context to the tree\n  input.provide(ssrContextKey, context)\n\n  Promise.resolve(renderComponentVNode(vnode))\n    .then(buffer => unrollBuffer(buffer, stream))\n    .then(() => resolveTeleports(context))\n    .then(() => {\n      if (context.__watcherHandles) {\n        for (const unwatch of context.__watcherHandles) {\n          unwatch()\n        }\n      }\n    })\n    .then(() => stream.push(null))\n    .catch(error => {\n      stream.destroy(error)\n    })\n\n  return stream\n}\n\n/**\n * @deprecated\n */\nexport function renderToStream(\n  input: App | VNode,\n  context: SSRContext = {},\n): Readable {\n  console.warn(\n    `[@vue/server-renderer] renderToStream is deprecated - use renderToNodeStream instead.`,\n  )\n  return renderToNodeStream(input, context)\n}\n\nexport function renderToNodeStream(\n  input: App | VNode,\n  context: SSRContext = {},\n): Readable {\n  const stream: Readable = __CJS__\n    ? new (require('node:stream').Readable)({ read() {} })\n    : null\n\n  if (!stream) {\n    throw new Error(\n      `ESM build of renderToStream() does not support renderToNodeStream(). ` +\n        `Use pipeToNodeWritable() with an existing Node.js Writable stream ` +\n        `instance instead.`,\n    )\n  }\n\n  return renderToSimpleStream(input, context, stream)\n}\n\nexport function pipeToNodeWritable(\n  input: App | VNode,\n  context: SSRContext | undefined = {},\n  writable: Writable,\n): void {\n  renderToSimpleStream(input, context, {\n    push(content) {\n      if (content != null) {\n        writable.write(content)\n      } else {\n        writable.end()\n      }\n    },\n    destroy(err) {\n      writable.destroy(err)\n    },\n  })\n}\n\nexport function renderToWebStream(\n  input: App | VNode,\n  context: SSRContext = {},\n): ReadableStream {\n  if (typeof ReadableStream !== 'function') {\n    throw new Error(\n      `ReadableStream constructor is not available in the global scope. ` +\n        `If the target environment does support web streams, consider using ` +\n        `pipeToWebWritable() with an existing WritableStream instance instead.`,\n    )\n  }\n\n  const encoder = new TextEncoder()\n  let cancelled = false\n\n  return new ReadableStream({\n    start(controller) {\n      renderToSimpleStream(input, context, {\n        push(content) {\n          if (cancelled) return\n          if (content != null) {\n            controller.enqueue(encoder.encode(content))\n          } else {\n            controller.close()\n          }\n        },\n        destroy(err) {\n          controller.error(err)\n        },\n      })\n    },\n    cancel() {\n      cancelled = true\n    },\n  })\n}\n\nexport function pipeToWebWritable(\n  input: App | VNode,\n  context: SSRContext | undefined = {},\n  writable: WritableStream,\n): void {\n  const writer = writable.getWriter()\n  const encoder = new TextEncoder()\n\n  // #4287 CloudFlare workers do not implement `ready` property\n  let hasReady = false\n  try {\n    hasReady = isPromise(writer.ready)\n  } catch (e: any) {}\n\n  renderToSimpleStream(input, context, {\n    async push(content) {\n      if (hasReady) {\n        await writer.ready\n      }\n      if (content != null) {\n        return writer.write(encoder.encode(content))\n      } else {\n        return writer.close()\n      }\n    },\n    destroy(err) {\n      // TODO better error handling?\n      // eslint-disable-next-line no-console\n      console.log(err)\n      writer.close()\n    },\n  })\n}\n"
  },
  {
    "path": "packages/server-renderer/src/renderToString.ts",
    "content": "import {\n  type App,\n  type VNode,\n  createApp,\n  createVNode,\n  ssrContextKey,\n  ssrUtils,\n} from 'vue'\nimport { isPromise, isString } from '@vue/shared'\nimport { type SSRBuffer, type SSRContext, renderComponentVNode } from './render'\n\nconst { isVNode } = ssrUtils\n\nfunction nestedUnrollBuffer(\n  buffer: SSRBuffer,\n  parentRet: string,\n  startIndex: number,\n): Promise<string> | string {\n  if (!buffer.hasAsync) {\n    return parentRet + unrollBufferSync(buffer)\n  }\n\n  let ret = parentRet\n  for (let i = startIndex; i < buffer.length; i += 1) {\n    const item = buffer[i]\n    if (isString(item)) {\n      ret += item\n      continue\n    }\n\n    if (isPromise(item)) {\n      return item.then(nestedItem => {\n        buffer[i] = nestedItem\n        return nestedUnrollBuffer(buffer, ret, i)\n      })\n    }\n\n    const result = nestedUnrollBuffer(item, ret, 0)\n    if (isPromise(result)) {\n      return result.then(nestedItem => {\n        buffer[i] = nestedItem\n        return nestedUnrollBuffer(buffer, '', i)\n      })\n    }\n\n    ret = result\n  }\n\n  return ret\n}\n\nexport function unrollBuffer(buffer: SSRBuffer): Promise<string> | string {\n  return nestedUnrollBuffer(buffer, '', 0)\n}\n\nfunction unrollBufferSync(buffer: SSRBuffer): string {\n  let ret = ''\n  for (let i = 0; i < buffer.length; i++) {\n    let item = buffer[i]\n    if (isString(item)) {\n      ret += item\n    } else {\n      // since this is a sync buffer, child buffers are never promises\n      ret += unrollBufferSync(item as SSRBuffer)\n    }\n  }\n  return ret\n}\n\nexport async function renderToString(\n  input: App | VNode,\n  context: SSRContext = {},\n): Promise<string> {\n  if (isVNode(input)) {\n    // raw vnode, wrap with app (for context)\n    return renderToString(createApp({ render: () => input }), context)\n  }\n\n  // rendering an app\n  const vnode = createVNode(input._component, input._props)\n  vnode.appContext = input._context\n  // provide the ssr context to the tree\n  input.provide(ssrContextKey, context)\n  const buffer = await renderComponentVNode(vnode)\n\n  const result = await unrollBuffer(buffer as SSRBuffer)\n\n  await resolveTeleports(context)\n\n  if (context.__watcherHandles) {\n    for (const unwatch of context.__watcherHandles) {\n      unwatch()\n    }\n  }\n\n  return result\n}\n\nexport async function resolveTeleports(context: SSRContext): Promise<void> {\n  if (context.__teleportBuffers) {\n    context.teleports = context.teleports || {}\n    for (const key in context.__teleportBuffers) {\n      // note: it's OK to await sequentially here because the Promises were\n      // created eagerly in parallel.\n      context.teleports[key] = await unrollBuffer(\n        await Promise.all([context.__teleportBuffers[key]]),\n      )\n    }\n  }\n}\n"
  },
  {
    "path": "packages/shared/LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2018-present, Yuxi (Evan) You\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "packages/shared/README.md",
    "content": "# @vue/shared\n\nInternal utility functions and constants shared across `@vue` packages.\n"
  },
  {
    "path": "packages/shared/__tests__/__snapshots__/codeframe.spec.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`compiler: codeframe > invalid start and end 1`] = `\n\"1  |  <div>\n   |  ^\n2  |    <template key=\"one\"></template>\n3  |    <ul>\"\n`;\n\nexports[`compiler: codeframe > invalid start and end 2`] = `\n\"1  |  <div>\n   |  ^^^^^\n2  |    <template key=\"one\"></template>\n   |  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n3  |    <ul>\n   |  ^^^^^^\n4  |      <li v-for=\"foobar\">hi</li>\n   |  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n5  |    </ul>\n   |  ^^^^^^^\n6  |    <template key=\"two\"></template>\n   |  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n7  |  </div>\n   |  ^^^^^^\"\n`;\n\nexports[`compiler: codeframe > invalid start and end 3`] = `\"\"`;\n\nexports[`compiler: codeframe > line in middle 1`] = `\n\"2  |    <template key=\"one\"></template>\n3  |    <ul>\n4  |      <li v-for=\"foobar\">hi</li>\n   |          ^^^^^^^^^^^^^^\n5  |    </ul>\n6  |    <template key=\"two\"></template>\"\n`;\n\nexports[`compiler: codeframe > line near bottom 1`] = `\n\"4  |      <li v-for=\"foobar\">hi</li>\n5  |    </ul>\n6  |    <template key=\"two\"></template>\n   |              ^^^^^^^^^\n7  |  </div>\"\n`;\n\nexports[`compiler: codeframe > line near top 1`] = `\n\"1  |  <div>\n2  |    <template key=\"one\"></template>\n   |              ^^^^^^^^^\n3  |    <ul>\n4  |      <li v-for=\"foobar\">hi</li>\"\n`;\n\nexports[`compiler: codeframe > multi-line highlights 1`] = `\n\"1  |  <div attr=\"some\n   |       ^^^^^^^^^^\n2  |    multiline\n   |  ^^^^^^^^^^^\n3  |  attr\n   |  ^^^^\n4  |  \">\n   |  ^\"\n`;\n\nexports[`compiler: codeframe > newline sequences - unix 1`] = `\n\"8  |          <input name=\"email\" type=\"text\"/>\n9  |        </div>\n10 |        <div id=\"hook\">\n   |        ^^^^^^^^^^^^^^^\n11 |          <label for=\"password\">Password</label>\n   |  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n12 |          <input name=\"password\" type=\"password\"/>\n   |  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n13 |        </div>\n   |  ^^^^^^^^^^^^\"\n`;\n\nexports[`compiler: codeframe > newline sequences - windows 1`] = `\n\"8  |          <input name=\"email\" type=\"text\"/>\n9  |        </div>\n10 |        <div id=\"hook\">\n   |        ^^^^^^^^^^^^^^^\n11 |          <label for=\"password\">Password</label>\n   |  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n12 |          <input name=\"password\" type=\"password\"/>\n   |  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n13 |        </div>\n   |  ^^^^^^^^^^^^\"\n`;\n"
  },
  {
    "path": "packages/shared/__tests__/codeframe.spec.ts",
    "content": "import { generateCodeFrame } from '../src/codeframe'\n\ndescribe('compiler: codeframe', () => {\n  const source = `\n<div>\n  <template key=\"one\"></template>\n  <ul>\n    <li v-for=\"foobar\">hi</li>\n  </ul>\n  <template key=\"two\"></template>\n</div>\n    `.trim()\n\n  test('line near top', () => {\n    const keyStart = source.indexOf(`key=\"one\"`)\n    const keyEnd = keyStart + `key=\"one\"`.length\n    expect(generateCodeFrame(source, keyStart, keyEnd)).toMatchSnapshot()\n  })\n\n  test('line in middle', () => {\n    // should cover 5 lines\n    const forStart = source.indexOf(`v-for=`)\n    const forEnd = forStart + `v-for=\"foobar\"`.length\n    expect(generateCodeFrame(source, forStart, forEnd)).toMatchSnapshot()\n  })\n\n  test('line near bottom', () => {\n    const keyStart = source.indexOf(`key=\"two\"`)\n    const keyEnd = keyStart + `key=\"two\"`.length\n    expect(generateCodeFrame(source, keyStart, keyEnd)).toMatchSnapshot()\n  })\n\n  test('multi-line highlights', () => {\n    const source = `\n<div attr=\"some\n  multiline\nattr\n\">\n</div>\n    `.trim()\n\n    const attrStart = source.indexOf(`attr=`)\n    const attrEnd = source.indexOf(`\">`) + 1\n    expect(generateCodeFrame(source, attrStart, attrEnd)).toMatchSnapshot()\n  })\n\n  test('invalid start and end', () => {\n    expect(generateCodeFrame(source, -Infinity, 0)).toMatchSnapshot()\n    expect(generateCodeFrame(source, 0, Infinity)).toMatchSnapshot()\n    expect(generateCodeFrame(source, Infinity, 0)).toMatchSnapshot()\n  })\n\n  {\n    const source = `\n<template>\n  <div>\n    <h1>Sign In</h1>\n    <form>\n      <div>\n        <label for=\"email\">Email</label>\n        <input name=\"email\" type=\"text\"/>\n      </div>\n      <div id=\"hook\">\n        <label for=\"password\">Password</label>\n        <input name=\"password\" type=\"password\"/>\n      </div>\n    </form>\n  </div>\n</template>\n`\n    const startToken = '<div id=\"hook\">'\n    const endToken = '</div>'\n\n    // Explicitly ensure the line-ending for the platform instead of assuming\n    // the newline sequences used in the source above.\n    const unixNewlineSource = source.replace(/\\r\\n/g, '\\n')\n    const windowsNewLineSource = unixNewlineSource.replace(/\\n/g, '\\r\\n')\n\n    test('newline sequences - windows', () => {\n      const keyStart = windowsNewLineSource.indexOf(startToken)\n      const keyEnd =\n        windowsNewLineSource.indexOf(endToken, keyStart) + endToken.length\n      expect(\n        generateCodeFrame(windowsNewLineSource, keyStart, keyEnd),\n      ).toMatchSnapshot()\n    })\n\n    test('newline sequences - unix', () => {\n      const keyStart = unixNewlineSource.indexOf(startToken)\n      const keyEnd =\n        unixNewlineSource.indexOf(endToken, keyStart) + endToken.length\n      expect(\n        generateCodeFrame(unixNewlineSource, keyStart, keyEnd),\n      ).toMatchSnapshot()\n    })\n  }\n})\n"
  },
  {
    "path": "packages/shared/__tests__/cssVars.spec.ts",
    "content": "import { normalizeCssVarValue } from '../src'\n\ndescribe('utils/cssVars', () => {\n  test('should normalize css binding values correctly', () => {\n    expect(normalizeCssVarValue(null)).toBe('initial')\n    expect(normalizeCssVarValue(undefined)).toBe('initial')\n    expect(normalizeCssVarValue('')).toBe(' ')\n    expect(normalizeCssVarValue('  ')).toBe('  ')\n    expect(normalizeCssVarValue('foo')).toBe('foo')\n    expect(normalizeCssVarValue(0)).toBe('0')\n  })\n\n  test('should warn on invalid css binding values', () => {\n    const warning =\n      '[Vue warn] Invalid value used for CSS binding. Expected a string or a finite number but received:'\n    expect(normalizeCssVarValue(NaN)).toBe('NaN')\n    expect(warning).toHaveBeenWarnedTimes(1)\n    expect(normalizeCssVarValue(Infinity)).toBe('Infinity')\n    expect(warning).toHaveBeenWarnedTimes(2)\n    expect(normalizeCssVarValue(-Infinity)).toBe('-Infinity')\n    expect(warning).toHaveBeenWarnedTimes(3)\n    expect(normalizeCssVarValue({})).toBe('[object Object]')\n    expect(warning).toHaveBeenWarnedTimes(4)\n    expect(normalizeCssVarValue([])).toBe('')\n    expect(warning).toHaveBeenWarnedTimes(5)\n  })\n})\n"
  },
  {
    "path": "packages/shared/__tests__/escapeHtml.spec.ts",
    "content": "import { escapeHtml, escapeHtmlComment } from '../src'\n\ndescribe('escapeHtml', () => {\n  test('ssr: escapeHTML', () => {\n    expect(escapeHtml(`foo`)).toBe(`foo`)\n    expect(escapeHtml(true)).toBe(`true`)\n    expect(escapeHtml(false)).toBe(`false`)\n    expect(escapeHtml(`a && b`)).toBe(`a &amp;&amp; b`)\n    expect(escapeHtml(`\"foo\"`)).toBe(`&quot;foo&quot;`)\n    expect(escapeHtml(`'bar'`)).toBe(`&#39;bar&#39;`)\n    expect(escapeHtml(`<div>`)).toBe(`&lt;div&gt;`)\n  })\n\n  test('ssr: escapeHTMLComment', () => {\n    const input = '<!-- Hello --><!-- World! -->'\n    const result = escapeHtmlComment(input)\n    expect(result).toEqual(' Hello  World! ')\n  })\n\n  test('ssr: escapeHTMLComment', () => {\n    const input = '<!-- Comment 1 --> Hello <!--! Comment 2 --> World!'\n    const result = escapeHtmlComment(input)\n    expect(result).toEqual(' Comment 1  Hello ! Comment 2  World!')\n  })\n\n  test('should not affect non-comment strings', () => {\n    const input = 'Hello World'\n    const result = escapeHtmlComment(input)\n    expect(result).toEqual(input)\n  })\n})\n"
  },
  {
    "path": "packages/shared/__tests__/looseEqual.spec.ts",
    "content": "/**\n * @vitest-environment jsdom\n */\nimport { looseEqual } from '../src'\n\ndescribe('utils/looseEqual', () => {\n  test('compares booleans correctly', () => {\n    expect(looseEqual(true, true)).toBe(true)\n    expect(looseEqual(false, false)).toBe(true)\n    expect(looseEqual(true, false)).toBe(false)\n    expect(looseEqual(true, 1)).toBe(false)\n    expect(looseEqual(false, 0)).toBe(false)\n  })\n\n  test('compares strings correctly', () => {\n    const text = 'Lorem ipsum'\n    const number = 1\n    const bool = true\n\n    expect(looseEqual(text, text)).toBe(true)\n    expect(looseEqual(text, text.slice(0, -1))).toBe(false)\n    expect(looseEqual(String(number), number)).toBe(true)\n    expect(looseEqual(String(bool), bool)).toBe(true)\n  })\n\n  test('compares numbers correctly', () => {\n    const number = 100\n    const decimal = 2.5\n    const multiplier = 1.0000001\n\n    expect(looseEqual(number, number)).toBe(true)\n    expect(looseEqual(number, number - 1)).toBe(false)\n    expect(looseEqual(decimal, decimal)).toBe(true)\n    expect(looseEqual(decimal, decimal * multiplier)).toBe(false)\n    expect(looseEqual(number, number * multiplier)).toBe(false)\n    expect(looseEqual(multiplier, multiplier)).toBe(true)\n  })\n\n  test('compares dates correctly', () => {\n    const date1 = new Date(2019, 1, 2, 3, 4, 5, 6)\n    const date2 = new Date(2019, 1, 2, 3, 4, 5, 6)\n    const date3 = new Date(2019, 1, 2, 3, 4, 5, 7)\n    const date4 = new Date(2219, 1, 2, 3, 4, 5, 6)\n\n    // Identical date object references\n    expect(looseEqual(date1, date1)).toBe(true)\n    // Different date references with identical values\n    expect(looseEqual(date1, date2)).toBe(true)\n    // Dates with slightly different time (ms)\n    expect(looseEqual(date1, date3)).toBe(false)\n    // Dates with different year\n    expect(looseEqual(date1, date4)).toBe(false)\n  })\n\n  test('compares symbols correctly', () => {\n    const symbol1 = Symbol('a')\n    const symbol2 = Symbol('a')\n    const symbol3 = Symbol('b')\n    const notSymbol = 0\n\n    expect(looseEqual(symbol1, symbol1)).toBe(true)\n    expect(looseEqual(symbol1, symbol2)).toBe(false)\n    expect(looseEqual(symbol1, symbol3)).toBe(false)\n    expect(looseEqual(symbol1, notSymbol)).toBe(false)\n  })\n\n  test('compares files correctly', () => {\n    const date1 = new Date(2019, 1, 2, 3, 4, 5, 6)\n    const date2 = new Date(2019, 1, 2, 3, 4, 5, 7)\n    const file1 = new File([''], 'filename.txt', {\n      type: 'text/plain',\n      lastModified: date1.getTime(),\n    })\n    const file2 = new File([''], 'filename.txt', {\n      type: 'text/plain',\n      lastModified: date1.getTime(),\n    })\n    const file3 = new File([''], 'filename.txt', {\n      type: 'text/plain',\n      lastModified: date2.getTime(),\n    })\n    const file4 = new File([''], 'filename.csv', {\n      type: 'text/csv',\n      lastModified: date1.getTime(),\n    })\n    const file5 = new File(['abcdef'], 'filename.txt', {\n      type: 'text/plain',\n      lastModified: date1.getTime(),\n    })\n    const file6 = new File(['12345'], 'filename.txt', {\n      type: 'text/plain',\n      lastModified: date1.getTime(),\n    })\n\n    // Identical file object references\n    expect(looseEqual(file1, file1)).toBe(true)\n    // Different file references with identical values\n    expect(looseEqual(file1, file2)).toBe(true)\n    // Files with slightly different dates\n    expect(looseEqual(file1, file3)).toBe(false)\n    // Two different file types\n    expect(looseEqual(file1, file4)).toBe(false)\n    // Two files with same name, modified date, but different content\n    expect(looseEqual(file5, file6)).toBe(false)\n  })\n\n  test('compares arrays correctly', () => {\n    const arr1 = [1, 2, 3, 4]\n    const arr2 = [1, 2, 3, '4']\n    const arr3 = [1, 2, 3, 4, 5]\n    const arr4 = [1, 2, 3, 4, { a: 5 }]\n\n    // Identical array references\n    expect(looseEqual(arr1, arr1)).toBe(true)\n    // Different array references with identical values\n    expect(looseEqual(arr1, arr1.slice())).toBe(true)\n    expect(looseEqual(arr4, arr4.slice())).toBe(true)\n    // Array with one value different (loose)\n    expect(looseEqual(arr1, arr2)).toBe(true)\n    // Array with one value different\n    expect(looseEqual(arr3, arr4)).toBe(false)\n    // Arrays with different lengths\n    expect(looseEqual(arr1, arr3)).toBe(false)\n    // Arrays with values in different order\n    expect(looseEqual(arr1, arr1.slice().reverse())).toBe(false)\n  })\n\n  test('compares RegExp correctly', () => {\n    const rx1 = /^foo$/\n    const rx2 = /^foo$/\n    const rx3 = /^bar$/\n    const rx4 = /^bar$/i\n\n    // Identical regex references\n    expect(looseEqual(rx1, rx1)).toBe(true)\n    // Different regex references with identical values\n    expect(looseEqual(rx1, rx2)).toBe(true)\n    // Different regex\n    expect(looseEqual(rx1, rx3)).toBe(false)\n    // Same regex with different options\n    expect(looseEqual(rx3, rx4)).toBe(false)\n  })\n\n  test('compares objects correctly', () => {\n    const obj1 = { foo: 'bar' }\n    const obj2 = { foo: 'bar1' }\n    const obj3 = { a: 1, b: 2, c: 3 }\n    const obj4 = { b: 2, c: 3, a: 1 }\n    const obj5 = { ...obj4, z: 999 }\n    const nestedObj1 = { ...obj1, bar: [{ ...obj1 }, { ...obj1 }] }\n    const nestedObj2 = { ...obj1, bar: [{ ...obj1 }, { ...obj2 }] }\n\n    // Identical object references\n    expect(looseEqual(obj1, obj1)).toBe(true)\n    // Two objects with identical keys/values\n    expect(looseEqual(obj1, { ...obj1 })).toBe(true)\n    // Different key values\n    expect(looseEqual(obj1, obj2)).toBe(false)\n    // Keys in different orders\n    expect(looseEqual(obj3, obj4)).toBe(true)\n    // One object has additional key\n    expect(looseEqual(obj4, obj5)).toBe(false)\n    // Identical object references with nested array\n    expect(looseEqual(nestedObj1, nestedObj1)).toBe(true)\n    // Identical object definitions with nested array\n    expect(looseEqual(nestedObj1, { ...nestedObj1 })).toBe(true)\n    // Object definitions with nested array (which has different order)\n    expect(looseEqual(nestedObj1, nestedObj2)).toBe(false)\n  })\n\n  test('compares different types correctly', () => {\n    const obj1 = {}\n    const obj2 = { a: 1 }\n    const obj3 = { 0: 0, 1: 1, 2: 2 }\n    const arr1: any[] = []\n    const arr2 = [1]\n    const arr3 = [0, 1, 2]\n    const date1 = new Date(2019, 1, 2, 3, 4, 5, 6)\n    const file1 = new File([''], 'filename.txt', {\n      type: 'text/plain',\n      lastModified: date1.getTime(),\n    })\n\n    expect(looseEqual(123, '123')).toBe(true)\n    expect(looseEqual(123, new Date(123))).toBe(false)\n    expect(looseEqual(`123`, new Date(123))).toBe(false)\n    expect(looseEqual([1, 2, 3], '1,2,3')).toBe(false)\n    expect(looseEqual(obj1, arr1)).toBe(false)\n    expect(looseEqual(obj2, arr2)).toBe(false)\n    expect(looseEqual(obj1, '[object Object]')).toBe(false)\n    expect(looseEqual(arr1, '[object Array]')).toBe(false)\n    expect(looseEqual(obj1, date1)).toBe(false)\n    expect(looseEqual(obj2, date1)).toBe(false)\n    expect(looseEqual(arr1, date1)).toBe(false)\n    expect(looseEqual(arr2, date1)).toBe(false)\n    expect(looseEqual(obj2, file1)).toBe(false)\n    expect(looseEqual(arr2, file1)).toBe(false)\n    expect(looseEqual(date1, file1)).toBe(false)\n    // Special case where an object's keys are the same as keys (indexes) of an array\n    expect(looseEqual(obj3, arr3)).toBe(false)\n  })\n\n  test('compares null and undefined values correctly', () => {\n    expect(looseEqual(null, null)).toBe(true)\n    expect(looseEqual(undefined, undefined)).toBe(true)\n    expect(looseEqual(void 0, undefined)).toBe(true)\n    expect(looseEqual(null, undefined)).toBe(false)\n    expect(looseEqual(null, void 0)).toBe(false)\n    expect(looseEqual(null, '')).toBe(false)\n    expect(looseEqual(null, false)).toBe(false)\n    expect(looseEqual(undefined, false)).toBe(false)\n  })\n\n  test('compares sparse arrays correctly', () => {\n    // The following arrays all have a length of 3\n    // But the first two are \"sparse\"\n    const arr1 = []\n    arr1[2] = true\n    const arr2 = []\n    arr2[2] = true\n    const arr3 = [false, false, true]\n    const arr4 = [undefined, undefined, true]\n    // This one is also sparse (missing index 1)\n    const arr5 = []\n    arr5[0] = arr5[2] = true\n\n    expect(looseEqual(arr1, arr2)).toBe(true)\n    expect(looseEqual(arr2, arr1)).toBe(true)\n    expect(looseEqual(arr1, arr3)).toBe(false)\n    expect(looseEqual(arr3, arr1)).toBe(false)\n    expect(looseEqual(arr1, arr4)).toBe(true)\n    expect(looseEqual(arr4, arr1)).toBe(true)\n    expect(looseEqual(arr1, arr5)).toBe(false)\n    expect(looseEqual(arr5, arr1)).toBe(false)\n  })\n})\n"
  },
  {
    "path": "packages/shared/__tests__/normalizeProp.spec.ts",
    "content": "import {\n  normalizeClass,\n  normalizeProps,\n  normalizeStyle,\n  parseStringStyle,\n  stringifyStyle,\n} from '../src'\n\ndescribe('normalizeClass', () => {\n  test('handles undefined correctly', () => {\n    expect(normalizeClass(undefined)).toEqual('')\n  })\n\n  test('handles string correctly', () => {\n    expect(normalizeClass('foo')).toEqual('foo')\n  })\n\n  test('handles array correctly', () => {\n    expect(normalizeClass(['foo', undefined, true, false, 'bar'])).toEqual(\n      'foo bar',\n    )\n  })\n\n  test('handles string containing spaces correctly', () => {\n    expect(normalizeClass('foo1 ')).toEqual('foo1')\n    expect(normalizeClass(['foo ', ' baz '])).toEqual('foo baz')\n  })\n\n  test('handles empty array correctly', () => {\n    expect(normalizeClass([])).toEqual('')\n  })\n\n  test('handles nested array correctly', () => {\n    expect(normalizeClass(['foo', ['bar'], [['baz']]])).toEqual('foo bar baz')\n  })\n\n  test('handles object correctly', () => {\n    expect(normalizeClass({ foo: true, bar: false, baz: true })).toEqual(\n      'foo baz',\n    )\n  })\n\n  test('handles empty object correctly', () => {\n    expect(normalizeClass({})).toEqual('')\n  })\n\n  test('handles arrays and objects correctly', () => {\n    expect(\n      normalizeClass(['foo', ['bar'], { baz: true }, [{ qux: true }]]),\n    ).toEqual('foo bar baz qux')\n  })\n\n  test('handles array of objects with falsy values', () => {\n    expect(\n      normalizeClass([\n        { foo: false },\n        { bar: 0 },\n        { baz: -0 },\n        { qux: '' },\n        { quux: null },\n        { corge: undefined },\n        { grault: NaN },\n      ]),\n    ).toEqual('')\n  })\n\n  test('handles array of objects with truthy values', () => {\n    expect(\n      normalizeClass([\n        { foo: true },\n        { bar: 'not-empty' },\n        { baz: 1 },\n        { qux: {} },\n        { quux: [] },\n      ]),\n    ).toEqual('foo bar baz qux quux')\n  })\n\n  // #6777\n  test('parse multi-line inline style', () => {\n    expect(\n      parseStringStyle(`border: 1px solid transparent;\n    background: linear-gradient(white, white) padding-box,\n      repeating-linear-gradient(\n        -45deg,\n        #ccc 0,\n        #ccc 0.5em,\n        white 0,\n        white 0.75em\n      );`),\n    ).toMatchInlineSnapshot(`\n      {\n        \"background\": \"linear-gradient(white, white) padding-box,\n            repeating-linear-gradient(\n              -45deg,\n              #ccc 0,\n              #ccc 0.5em,\n              white 0,\n              white 0.75em\n            )\",\n        \"border\": \"1px solid transparent\",\n      }\n    `)\n  })\n})\n\ndescribe('normalizeStyle', () => {\n  test('handles string correctly', () => {\n    expect(normalizeStyle('foo')).toEqual('foo')\n  })\n\n  test('handles array correctly', () => {\n    const style: any = normalizeStyle([\n      `border: 1px solid transparent;\n    background: linear-gradient(white, white) padding-box,\n      repeating-linear-gradient(\n        -45deg,\n        #ccc 0,\n        #ccc 0.5em,\n        white 0,\n        white 0.75em\n      );`,\n    ])\n\n    expect(style.border).toEqual('1px solid transparent')\n\n    expect(style.background).toEqual(`linear-gradient(white, white) padding-box,\n      repeating-linear-gradient(\n        -45deg,\n        #ccc 0,\n        #ccc 0.5em,\n        white 0,\n        white 0.75em\n      )`)\n  })\n\n  test('handles object correctly', () => {\n    const styleObj = {\n      border: '1px solid transparent',\n      background: `linear-gradient(white, white) padding-box,\n      repeating-linear-gradient(\n        -45deg,\n        #ccc 0,\n        #ccc 0.5em,\n        white 0,\n        white 0.75em\n      )`,\n    }\n    const style: any = normalizeStyle(styleObj)\n    expect(style.border).toEqual(styleObj.border)\n    expect(style.background).toEqual(styleObj.background)\n  })\n})\n\ndescribe('stringifyStyle', () => {\n  test('should return empty string for undefined', () => {\n    expect(stringifyStyle(undefined)).toBe('')\n    expect(stringifyStyle('')).toBe('')\n    expect(stringifyStyle('color: blue;')).toBe('color: blue;')\n  })\n\n  test('should return valid CSS string for normalized style object', () => {\n    const style = {\n      color: 'blue',\n      fontSize: '14px',\n      backgroundColor: 'white',\n      opacity: 0.8,\n      margin: 0,\n      '--custom-color': 'red',\n    }\n\n    expect(stringifyStyle(style)).toBe(\n      'color:blue;font-size:14px;background-color:white;opacity:0.8;margin:0;--custom-color:red;',\n    )\n  })\n\n  test('should ignore non-string or non-number values in style object', () => {\n    const style: any = {\n      color: 'blue',\n      fontSize: '14px',\n      lineHeight: true,\n      padding: null,\n      margin: undefined,\n    }\n\n    const expected = 'color:blue;font-size:14px;'\n    expect(stringifyStyle(style)).toBe(expected)\n  })\n})\n\ndescribe('normalizeProps', () => {\n  test('should return null when props is null', () => {\n    const props = null\n    const result = normalizeProps(props)\n    expect(result).toBeNull()\n  })\n\n  test('should normalize class prop when it is an array', () => {\n    const props = {\n      class: ['class1', 'class2'],\n    }\n    const result = normalizeProps(props)\n    expect(result).toEqual({\n      class: 'class1 class2',\n    })\n  })\n\n  test('should normalize class prop when it is an object', () => {\n    const props = {\n      class: {\n        class1: true,\n        class2: false,\n        class3: true,\n      },\n    }\n    const result = normalizeProps(props)\n    expect(result).toEqual({\n      class: 'class1 class3',\n    })\n  })\n\n  test('should normalize style prop', () => {\n    const props = {\n      style: ['color: blue', 'font-size: 14px'],\n    }\n    const result = normalizeProps(props)\n    expect(result).toEqual({\n      style: {\n        color: 'blue',\n        'font-size': '14px',\n      },\n    })\n  })\n})\n"
  },
  {
    "path": "packages/shared/__tests__/toDisplayString.spec.ts",
    "content": "/**\n * @vitest-environment jsdom\n */\nimport { computed, ref } from '@vue/reactivity'\nimport { toDisplayString } from '../src'\n\ndescribe('toDisplayString', () => {\n  test('nullish values', () => {\n    expect(toDisplayString(null)).toBe('')\n    expect(toDisplayString(undefined)).toBe('')\n  })\n\n  test('primitive values', () => {\n    expect(toDisplayString(0)).toBe('0')\n    expect(toDisplayString(1)).toBe('1')\n    expect(toDisplayString(NaN)).toBe('NaN')\n    expect(toDisplayString(true)).toBe('true')\n    expect(toDisplayString(false)).toBe('false')\n    expect(toDisplayString('hello')).toBe('hello')\n  })\n\n  test('primitive values in refs', () => {\n    expect(toDisplayString(ref(0))).toBe('0')\n    expect(toDisplayString(ref(1))).toBe('1')\n    expect(toDisplayString(ref(NaN))).toBe('NaN')\n    expect(toDisplayString(ref(true))).toBe('true')\n    expect(toDisplayString(ref(false))).toBe('false')\n    expect(toDisplayString(ref('hello'))).toBe('hello')\n  })\n\n  test('symbol values', () => {\n    expect(toDisplayString(Symbol('hello'))).toBe('Symbol(hello)')\n    expect(toDisplayString(ref(Symbol('hello')))).toBe('Symbol(hello)')\n  })\n\n  test('Object and Arrays', () => {\n    const obj = { foo: 123 }\n    expect(toDisplayString(obj)).toBe(JSON.stringify(obj, null, 2))\n    const arr = [obj]\n    expect(toDisplayString(arr)).toBe(JSON.stringify(arr, null, 2))\n\n    const objWithToStringOverride = {\n      foo: 555,\n      toString() {\n        return 'override'\n      },\n    }\n    expect(toDisplayString(objWithToStringOverride)).toBe('override')\n\n    const objWithNonInvokableToString = {\n      foo: 555,\n      toString: null,\n    }\n    expect(toDisplayString(objWithNonInvokableToString)).toBe(\n      `{\n  \"foo\": 555,\n  \"toString\": null\n}`,\n    )\n\n    // object created from null does not have .toString in its prototype\n    const nullObjectWithoutToString = Object.create(null)\n    nullObjectWithoutToString.bar = 1\n    expect(toDisplayString(nullObjectWithoutToString)).toBe(\n      `{\n  \"bar\": 1\n}`,\n    )\n\n    // array toString override is ignored\n    const arrWithToStringOverride = [1, 2, 3]\n    arrWithToStringOverride.toString = () =>\n      'override for array is not supported'\n    expect(toDisplayString(arrWithToStringOverride)).toBe(\n      `[\n  1,\n  2,\n  3\n]`,\n    )\n  })\n\n  test('refs', () => {\n    const n = ref(1)\n    const np = computed(() => n.value + 1)\n    expect(\n      toDisplayString({\n        n,\n        np,\n      }),\n    ).toBe(JSON.stringify({ n: 1, np: 2 }, null, 2))\n  })\n\n  test('objects with custom toString', () => {\n    class TestClass {\n      toString() {\n        return 'foo'\n      }\n    }\n    const instance = new TestClass()\n    expect(toDisplayString(instance)).toBe('foo')\n    const obj = { toString: () => 'bar' }\n    expect(toDisplayString(obj)).toBe('bar')\n  })\n\n  test('native objects', () => {\n    const div = document.createElement('div')\n    expect(toDisplayString(div)).toMatch('[object HTMLDivElement]')\n    expect(toDisplayString({ div })).toMatchInlineSnapshot(`\n      \"{\n        \"div\": \"[object HTMLDivElement]\"\n      }\"\n    `)\n  })\n\n  test('Map and Set', () => {\n    const m = new Map<any, any>([\n      [1, 'foo'],\n      [{ baz: 1 }, { foo: 'bar', qux: 2 }],\n    ])\n    const s = new Set<any>([1, { foo: 'bar' }, m])\n\n    expect(toDisplayString(m)).toMatchInlineSnapshot(`\n      \"{\n        \"Map(2)\": {\n          \"1 =>\": \"foo\",\n          \"[object Object] =>\": {\n            \"foo\": \"bar\",\n            \"qux\": 2\n          }\n        }\n      }\"\n    `)\n    expect(toDisplayString(s)).toMatchInlineSnapshot(`\n      \"{\n        \"Set(3)\": [\n          1,\n          {\n            \"foo\": \"bar\"\n          },\n          {\n            \"Map(2)\": {\n              \"1 =>\": \"foo\",\n              \"[object Object] =>\": {\n                \"foo\": \"bar\",\n                \"qux\": 2\n              }\n            }\n          }\n        ]\n      }\"\n    `)\n\n    expect(\n      toDisplayString({\n        m,\n        s,\n      }),\n    ).toMatchInlineSnapshot(`\n      \"{\n        \"m\": {\n          \"Map(2)\": {\n            \"1 =>\": \"foo\",\n            \"[object Object] =>\": {\n              \"foo\": \"bar\",\n              \"qux\": 2\n            }\n          }\n        },\n        \"s\": {\n          \"Set(3)\": [\n            1,\n            {\n              \"foo\": \"bar\"\n            },\n            {\n              \"Map(2)\": {\n                \"1 =>\": \"foo\",\n                \"[object Object] =>\": {\n                  \"foo\": \"bar\",\n                  \"qux\": 2\n                }\n              }\n            }\n          ]\n        }\n      }\"\n    `)\n  })\n\n  //#9727\n  test('Map with Symbol keys', () => {\n    const m = new Map<any, any>([\n      [Symbol(), 'foo'],\n      [Symbol(), 'bar'],\n      [Symbol('baz'), 'baz'],\n    ])\n    expect(toDisplayString(m)).toMatchInlineSnapshot(`\n      \"{\n        \"Map(3)\": {\n          \"Symbol(0) =>\": \"foo\",\n          \"Symbol(1) =>\": \"bar\",\n          \"Symbol(baz) =>\": \"baz\"\n        }\n      }\"\n    `)\n    // confirming the symbol renders Symbol(foo)\n    expect(toDisplayString(new Map([[Symbol('foo'), 'foo']]))).toContain(\n      String(Symbol('foo')),\n    )\n  })\n\n  test('Set with Symbol values', () => {\n    const s = new Set([Symbol('foo'), Symbol('bar'), Symbol()])\n    expect(toDisplayString(s)).toMatchInlineSnapshot(`\n      \"{\n        \"Set(3)\": [\n          \"Symbol(foo)\",\n          \"Symbol(bar)\",\n          \"Symbol()\"\n        ]\n      }\"\n    `)\n  })\n\n  test('Object with Symbol values', () => {\n    expect(toDisplayString({ foo: Symbol('x'), bar: Symbol() }))\n      .toMatchInlineSnapshot(`\n      \"{\n        \"foo\": \"Symbol(x)\",\n        \"bar\": \"Symbol()\"\n      }\"\n    `)\n  })\n})\n"
  },
  {
    "path": "packages/shared/index.js",
    "content": "'use strict'\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./dist/shared.cjs.prod.js')\n} else {\n  module.exports = require('./dist/shared.cjs.js')\n}\n"
  },
  {
    "path": "packages/shared/package.json",
    "content": "{\n  \"name\": \"@vue/shared\",\n  \"version\": \"3.5.30\",\n  \"description\": \"internal utils shared across @vue packages\",\n  \"main\": \"index.js\",\n  \"module\": \"dist/shared.esm-bundler.js\",\n  \"types\": \"dist/shared.d.ts\",\n  \"files\": [\n    \"index.js\",\n    \"dist\"\n  ],\n  \"exports\": {\n    \".\": {\n      \"types\": \"./dist/shared.d.ts\",\n      \"node\": {\n        \"production\": \"./dist/shared.cjs.prod.js\",\n        \"development\": \"./dist/shared.cjs.js\",\n        \"default\": \"./index.js\"\n      },\n      \"module\": \"./dist/shared.esm-bundler.js\",\n      \"import\": \"./dist/shared.esm-bundler.js\",\n      \"require\": \"./index.js\"\n    },\n    \"./*\": \"./*\"\n  },\n  \"sideEffects\": false,\n  \"buildOptions\": {\n    \"formats\": [\n      \"esm-bundler\",\n      \"cjs\"\n    ]\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/vuejs/core.git\",\n    \"directory\": \"packages/shared\"\n  },\n  \"keywords\": [\n    \"vue\"\n  ],\n  \"author\": \"Evan You\",\n  \"license\": \"MIT\",\n  \"bugs\": {\n    \"url\": \"https://github.com/vuejs/core/issues\"\n  },\n  \"homepage\": \"https://github.com/vuejs/core/tree/main/packages/shared#readme\"\n}\n"
  },
  {
    "path": "packages/shared/src/codeframe.ts",
    "content": "const range: number = 2\n\nexport function generateCodeFrame(\n  source: string,\n  start = 0,\n  end: number = source.length,\n): string {\n  // Ensure start and end are within the source length\n  start = Math.max(0, Math.min(start, source.length))\n  end = Math.max(0, Math.min(end, source.length))\n\n  if (start > end) return ''\n\n  // Split the content into individual lines but capture the newline sequence\n  // that separated each line. This is important because the actual sequence is\n  // needed to properly take into account the full line length for offset\n  // comparison\n  let lines = source.split(/(\\r?\\n)/)\n\n  // Separate the lines and newline sequences into separate arrays for easier referencing\n  const newlineSequences = lines.filter((_, idx) => idx % 2 === 1)\n  lines = lines.filter((_, idx) => idx % 2 === 0)\n\n  let count = 0\n  const res: string[] = []\n  for (let i = 0; i < lines.length; i++) {\n    count +=\n      lines[i].length +\n      ((newlineSequences[i] && newlineSequences[i].length) || 0)\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        res.push(\n          `${line}${' '.repeat(Math.max(3 - String(line).length, 0))}|  ${\n            lines[j]\n          }`,\n        )\n        const lineLength = lines[j].length\n        const newLineSeqLength =\n          (newlineSequences[j] && newlineSequences[j].length) || 0\n\n        if (j === i) {\n          // push underline\n          const pad = start - (count - (lineLength + newLineSeqLength))\n          const length = Math.max(\n            1,\n            end > count ? lineLength - pad : end - start,\n          )\n          res.push(`   |  ` + ' '.repeat(pad) + '^'.repeat(length))\n        } else if (j > i) {\n          if (end > count) {\n            const length = Math.max(Math.min(end - count, lineLength), 1)\n            res.push(`   |  ` + '^'.repeat(length))\n          }\n\n          count += lineLength + newLineSeqLength\n        }\n      }\n      break\n    }\n  }\n  return res.join('\\n')\n}\n"
  },
  {
    "path": "packages/shared/src/cssVars.ts",
    "content": "/**\n * Normalize CSS var value created by `v-bind` in `<style>` block\n * See https://github.com/vuejs/core/pull/12461#issuecomment-2495804664\n */\nexport function normalizeCssVarValue(value: unknown): string {\n  if (value == null) {\n    return 'initial'\n  }\n\n  if (typeof value === 'string') {\n    return value === '' ? ' ' : value\n  }\n\n  if (typeof value !== 'number' || !Number.isFinite(value)) {\n    if (__DEV__) {\n      console.warn(\n        '[Vue warn] Invalid value used for CSS binding. Expected a string or a finite number but received:',\n        value,\n      )\n    }\n  }\n\n  return String(value)\n}\n"
  },
  {
    "path": "packages/shared/src/domAttrConfig.ts",
    "content": "import { makeMap } from './makeMap'\n\n/**\n * On the client we only need to offer special cases for boolean attributes that\n * have different names from their corresponding dom properties:\n * - itemscope -> N/A\n * - allowfullscreen -> allowFullscreen\n * - formnovalidate -> formNoValidate\n * - ismap -> isMap\n * - nomodule -> noModule\n * - novalidate -> noValidate\n * - readonly -> readOnly\n */\nconst specialBooleanAttrs = `itemscope,allowfullscreen,formnovalidate,ismap,nomodule,novalidate,readonly`\nexport const isSpecialBooleanAttr: (key: string) => boolean =\n  /*@__PURE__*/ makeMap(specialBooleanAttrs)\n\n/**\n * The full list is needed during SSR to produce the correct initial markup.\n */\nexport const isBooleanAttr: (key: string) => boolean = /*@__PURE__*/ makeMap(\n  specialBooleanAttrs +\n    `,async,autofocus,autoplay,controls,default,defer,disabled,hidden,` +\n    `inert,loop,open,required,reversed,scoped,seamless,` +\n    `checked,muted,multiple,selected`,\n)\n\n/**\n * Boolean attributes should be included if the value is truthy or ''.\n * e.g. `<select multiple>` compiles to `{ multiple: '' }`\n */\nexport function includeBooleanAttr(value: unknown): boolean {\n  return !!value || value === ''\n}\n\nconst unsafeAttrCharRE = /[>/=\"'\\u0009\\u000a\\u000c\\u0020]/\nconst attrValidationCache: Record<string, boolean> = {}\n\nexport function isSSRSafeAttrName(name: string): boolean {\n  if (attrValidationCache.hasOwnProperty(name)) {\n    return attrValidationCache[name]\n  }\n  const isUnsafe = unsafeAttrCharRE.test(name)\n  if (isUnsafe) {\n    console.error(`unsafe attribute name: ${name}`)\n  }\n  return (attrValidationCache[name] = !isUnsafe)\n}\n\nexport const propsToAttrMap: Record<string, string | undefined> = {\n  acceptCharset: 'accept-charset',\n  className: 'class',\n  htmlFor: 'for',\n  httpEquiv: 'http-equiv',\n}\n\n/**\n * Known attributes, this is used for stringification of runtime static nodes\n * so that we don't stringify bindings that cannot be set from HTML.\n * Don't also forget to allow `data-*` and `aria-*`!\n * Generated from https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes\n */\nexport const isKnownHtmlAttr: (key: string) => boolean = /*@__PURE__*/ makeMap(\n  `accept,accept-charset,accesskey,action,align,allow,alt,async,` +\n    `autocapitalize,autocomplete,autofocus,autoplay,background,bgcolor,` +\n    `border,buffered,capture,challenge,charset,checked,cite,class,code,` +\n    `codebase,color,cols,colspan,content,contenteditable,contextmenu,controls,` +\n    `coords,crossorigin,csp,data,datetime,decoding,default,defer,dir,dirname,` +\n    `disabled,download,draggable,dropzone,enctype,enterkeyhint,for,form,` +\n    `formaction,formenctype,formmethod,formnovalidate,formtarget,headers,` +\n    `height,hidden,high,href,hreflang,http-equiv,icon,id,importance,inert,integrity,` +\n    `ismap,itemprop,keytype,kind,label,lang,language,loading,list,loop,low,` +\n    `manifest,max,maxlength,minlength,media,min,multiple,muted,name,novalidate,` +\n    `open,optimum,pattern,ping,placeholder,poster,preload,radiogroup,readonly,` +\n    `referrerpolicy,rel,required,reversed,rows,rowspan,sandbox,scope,scoped,` +\n    `selected,shape,size,sizes,slot,span,spellcheck,src,srcdoc,srclang,srcset,` +\n    `start,step,style,summary,tabindex,target,title,translate,type,usemap,` +\n    `value,width,wrap`,\n)\n\n/**\n * Generated from https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute\n */\nexport const isKnownSvgAttr: (key: string) => boolean = /*@__PURE__*/ makeMap(\n  `xmlns,accent-height,accumulate,additive,alignment-baseline,alphabetic,amplitude,` +\n    `arabic-form,ascent,attributeName,attributeType,azimuth,baseFrequency,` +\n    `baseline-shift,baseProfile,bbox,begin,bias,by,calcMode,cap-height,class,` +\n    `clip,clipPathUnits,clip-path,clip-rule,color,color-interpolation,` +\n    `color-interpolation-filters,color-profile,color-rendering,` +\n    `contentScriptType,contentStyleType,crossorigin,cursor,cx,cy,d,decelerate,` +\n    `descent,diffuseConstant,direction,display,divisor,dominant-baseline,dur,dx,` +\n    `dy,edgeMode,elevation,enable-background,end,exponent,fill,fill-opacity,` +\n    `fill-rule,filter,filterRes,filterUnits,flood-color,flood-opacity,` +\n    `font-family,font-size,font-size-adjust,font-stretch,font-style,` +\n    `font-variant,font-weight,format,from,fr,fx,fy,g1,g2,glyph-name,` +\n    `glyph-orientation-horizontal,glyph-orientation-vertical,glyphRef,` +\n    `gradientTransform,gradientUnits,hanging,height,href,hreflang,horiz-adv-x,` +\n    `horiz-origin-x,id,ideographic,image-rendering,in,in2,intercept,k,k1,k2,k3,` +\n    `k4,kernelMatrix,kernelUnitLength,kerning,keyPoints,keySplines,keyTimes,` +\n    `lang,lengthAdjust,letter-spacing,lighting-color,limitingConeAngle,local,` +\n    `marker-end,marker-mid,marker-start,markerHeight,markerUnits,markerWidth,` +\n    `mask,maskContentUnits,maskUnits,mathematical,max,media,method,min,mode,` +\n    `name,numOctaves,offset,opacity,operator,order,orient,orientation,origin,` +\n    `overflow,overline-position,overline-thickness,panose-1,paint-order,path,` +\n    `pathLength,patternContentUnits,patternTransform,patternUnits,ping,` +\n    `pointer-events,points,pointsAtX,pointsAtY,pointsAtZ,preserveAlpha,` +\n    `preserveAspectRatio,primitiveUnits,r,radius,referrerPolicy,refX,refY,rel,` +\n    `rendering-intent,repeatCount,repeatDur,requiredExtensions,requiredFeatures,` +\n    `restart,result,rotate,rx,ry,scale,seed,shape-rendering,slope,spacing,` +\n    `specularConstant,specularExponent,speed,spreadMethod,startOffset,` +\n    `stdDeviation,stemh,stemv,stitchTiles,stop-color,stop-opacity,` +\n    `strikethrough-position,strikethrough-thickness,string,stroke,` +\n    `stroke-dasharray,stroke-dashoffset,stroke-linecap,stroke-linejoin,` +\n    `stroke-miterlimit,stroke-opacity,stroke-width,style,surfaceScale,` +\n    `systemLanguage,tabindex,tableValues,target,targetX,targetY,text-anchor,` +\n    `text-decoration,text-rendering,textLength,to,transform,transform-origin,` +\n    `type,u1,u2,underline-position,underline-thickness,unicode,unicode-bidi,` +\n    `unicode-range,units-per-em,v-alphabetic,v-hanging,v-ideographic,` +\n    `v-mathematical,values,vector-effect,version,vert-adv-y,vert-origin-x,` +\n    `vert-origin-y,viewBox,viewTarget,visibility,width,widths,word-spacing,` +\n    `writing-mode,x,x-height,x1,x2,xChannelSelector,xlink:actuate,xlink:arcrole,` +\n    `xlink:href,xlink:role,xlink:show,xlink:title,xlink:type,xmlns:xlink,xml:base,xml:lang,` +\n    `xml:space,y,y1,y2,yChannelSelector,z,zoomAndPan`,\n)\n\n/**\n * Generated from https://developer.mozilla.org/en-US/docs/Web/MathML/Attribute\n */\nexport const isKnownMathMLAttr: (key: string) => boolean =\n  /*@__PURE__*/ makeMap(\n    `accent,accentunder,actiontype,align,alignmentscope,altimg,altimg-height,` +\n      `altimg-valign,altimg-width,alttext,bevelled,close,columnsalign,columnlines,` +\n      `columnspan,denomalign,depth,dir,display,displaystyle,encoding,` +\n      `equalcolumns,equalrows,fence,fontstyle,fontweight,form,frame,framespacing,` +\n      `groupalign,height,href,id,indentalign,indentalignfirst,indentalignlast,` +\n      `indentshift,indentshiftfirst,indentshiftlast,indextype,justify,` +\n      `largetop,largeop,lquote,lspace,mathbackground,mathcolor,mathsize,` +\n      `mathvariant,maxsize,minlabelspacing,mode,other,overflow,position,` +\n      `rowalign,rowlines,rowspan,rquote,rspace,scriptlevel,scriptminsize,` +\n      `scriptsizemultiplier,selection,separator,separators,shift,side,` +\n      `src,stackalign,stretchy,subscriptshift,superscriptshift,symmetric,` +\n      `voffset,width,widths,xlink:href,xlink:show,xlink:type,xmlns`,\n  )\n\n/**\n * Shared between server-renderer and runtime-core hydration logic\n */\nexport function isRenderableAttrValue(value: unknown): boolean {\n  if (value == null) {\n    return false\n  }\n  const type = typeof value\n  return type === 'string' || type === 'number' || type === 'boolean'\n}\n"
  },
  {
    "path": "packages/shared/src/domTagConfig.ts",
    "content": "// These tag configs are shared between compiler-dom and runtime-dom, so they\n// must be extracted in shared to avoid creating a dependency between the two.\nimport { makeMap } from './makeMap'\n\n// https://developer.mozilla.org/en-US/docs/Web/HTML/Element\nconst HTML_TAGS =\n  'html,body,base,head,link,meta,style,title,address,article,aside,footer,' +\n  'header,hgroup,h1,h2,h3,h4,h5,h6,nav,section,div,dd,dl,dt,figcaption,' +\n  'figure,picture,hr,img,li,main,ol,p,pre,ul,a,b,abbr,bdi,bdo,br,cite,code,' +\n  'data,dfn,em,i,kbd,mark,q,rp,rt,ruby,s,samp,small,span,strong,sub,sup,' +\n  'time,u,var,wbr,area,audio,map,track,video,embed,object,param,source,' +\n  'canvas,script,noscript,del,ins,caption,col,colgroup,table,thead,tbody,td,' +\n  'th,tr,button,datalist,fieldset,form,input,label,legend,meter,optgroup,' +\n  'option,output,progress,select,textarea,details,dialog,menu,' +\n  'summary,template,blockquote,iframe,tfoot'\n\n// https://developer.mozilla.org/en-US/docs/Web/SVG/Element\nconst SVG_TAGS =\n  'svg,animate,animateMotion,animateTransform,circle,clipPath,color-profile,' +\n  'defs,desc,discard,ellipse,feBlend,feColorMatrix,feComponentTransfer,' +\n  'feComposite,feConvolveMatrix,feDiffuseLighting,feDisplacementMap,' +\n  'feDistantLight,feDropShadow,feFlood,feFuncA,feFuncB,feFuncG,feFuncR,' +\n  'feGaussianBlur,feImage,feMerge,feMergeNode,feMorphology,feOffset,' +\n  'fePointLight,feSpecularLighting,feSpotLight,feTile,feTurbulence,filter,' +\n  'foreignObject,g,hatch,hatchpath,image,line,linearGradient,marker,mask,' +\n  'mesh,meshgradient,meshpatch,meshrow,metadata,mpath,path,pattern,' +\n  'polygon,polyline,radialGradient,rect,set,solidcolor,stop,switch,symbol,' +\n  'text,textPath,title,tspan,unknown,use,view'\n\n// https://www.w3.org/TR/mathml4/ (content elements excluded)\nconst MATH_TAGS =\n  'annotation,annotation-xml,maction,maligngroup,malignmark,math,menclose,' +\n  'merror,mfenced,mfrac,mfraction,mglyph,mi,mlabeledtr,mlongdiv,' +\n  'mmultiscripts,mn,mo,mover,mpadded,mphantom,mprescripts,mroot,mrow,ms,' +\n  'mscarries,mscarry,msgroup,msline,mspace,msqrt,msrow,mstack,mstyle,msub,' +\n  'msubsup,msup,mtable,mtd,mtext,mtr,munder,munderover,none,semantics'\n\nconst VOID_TAGS =\n  'area,base,br,col,embed,hr,img,input,link,meta,param,source,track,wbr'\n\n/**\n * Compiler only.\n * Do NOT use in runtime code paths unless behind `__DEV__` flag.\n */\nexport const isHTMLTag: (key: string) => boolean =\n  /*@__PURE__*/ makeMap(HTML_TAGS)\n/**\n * Compiler only.\n * Do NOT use in runtime code paths unless behind `__DEV__` flag.\n */\nexport const isSVGTag: (key: string) => boolean =\n  /*@__PURE__*/ makeMap(SVG_TAGS)\n/**\n * Compiler only.\n * Do NOT use in runtime code paths unless behind `__DEV__` flag.\n */\nexport const isMathMLTag: (key: string) => boolean =\n  /*@__PURE__*/ makeMap(MATH_TAGS)\n/**\n * Compiler only.\n * Do NOT use in runtime code paths unless behind `__DEV__` flag.\n */\nexport const isVoidTag: (key: string) => boolean =\n  /*@__PURE__*/ makeMap(VOID_TAGS)\n"
  },
  {
    "path": "packages/shared/src/escapeHtml.ts",
    "content": "const escapeRE = /[\"'&<>]/\n\nexport function escapeHtml(string: unknown): string {\n  const str = '' + string\n  const match = escapeRE.exec(str)\n\n  if (!match) {\n    return str\n  }\n\n  let html = ''\n  let escaped: string\n  let index: number\n  let lastIndex = 0\n  for (index = match.index; index < str.length; index++) {\n    switch (str.charCodeAt(index)) {\n      case 34: // \"\n        escaped = '&quot;'\n        break\n      case 38: // &\n        escaped = '&amp;'\n        break\n      case 39: // '\n        escaped = '&#39;'\n        break\n      case 60: // <\n        escaped = '&lt;'\n        break\n      case 62: // >\n        escaped = '&gt;'\n        break\n      default:\n        continue\n    }\n\n    if (lastIndex !== index) {\n      html += str.slice(lastIndex, index)\n    }\n\n    lastIndex = index + 1\n    html += escaped\n  }\n\n  return lastIndex !== index ? html + str.slice(lastIndex, index) : html\n}\n\n// https://www.w3.org/TR/html52/syntax.html#comments\nconst commentStripRE = /^-?>|<!--|-->|--!>|<!-$/g\n\nexport function escapeHtmlComment(src: string): string {\n  return src.replace(commentStripRE, '')\n}\n\nexport const cssVarNameEscapeSymbolsRE: RegExp =\n  /[ !\"#$%&'()*+,./:;<=>?@[\\\\\\]^`{|}~]/g\n\nexport function getEscapedCssVarName(\n  key: string,\n  doubleEscape: boolean,\n): string {\n  return key.replace(cssVarNameEscapeSymbolsRE, s =>\n    doubleEscape ? (s === '\"' ? '\\\\\\\\\\\\\"' : `\\\\\\\\${s}`) : `\\\\${s}`,\n  )\n}\n"
  },
  {
    "path": "packages/shared/src/general.ts",
    "content": "import { makeMap } from './makeMap'\n\nexport const EMPTY_OBJ: { readonly [key: string]: any } = __DEV__\n  ? Object.freeze({})\n  : {}\nexport const EMPTY_ARR: readonly never[] = __DEV__ ? Object.freeze([]) : []\n\nexport const NOOP = (): void => {}\n\n/**\n * Always return false.\n */\nexport const NO = () => false\n\nexport const isOn = (key: string): boolean =>\n  key.charCodeAt(0) === 111 /* o */ &&\n  key.charCodeAt(1) === 110 /* n */ &&\n  // uppercase letter\n  (key.charCodeAt(2) > 122 || key.charCodeAt(2) < 97)\n\nexport const isModelListener = (key: string): key is `onUpdate:${string}` =>\n  key.startsWith('onUpdate:')\n\nexport const extend: typeof Object.assign = Object.assign\n\nexport const remove = <T>(arr: T[], el: T): void => {\n  const i = arr.indexOf(el)\n  if (i > -1) {\n    arr.splice(i, 1)\n  }\n}\n\nconst hasOwnProperty = Object.prototype.hasOwnProperty\nexport const hasOwn = (\n  val: object,\n  key: string | symbol,\n): key is keyof typeof val => hasOwnProperty.call(val, key)\n\nexport const isArray: typeof Array.isArray = Array.isArray\nexport const isMap = (val: unknown): val is Map<any, any> =>\n  toTypeString(val) === '[object Map]'\nexport const isSet = (val: unknown): val is Set<any> =>\n  toTypeString(val) === '[object Set]'\n\nexport const isDate = (val: unknown): val is Date =>\n  toTypeString(val) === '[object Date]'\nexport const isRegExp = (val: unknown): val is RegExp =>\n  toTypeString(val) === '[object RegExp]'\nexport const isFunction = (val: unknown): val is Function =>\n  typeof val === 'function'\nexport const isString = (val: unknown): val is string => typeof val === 'string'\nexport const isSymbol = (val: unknown): val is symbol => typeof val === 'symbol'\nexport const isObject = (val: unknown): val is Record<any, any> =>\n  val !== null && typeof val === 'object'\n\nexport const isPromise = <T = any>(val: unknown): val is Promise<T> => {\n  return (\n    (isObject(val) || isFunction(val)) &&\n    isFunction((val as any).then) &&\n    isFunction((val as any).catch)\n  )\n}\n\nexport const objectToString: typeof Object.prototype.toString =\n  Object.prototype.toString\nexport const toTypeString = (value: unknown): string =>\n  objectToString.call(value)\n\nexport const toRawType = (value: unknown): string => {\n  // extract \"RawType\" from strings like \"[object RawType]\"\n  return toTypeString(value).slice(8, -1)\n}\n\nexport const isPlainObject = (val: unknown): val is object =>\n  toTypeString(val) === '[object Object]'\n\nexport const isIntegerKey = (key: unknown): boolean =>\n  isString(key) &&\n  key !== 'NaN' &&\n  key[0] !== '-' &&\n  '' + parseInt(key, 10) === key\n\nexport const isReservedProp: (key: string) => boolean = /*@__PURE__*/ makeMap(\n  // the leading comma is intentional so empty string \"\" is also included\n  ',key,ref,ref_for,ref_key,' +\n    'onVnodeBeforeMount,onVnodeMounted,' +\n    'onVnodeBeforeUpdate,onVnodeUpdated,' +\n    'onVnodeBeforeUnmount,onVnodeUnmounted',\n)\n\nexport const isBuiltInDirective: (key: string) => boolean =\n  /*@__PURE__*/ makeMap(\n    'bind,cloak,else-if,else,for,html,if,model,on,once,pre,show,slot,text,memo',\n  )\n\nconst cacheStringFunction = <T extends (str: string) => string>(fn: T): T => {\n  const cache: Record<string, string> = Object.create(null)\n  return ((str: string) => {\n    const hit = cache[str]\n    return hit || (cache[str] = fn(str))\n  }) as T\n}\n\nconst camelizeRE = /-\\w/g\n/**\n * @private\n */\nexport const camelize: (str: string) => string = cacheStringFunction(\n  (str: string): string => {\n    return str.replace(camelizeRE, c => c.slice(1).toUpperCase())\n  },\n)\n\nconst hyphenateRE = /\\B([A-Z])/g\n/**\n * @private\n */\nexport const hyphenate: (str: string) => string = cacheStringFunction(\n  (str: string) => str.replace(hyphenateRE, '-$1').toLowerCase(),\n)\n\n/**\n * @private\n */\nexport const capitalize: <T extends string>(str: T) => Capitalize<T> =\n  cacheStringFunction(<T extends string>(str: T) => {\n    return (str.charAt(0).toUpperCase() + str.slice(1)) as Capitalize<T>\n  })\n\n/**\n * @private\n */\nexport const toHandlerKey: <T extends string>(\n  str: T,\n) => T extends '' ? '' : `on${Capitalize<T>}` = cacheStringFunction(\n  <T extends string>(str: T) => {\n    const s = str ? `on${capitalize(str)}` : ``\n    return s as T extends '' ? '' : `on${Capitalize<T>}`\n  },\n)\n\n// compare whether a value has changed, accounting for NaN.\nexport const hasChanged = (value: any, oldValue: any): boolean =>\n  !Object.is(value, oldValue)\n\nexport const invokeArrayFns = (fns: Function[], ...arg: any[]): void => {\n  for (let i = 0; i < fns.length; i++) {\n    fns[i](...arg)\n  }\n}\n\nexport const def = (\n  obj: object,\n  key: string | symbol,\n  value: any,\n  writable = false,\n): void => {\n  Object.defineProperty(obj, key, {\n    configurable: true,\n    enumerable: false,\n    writable,\n    value,\n  })\n}\n\n/**\n * \"123-foo\" will be parsed to 123\n * This is used for the .number modifier in v-model\n */\nexport const looseToNumber = (val: any): any => {\n  const n = parseFloat(val)\n  return isNaN(n) ? val : n\n}\n\n/**\n * Only concerns number-like strings\n * \"123-foo\" will be returned as-is\n */\nexport const toNumber = (val: any): any => {\n  const n = isString(val) ? Number(val) : NaN\n  return isNaN(n) ? val : n\n}\n\n// for typeof global checks without @types/node\ndeclare var global: {}\n\nlet _globalThis: any\nexport const getGlobalThis = (): any => {\n  return (\n    _globalThis ||\n    (_globalThis =\n      typeof globalThis !== 'undefined'\n        ? globalThis\n        : typeof self !== 'undefined'\n          ? self\n          : typeof window !== 'undefined'\n            ? window\n            : typeof global !== 'undefined'\n              ? global\n              : {})\n  )\n}\n\nconst identRE = /^[_$a-zA-Z\\xA0-\\uFFFF][_$a-zA-Z0-9\\xA0-\\uFFFF]*$/\n\nexport function genPropsAccessExp(name: string): string {\n  return identRE.test(name)\n    ? `__props.${name}`\n    : `__props[${JSON.stringify(name)}]`\n}\n\nexport function genCacheKey(source: string, options: any): string {\n  return (\n    source +\n    JSON.stringify(options, (_, val) =>\n      typeof val === 'function' ? val.toString() : val,\n    )\n  )\n}\n"
  },
  {
    "path": "packages/shared/src/globalsAllowList.ts",
    "content": "import { makeMap } from './makeMap'\n\nconst GLOBALS_ALLOWED =\n  'Infinity,undefined,NaN,isFinite,isNaN,parseFloat,parseInt,decodeURI,' +\n  'decodeURIComponent,encodeURI,encodeURIComponent,Math,Number,Date,Array,' +\n  'Object,Boolean,String,RegExp,Map,Set,JSON,Intl,BigInt,console,Error,Symbol'\n\nexport const isGloballyAllowed: (key: string) => boolean =\n  /*@__PURE__*/ makeMap(GLOBALS_ALLOWED)\n\n/** @deprecated use `isGloballyAllowed` instead */\nexport const isGloballyWhitelisted: (key: string) => boolean = isGloballyAllowed\n"
  },
  {
    "path": "packages/shared/src/index.ts",
    "content": "export { makeMap } from './makeMap'\nexport * from './general'\nexport * from './patchFlags'\nexport * from './shapeFlags'\nexport * from './slotFlags'\nexport * from './globalsAllowList'\nexport * from './codeframe'\nexport * from './normalizeProp'\nexport * from './domTagConfig'\nexport * from './domAttrConfig'\nexport * from './escapeHtml'\nexport * from './looseEqual'\nexport * from './toDisplayString'\nexport * from './typeUtils'\nexport * from './cssVars'\n"
  },
  {
    "path": "packages/shared/src/looseEqual.ts",
    "content": "import { isArray, isDate, isObject, isSymbol } from './general'\n\nfunction looseCompareArrays(a: any[], b: any[]) {\n  if (a.length !== b.length) return false\n  let equal = true\n  for (let i = 0; equal && i < a.length; i++) {\n    equal = looseEqual(a[i], b[i])\n  }\n  return equal\n}\n\nexport function looseEqual(a: any, b: any): boolean {\n  if (a === b) return true\n  let aValidType = isDate(a)\n  let bValidType = isDate(b)\n  if (aValidType || bValidType) {\n    return aValidType && bValidType ? a.getTime() === b.getTime() : false\n  }\n  aValidType = isSymbol(a)\n  bValidType = isSymbol(b)\n  if (aValidType || bValidType) {\n    return a === b\n  }\n  aValidType = isArray(a)\n  bValidType = isArray(b)\n  if (aValidType || bValidType) {\n    return aValidType && bValidType ? looseCompareArrays(a, b) : false\n  }\n  aValidType = isObject(a)\n  bValidType = isObject(b)\n  if (aValidType || bValidType) {\n    if (!aValidType || !bValidType) {\n      return false\n    }\n    const aKeysCount = Object.keys(a).length\n    const bKeysCount = Object.keys(b).length\n    if (aKeysCount !== bKeysCount) {\n      return false\n    }\n    for (const key in a) {\n      const aHasKey = a.hasOwnProperty(key)\n      const bHasKey = b.hasOwnProperty(key)\n      if (\n        (aHasKey && !bHasKey) ||\n        (!aHasKey && bHasKey) ||\n        !looseEqual(a[key], b[key])\n      ) {\n        return false\n      }\n    }\n  }\n  return String(a) === String(b)\n}\n\nexport function looseIndexOf(arr: any[], val: any): number {\n  return arr.findIndex(item => looseEqual(item, val))\n}\n"
  },
  {
    "path": "packages/shared/src/makeMap.ts",
    "content": "/**\n * Make a map and return a function for checking if a key\n * is in that map.\n * IMPORTANT: all calls of this function must be prefixed with\n * \\/\\*#\\_\\_PURE\\_\\_\\*\\/\n * So that rollup can tree-shake them if necessary.\n */\n\n/*@__NO_SIDE_EFFECTS__*/\nexport function makeMap(str: string): (key: string) => boolean {\n  const map = Object.create(null)\n  for (const key of str.split(',')) map[key] = 1\n  return val => val in map\n}\n"
  },
  {
    "path": "packages/shared/src/normalizeProp.ts",
    "content": "import { hyphenate, isArray, isObject, isString } from './general'\n\nexport type NormalizedStyle = Record<string, string | number>\n\nexport function normalizeStyle(\n  value: unknown,\n): NormalizedStyle | string | undefined {\n  if (isArray(value)) {\n    const res: NormalizedStyle = {}\n    for (let i = 0; i < value.length; i++) {\n      const item = value[i]\n      const normalized = isString(item)\n        ? parseStringStyle(item)\n        : (normalizeStyle(item) as NormalizedStyle)\n      if (normalized) {\n        for (const key in normalized) {\n          res[key] = normalized[key]\n        }\n      }\n    }\n    return res\n  } else if (isString(value) || isObject(value)) {\n    return value\n  }\n}\n\nconst listDelimiterRE = /;(?![^(]*\\))/g\nconst propertyDelimiterRE = /:([^]+)/\nconst styleCommentRE = /\\/\\*[^]*?\\*\\//g\n\nexport function parseStringStyle(cssText: string): NormalizedStyle {\n  const ret: NormalizedStyle = {}\n  cssText\n    .replace(styleCommentRE, '')\n    .split(listDelimiterRE)\n    .forEach(item => {\n      if (item) {\n        const tmp = item.split(propertyDelimiterRE)\n        tmp.length > 1 && (ret[tmp[0].trim()] = tmp[1].trim())\n      }\n    })\n  return ret\n}\n\nexport function stringifyStyle(\n  styles: NormalizedStyle | string | undefined,\n): string {\n  if (!styles) return ''\n  if (isString(styles)) return styles\n\n  let ret = ''\n  for (const key in styles) {\n    const value = styles[key]\n    if (isString(value) || typeof value === 'number') {\n      const normalizedKey = key.startsWith(`--`) ? key : hyphenate(key)\n      // only render valid values\n      ret += `${normalizedKey}:${value};`\n    }\n  }\n  return ret\n}\n\nexport function normalizeClass(value: unknown): string {\n  let res = ''\n  if (isString(value)) {\n    res = value\n  } else if (isArray(value)) {\n    for (let i = 0; i < value.length; i++) {\n      const normalized = normalizeClass(value[i])\n      if (normalized) {\n        res += normalized + ' '\n      }\n    }\n  } else if (isObject(value)) {\n    for (const name in value) {\n      if (value[name]) {\n        res += name + ' '\n      }\n    }\n  }\n  return res.trim()\n}\n\nexport function normalizeProps(\n  props: Record<string, any> | null,\n): Record<string, any> | null {\n  if (!props) return null\n  let { class: klass, style } = props\n  if (klass && !isString(klass)) {\n    props.class = normalizeClass(klass)\n  }\n  if (style) {\n    props.style = normalizeStyle(style)\n  }\n  return props\n}\n"
  },
  {
    "path": "packages/shared/src/patchFlags.ts",
    "content": "/**\n * Patch flags are optimization hints generated by the compiler.\n * when a block with dynamicChildren is encountered during diff, the algorithm\n * enters \"optimized mode\". In this mode, we know that the vdom is produced by\n * a render function generated by the compiler, so the algorithm only needs to\n * handle updates explicitly marked by these patch flags.\n *\n * Patch flags can be combined using the | bitwise operator and can be checked\n * using the & operator, e.g.\n *\n * ```js\n * const flag = TEXT | CLASS\n * if (flag & TEXT) { ... }\n * ```\n *\n * Check the `patchElement` function in '../../runtime-core/src/renderer.ts' to see how the\n * flags are handled during diff.\n */\nexport enum PatchFlags {\n  /**\n   * Indicates an element with dynamic textContent (children fast path)\n   */\n  TEXT = 1,\n\n  /**\n   * Indicates an element with dynamic class binding.\n   */\n  CLASS = 1 << 1,\n\n  /**\n   * Indicates an element with dynamic style\n   * The compiler pre-compiles static string styles into static objects\n   * + detects and hoists inline static objects\n   * e.g. `style=\"color: red\"` and `:style=\"{ color: 'red' }\"` both get hoisted\n   * as:\n   * ```js\n   * const style = { color: 'red' }\n   * render() { return e('div', { style }) }\n   * ```\n   */\n  STYLE = 1 << 2,\n\n  /**\n   * Indicates an element that has non-class/style dynamic props.\n   * Can also be on a component that has any dynamic props (includes\n   * class/style). when this flag is present, the vnode also has a dynamicProps\n   * array that contains the keys of the props that may change so the runtime\n   * can diff them faster (without having to worry about removed props)\n   */\n  PROPS = 1 << 3,\n\n  /**\n   * Indicates an element with props with dynamic keys. When keys change, a full\n   * diff is always needed to remove the old key. This flag is mutually\n   * exclusive with CLASS, STYLE and PROPS.\n   */\n  FULL_PROPS = 1 << 4,\n\n  /**\n   * Indicates an element that requires props hydration\n   * (but not necessarily patching)\n   * e.g. event listeners & v-bind with prop modifier\n   */\n  NEED_HYDRATION = 1 << 5,\n\n  /**\n   * Indicates a fragment whose children order doesn't change.\n   */\n  STABLE_FRAGMENT = 1 << 6,\n\n  /**\n   * Indicates a fragment with keyed or partially keyed children\n   */\n  KEYED_FRAGMENT = 1 << 7,\n\n  /**\n   * Indicates a fragment with unkeyed children.\n   */\n  UNKEYED_FRAGMENT = 1 << 8,\n\n  /**\n   * Indicates an element that only needs non-props patching, e.g. ref or\n   * directives (onVnodeXXX hooks). since every patched vnode checks for refs\n   * and onVnodeXXX hooks, it simply marks the vnode so that a parent block\n   * will track it.\n   */\n  NEED_PATCH = 1 << 9,\n\n  /**\n   * Indicates a component with dynamic slots (e.g. slot that references a v-for\n   * iterated value, or dynamic slot names).\n   * Components with this flag are always force updated.\n   */\n  DYNAMIC_SLOTS = 1 << 10,\n\n  /**\n   * Indicates a fragment that was created only because the user has placed\n   * comments at the root level of a template. This is a dev-only flag since\n   * comments are stripped in production.\n   */\n  DEV_ROOT_FRAGMENT = 1 << 11,\n\n  /**\n   * SPECIAL FLAGS -------------------------------------------------------------\n   * Special flags are negative integers. They are never matched against using\n   * bitwise operators (bitwise matching should only happen in branches where\n   * patchFlag > 0), and are mutually exclusive. When checking for a special\n   * flag, simply check patchFlag === FLAG.\n   */\n\n  /**\n   * Indicates a cached static vnode. This is also a hint for hydration to skip\n   * the entire sub tree since static content never needs to be updated.\n   */\n  CACHED = -1,\n  /**\n   * A special flag that indicates that the diffing algorithm should bail out\n   * of optimized mode. For example, on block fragments created by renderSlot()\n   * when encountering non-compiler generated slots (i.e. manually written\n   * render functions, which should always be fully diffed)\n   * OR manually cloneVNodes\n   */\n  BAIL = -2,\n}\n\n/**\n * dev only flag -> name mapping\n */\nexport const PatchFlagNames: Record<PatchFlags, string> = {\n  [PatchFlags.TEXT]: `TEXT`,\n  [PatchFlags.CLASS]: `CLASS`,\n  [PatchFlags.STYLE]: `STYLE`,\n  [PatchFlags.PROPS]: `PROPS`,\n  [PatchFlags.FULL_PROPS]: `FULL_PROPS`,\n  [PatchFlags.NEED_HYDRATION]: `NEED_HYDRATION`,\n  [PatchFlags.STABLE_FRAGMENT]: `STABLE_FRAGMENT`,\n  [PatchFlags.KEYED_FRAGMENT]: `KEYED_FRAGMENT`,\n  [PatchFlags.UNKEYED_FRAGMENT]: `UNKEYED_FRAGMENT`,\n  [PatchFlags.NEED_PATCH]: `NEED_PATCH`,\n  [PatchFlags.DYNAMIC_SLOTS]: `DYNAMIC_SLOTS`,\n  [PatchFlags.DEV_ROOT_FRAGMENT]: `DEV_ROOT_FRAGMENT`,\n  [PatchFlags.CACHED]: `CACHED`,\n  [PatchFlags.BAIL]: `BAIL`,\n}\n"
  },
  {
    "path": "packages/shared/src/shapeFlags.ts",
    "content": "export enum ShapeFlags {\n  ELEMENT = 1,\n  FUNCTIONAL_COMPONENT = 1 << 1,\n  STATEFUL_COMPONENT = 1 << 2,\n  TEXT_CHILDREN = 1 << 3,\n  ARRAY_CHILDREN = 1 << 4,\n  SLOTS_CHILDREN = 1 << 5,\n  TELEPORT = 1 << 6,\n  SUSPENSE = 1 << 7,\n  COMPONENT_SHOULD_KEEP_ALIVE = 1 << 8,\n  COMPONENT_KEPT_ALIVE = 1 << 9,\n  COMPONENT = ShapeFlags.STATEFUL_COMPONENT | ShapeFlags.FUNCTIONAL_COMPONENT,\n}\n"
  },
  {
    "path": "packages/shared/src/slotFlags.ts",
    "content": "export enum SlotFlags {\n  /**\n   * Stable slots that only reference slot props or context state. The slot\n   * can fully capture its own dependencies so when passed down the parent won't\n   * need to force the child to update.\n   */\n  STABLE = 1,\n  /**\n   * Slots that reference scope variables (v-for or an outer slot prop), or\n   * has conditional structure (v-if, v-for). The parent will need to force\n   * the child to update because the slot does not fully capture its dependencies.\n   */\n  DYNAMIC = 2,\n  /**\n   * `<slot/>` being forwarded into a child component. Whether the parent needs\n   * to update the child is dependent on what kind of slots the parent itself\n   * received. This has to be refined at runtime, when the child's vnode\n   * is being created (in `normalizeChildren`)\n   */\n  FORWARDED = 3,\n}\n\n/**\n * Dev only\n */\nexport const slotFlagsText: Record<SlotFlags, string> = {\n  [SlotFlags.STABLE]: 'STABLE',\n  [SlotFlags.DYNAMIC]: 'DYNAMIC',\n  [SlotFlags.FORWARDED]: 'FORWARDED',\n}\n"
  },
  {
    "path": "packages/shared/src/toDisplayString.ts",
    "content": "// enums are compiled away via custom transform so no real dependency here\nimport { ReactiveFlags } from '@vue/reactivity'\nimport {\n  isArray,\n  isFunction,\n  isMap,\n  isObject,\n  isPlainObject,\n  isSet,\n  isString,\n  isSymbol,\n  objectToString,\n} from './general'\n\n// can't use isRef here since @vue/shared has no deps\nconst isRef = (val: any): val is { value: unknown } => {\n  return !!(val && val[ReactiveFlags.IS_REF] === true)\n}\n\n/**\n * For converting {{ interpolation }} values to displayed strings.\n * @private\n */\nexport const toDisplayString = (val: unknown): string => {\n  return isString(val)\n    ? val\n    : val == null\n      ? ''\n      : isArray(val) ||\n          (isObject(val) &&\n            (val.toString === objectToString || !isFunction(val.toString)))\n        ? isRef(val)\n          ? toDisplayString(val.value)\n          : JSON.stringify(val, replacer, 2)\n        : String(val)\n}\n\nconst replacer = (_key: string, val: unknown): any => {\n  if (isRef(val)) {\n    return replacer(_key, val.value)\n  } else if (isMap(val)) {\n    return {\n      [`Map(${val.size})`]: [...val.entries()].reduce(\n        (entries, [key, val], i) => {\n          entries[stringifySymbol(key, i) + ' =>'] = val\n          return entries\n        },\n        {} as Record<string, any>,\n      ),\n    }\n  } else if (isSet(val)) {\n    return {\n      [`Set(${val.size})`]: [...val.values()].map(v => stringifySymbol(v)),\n    }\n  } else if (isSymbol(val)) {\n    return stringifySymbol(val)\n  } else if (isObject(val) && !isArray(val) && !isPlainObject(val)) {\n    // native elements\n    return String(val)\n  }\n  return val\n}\n\nconst stringifySymbol = (v: unknown, i: number | string = ''): any =>\n  // Symbol.description in es2019+ so we need to cast here to pass\n  // the lib: es2016 check\n  isSymbol(v) ? `Symbol(${(v as any).description ?? i})` : v\n"
  },
  {
    "path": "packages/shared/src/typeUtils.ts",
    "content": "export type Prettify<T> = { [K in keyof T]: T[K] } & {}\n\nexport type UnionToIntersection<U> = (\n  U extends any ? (k: U) => void : never\n) extends (k: infer I) => void\n  ? I\n  : never\n\n// make keys required but keep undefined values\nexport type LooseRequired<T> = { [P in keyof (T & Required<T>)]: T[P] }\n\n// If the type T accepts type \"any\", output type Y, otherwise output type N.\n// https://stackoverflow.com/questions/49927523/disallow-call-with-any/49928360#49928360\nexport type IfAny<T, Y, N> = 0 extends 1 & T ? Y : N\n\nexport type IsKeyValues<T, K = string> = IfAny<\n  T,\n  false,\n  T extends object ? (keyof T extends K ? true : false) : false\n>\n\n/**\n * Utility for extracting the parameters from a function overload (for typed emits)\n * https://github.com/microsoft/TypeScript/issues/32164#issuecomment-1146737709\n */\nexport type OverloadParameters<T extends (...args: any[]) => any> = Parameters<\n  OverloadUnion<T>\n>\n\ntype OverloadProps<TOverload> = Pick<TOverload, keyof TOverload>\n\ntype OverloadUnionRecursive<\n  TOverload,\n  TPartialOverload = unknown,\n> = TOverload extends (...args: infer TArgs) => infer TReturn\n  ? TPartialOverload extends TOverload\n    ? never\n    :\n        | OverloadUnionRecursive<\n            TPartialOverload & TOverload,\n            TPartialOverload &\n              ((...args: TArgs) => TReturn) &\n              OverloadProps<TOverload>\n          >\n        | ((...args: TArgs) => TReturn)\n  : never\n\ntype OverloadUnion<TOverload extends (...args: any[]) => any> = Exclude<\n  OverloadUnionRecursive<(() => never) & TOverload>,\n  TOverload extends () => never ? never : () => never\n>\n"
  },
  {
    "path": "packages/vue/LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2018-present, Yuxi (Evan) You\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "packages/vue/README.md",
    "content": "# vue\n\n## Which dist file to use?\n\n### From CDN or without a Bundler\n\n- **`vue(.runtime).global(.prod).js`**:\n  - For direct use via `<script src=\"...\">` in the browser. Exposes the `Vue` global.\n  - Note that global builds are not [UMD](https://github.com/umdjs/umd) builds. They are built as [IIFEs](https://developer.mozilla.org/en-US/docs/Glossary/IIFE) and are only meant for direct use via `<script src=\"...\">`.\n  - In-browser template compilation:\n    - **`vue.global.js`** is the \"full\" build that includes both the compiler and the runtime so it supports compiling templates on the fly.\n    - **`vue.runtime.global.js`** contains only the runtime and requires templates to be pre-compiled during a build step.\n  - Inlines all Vue core internal packages - i.e. it's a single file with no dependencies on other files. This means you **must** import everything from this file and this file only to ensure you are getting the same instance of code.\n  - Contains hard-coded prod/dev branches, and the prod build is pre-minified. Use the `*.prod.js` files for production.\n\n- **`vue(.runtime).esm-browser(.prod).js`**:\n  - For usage via native ES modules imports (in browser via `<script type=\"module\">`).\n  - Shares the same runtime compilation, dependency inlining and hard-coded prod/dev behavior with the global build.\n\n### With a Bundler\n\n- **`vue(.runtime).esm-bundler.js`**:\n  - For use with bundlers like `webpack`, `rollup` and `parcel`.\n  - Leaves prod/dev branches with `process.env.NODE_ENV` guards (must be replaced by bundler)\n  - Does not ship minified builds (to be done together with the rest of the code after bundling)\n  - Imports dependencies (e.g. `@vue/runtime-core`, `@vue/compiler-core`)\n    - Imported dependencies are also `esm-bundler` builds and will in turn import their dependencies (e.g. `@vue/runtime-core` imports `@vue/reactivity`)\n    - This means you **can** install/import these deps individually without ending up with different instances of these dependencies, but you must make sure they all resolve to the same version.\n  - In-browser template compilation:\n    - **`vue.runtime.esm-bundler.js` (default)** is runtime only, and requires all templates to be pre-compiled. This is the default entry for bundlers (via `module` field in `package.json`) because when using a bundler templates are typically pre-compiled (e.g. in `*.vue` files).\n    - **`vue.esm-bundler.js`**: includes the runtime compiler. Use this if you are using a bundler but still want runtime template compilation (e.g. in-DOM templates or templates via inline JavaScript strings). You will need to configure your bundler to alias `vue` to this file.\n\n#### Bundler Build Feature Flags\n\n[Detailed Reference on vuejs.org](https://vuejs.org/api/compile-time-flags.html)\n\n`esm-bundler` builds of Vue expose global feature flags that can be overwritten at compile time:\n\n- `__VUE_OPTIONS_API__`\n  - Default: `true`\n  - Enable / disable Options API support\n\n- `__VUE_PROD_DEVTOOLS__`\n  - Default: `false`\n  - Enable / disable devtools support in production\n\n- `__VUE_PROD_HYDRATION_MISMATCH_DETAILS__`\n  - Default: `false`\n  - Enable / disable detailed warnings for hydration mismatches in production\n\nThe build will work without configuring these flags, however it is **strongly recommended** to properly configure them in order to get proper tree-shaking in the final bundle.\n\n### For Server-Side Rendering\n\n- **`vue.cjs(.prod).js`**:\n  - For use in Node.js server-side rendering via `require()`.\n  - If you bundle your app with webpack with `target: 'node'` and properly externalize `vue`, this is the build that will be loaded.\n  - The dev/prod files are pre-built, but the appropriate file is automatically required based on `process.env.NODE_ENV`.\n"
  },
  {
    "path": "packages/vue/__tests__/customElementCasing.spec.ts",
    "content": "import { createApp } from '../src'\n\n// https://github.com/vuejs/docs/pull/1890\n// https://github.com/vuejs/core/issues/5401\n// https://github.com/vuejs/docs/issues/1708\ntest('custom element event casing', () => {\n  customElements.define(\n    'custom-event-casing',\n    class Foo extends HTMLElement {\n      connectedCallback() {\n        this.dispatchEvent(new Event('camelCase'))\n        this.dispatchEvent(new Event('CAPScase'))\n        this.dispatchEvent(new Event('PascalCase'))\n      }\n    },\n  )\n\n  const container = document.createElement('div')\n  document.body.appendChild(container)\n\n  const handler = vi.fn()\n  const handler2 = vi.fn()\n  createApp({\n    template: `\n    <custom-event-casing\n      @camelCase=\"handler\"\n      @CAPScase=\"handler\"\n      @PascalCase=\"handler\"\n      v-on=\"{\n        camelCase: handler2,\n        CAPScase: handler2,\n        PascalCase: handler2\n      }\" />`,\n    methods: {\n      handler,\n      handler2,\n    },\n  }).mount(container)\n\n  expect(handler).toHaveBeenCalledTimes(3)\n  expect(handler2).toHaveBeenCalledTimes(3)\n})\n"
  },
  {
    "path": "packages/vue/__tests__/e2e/Transition.spec.ts",
    "content": "import type { ElementHandle } from 'puppeteer'\nimport { E2E_TIMEOUT, setupPuppeteer } from './e2eUtils'\nimport path from 'node:path'\nimport { Transition, createApp, h, nextTick, ref } from 'vue'\n\ndescribe('e2e: Transition', () => {\n  const { page, html, classList, style, isVisible, timeout, nextFrame, click } =\n    setupPuppeteer()\n  const baseUrl = `file://${path.resolve(__dirname, './transition.html')}`\n\n  const duration = process.env.CI ? 200 : 50\n  const buffer = process.env.CI ? 50 : 20\n\n  const transitionFinish = (time = duration) => timeout(time + buffer)\n\n  const classWhenTransitionStart = () =>\n    page().evaluate(() => {\n      ;(document.querySelector('#toggleBtn') as any)!.click()\n      return Promise.resolve().then(() => {\n        return document.querySelector('#container div')!.className.split(/\\s+/g)\n      })\n    })\n\n  beforeEach(async () => {\n    await page().goto(baseUrl)\n    await page().waitForSelector('#app')\n  })\n\n  describe('transition with v-if', () => {\n    test(\n      'basic transition',\n      async () => {\n        await page().evaluate(() => {\n          const { createApp, ref } = (window as any).Vue\n          createApp({\n            template: `\n            <div id=\"container\">\n              <transition>\n                <div v-if=\"toggle\" class=\"test\">content</div>\n              </transition>\n            </div>\n            <button id=\"toggleBtn\" @click=\"click\">button</button>\n          `,\n            setup: () => {\n              const toggle = ref(true)\n              const click = () => (toggle.value = !toggle.value)\n              return { toggle, click }\n            },\n          }).mount('#app')\n        })\n        expect(await html('#container')).toBe('<div class=\"test\">content</div>')\n\n        // leave\n        expect(await classWhenTransitionStart()).toStrictEqual([\n          'test',\n          'v-leave-from',\n          'v-leave-active',\n        ])\n        await nextFrame()\n        expect(await classList('.test')).toStrictEqual([\n          'test',\n          'v-leave-active',\n          'v-leave-to',\n        ])\n        await transitionFinish()\n        expect(await html('#container')).toBe('<!--v-if-->')\n\n        // enter\n        expect(await classWhenTransitionStart()).toStrictEqual([\n          'test',\n          'v-enter-from',\n          'v-enter-active',\n        ])\n        await nextFrame()\n        expect(await classList('.test')).toStrictEqual([\n          'test',\n          'v-enter-active',\n          'v-enter-to',\n        ])\n        await transitionFinish()\n        expect(await html('#container')).toBe('<div class=\"test\">content</div>')\n      },\n      E2E_TIMEOUT,\n    )\n\n    test(\n      'named transition',\n      async () => {\n        await page().evaluate(() => {\n          const { createApp, ref } = (window as any).Vue\n          createApp({\n            template: `\n              <div id=\"container\">\n                <transition name=\"test\">\n                  <div v-if=\"toggle\" class=\"test\">content</div>\n                </transition>\n              </div>\n              <button id=\"toggleBtn\" @click=\"click\">button</button>\n            `,\n            setup: () => {\n              const toggle = ref(true)\n              const click = () => (toggle.value = !toggle.value)\n              return { toggle, click }\n            },\n          }).mount('#app')\n        })\n        expect(await html('#container')).toBe('<div class=\"test\">content</div>')\n\n        // leave\n        expect(await classWhenTransitionStart()).toStrictEqual([\n          'test',\n          'test-leave-from',\n          'test-leave-active',\n        ])\n        await nextFrame()\n        expect(await classList('.test')).toStrictEqual([\n          'test',\n          'test-leave-active',\n          'test-leave-to',\n        ])\n        await transitionFinish()\n        expect(await html('#container')).toBe('<!--v-if-->')\n\n        // enter\n        expect(await classWhenTransitionStart()).toStrictEqual([\n          'test',\n          'test-enter-from',\n          'test-enter-active',\n        ])\n        await nextFrame()\n        expect(await classList('.test')).toStrictEqual([\n          'test',\n          'test-enter-active',\n          'test-enter-to',\n        ])\n        await transitionFinish()\n        expect(await html('#container')).toBe('<div class=\"test\">content</div>')\n      },\n      E2E_TIMEOUT,\n    )\n\n    test(\n      'custom transition classes',\n      async () => {\n        await page().evaluate(() => {\n          const { createApp, ref } = (window as any).Vue\n          createApp({\n            template: `\n          <div id=\"container\">\n            <transition enter-from-class=\"hello-from\"\n              enter-active-class=\"hello-active\"\n              enter-to-class=\"hello-to\"\n              leave-from-class=\"bye-from\"\n              leave-active-class=\"bye-active\"\n              leave-to-class=\"bye-to\">\n              <div v-if=\"toggle\" class=\"test\">content</div>\n            </transition>\n          </div>\n          <button id=\"toggleBtn\" @click=\"click\">button</button>\n          `,\n            setup: () => {\n              const toggle = ref(true)\n              const click = () => (toggle.value = !toggle.value)\n              return { toggle, click }\n            },\n          }).mount('#app')\n        })\n        expect(await html('#container')).toBe('<div class=\"test\">content</div>')\n\n        // leave\n        expect(await classWhenTransitionStart()).toStrictEqual([\n          'test',\n          'bye-from',\n          'bye-active',\n        ])\n        await nextFrame()\n        expect(await classList('.test')).toStrictEqual([\n          'test',\n          'bye-active',\n          'bye-to',\n        ])\n        await transitionFinish()\n        expect(await html('#container')).toBe('<!--v-if-->')\n\n        // enter\n        expect(await classWhenTransitionStart()).toStrictEqual([\n          'test',\n          'hello-from',\n          'hello-active',\n        ])\n        await nextFrame()\n        expect(await classList('.test')).toStrictEqual([\n          'test',\n          'hello-active',\n          'hello-to',\n        ])\n        await transitionFinish()\n        expect(await html('#container')).toBe('<div class=\"test\">content</div>')\n      },\n      E2E_TIMEOUT,\n    )\n\n    test(\n      'transition with dynamic name',\n      async () => {\n        await page().evaluate(() => {\n          const { createApp, ref } = (window as any).Vue\n          createApp({\n            template: `\n          <div id=\"container\">\n            <transition :name=\"name\">\n              <div v-if=\"toggle\" class=\"test\">content</div>\n            </transition>\n          </div>\n          <button id=\"toggleBtn\" @click=\"click\">button</button>\n          <button id=\"changeNameBtn\" @click=\"changeName\">button</button>\n          `,\n            setup: () => {\n              const name = ref('test')\n              const toggle = ref(true)\n              const click = () => (toggle.value = !toggle.value)\n              const changeName = () => (name.value = 'changed')\n              return { toggle, click, name, changeName }\n            },\n          }).mount('#app')\n        })\n        expect(await html('#container')).toBe('<div class=\"test\">content</div>')\n\n        // leave\n        expect(await classWhenTransitionStart()).toStrictEqual([\n          'test',\n          'test-leave-from',\n          'test-leave-active',\n        ])\n        await nextFrame()\n        expect(await classList('.test')).toStrictEqual([\n          'test',\n          'test-leave-active',\n          'test-leave-to',\n        ])\n        await transitionFinish()\n        expect(await html('#container')).toBe('<!--v-if-->')\n\n        // enter\n        await page().evaluate(() => {\n          ;(document.querySelector('#changeNameBtn') as any).click()\n        })\n        expect(await classWhenTransitionStart()).toStrictEqual([\n          'test',\n          'changed-enter-from',\n          'changed-enter-active',\n        ])\n        await nextFrame()\n        expect(await classList('.test')).toStrictEqual([\n          'test',\n          'changed-enter-active',\n          'changed-enter-to',\n        ])\n        await transitionFinish()\n        expect(await html('#container')).toBe('<div class=\"test\">content</div>')\n      },\n      E2E_TIMEOUT,\n    )\n\n    test(\n      'transition events without appear',\n      async () => {\n        const beforeLeaveSpy = vi.fn()\n        const onLeaveSpy = vi.fn()\n        const afterLeaveSpy = vi.fn()\n        const beforeEnterSpy = vi.fn()\n        const onEnterSpy = vi.fn()\n        const afterEnterSpy = vi.fn()\n\n        await page().exposeFunction('onLeaveSpy', onLeaveSpy)\n        await page().exposeFunction('onEnterSpy', onEnterSpy)\n        await page().exposeFunction('beforeLeaveSpy', beforeLeaveSpy)\n        await page().exposeFunction('beforeEnterSpy', beforeEnterSpy)\n        await page().exposeFunction('afterLeaveSpy', afterLeaveSpy)\n        await page().exposeFunction('afterEnterSpy', afterEnterSpy)\n\n        await page().evaluate(() => {\n          const {\n            beforeEnterSpy,\n            onEnterSpy,\n            afterEnterSpy,\n            beforeLeaveSpy,\n            onLeaveSpy,\n            afterLeaveSpy,\n          } = window as any\n          const { createApp, ref } = (window as any).Vue\n          createApp({\n            template: `\n            <div id=\"container\">\n              <transition\n                name=\"test\"\n                @before-enter=\"beforeEnterSpy()\"\n                @enter=\"onEnterSpy()\"\n                @after-enter=\"afterEnterSpy()\"\n                @before-leave=\"beforeLeaveSpy()\"\n                @leave=\"onLeaveSpy()\"\n                @after-leave=\"afterLeaveSpy()\">\n                <div v-if=\"toggle\" class=\"test\">content</div>\n              </transition>\n            </div>\n            <button id=\"toggleBtn\" @click=\"click\">button</button>\n          `,\n            setup: () => {\n              const toggle = ref(true)\n              const click = () => (toggle.value = !toggle.value)\n              return {\n                toggle,\n                click,\n                beforeEnterSpy,\n                onEnterSpy,\n                afterEnterSpy,\n                beforeLeaveSpy,\n                onLeaveSpy,\n                afterLeaveSpy,\n              }\n            },\n          }).mount('#app')\n        })\n        expect(await html('#container')).toBe('<div class=\"test\">content</div>')\n\n        // leave\n        expect(await classWhenTransitionStart()).toStrictEqual([\n          'test',\n          'test-leave-from',\n          'test-leave-active',\n        ])\n        expect(beforeLeaveSpy).toBeCalled()\n        expect(onLeaveSpy).toBeCalled()\n        expect(afterLeaveSpy).not.toBeCalled()\n        await nextFrame()\n        expect(await classList('.test')).toStrictEqual([\n          'test',\n          'test-leave-active',\n          'test-leave-to',\n        ])\n        expect(afterLeaveSpy).not.toBeCalled()\n        await transitionFinish()\n        expect(await html('#container')).toBe('<!--v-if-->')\n        expect(afterLeaveSpy).toBeCalled()\n\n        // enter\n        expect(await classWhenTransitionStart()).toStrictEqual([\n          'test',\n          'test-enter-from',\n          'test-enter-active',\n        ])\n        expect(beforeEnterSpy).toBeCalled()\n        expect(onEnterSpy).toBeCalled()\n        expect(afterEnterSpy).not.toBeCalled()\n        await nextFrame()\n        expect(await classList('.test')).toStrictEqual([\n          'test',\n          'test-enter-active',\n          'test-enter-to',\n        ])\n        expect(afterEnterSpy).not.toBeCalled()\n        await transitionFinish()\n        expect(await html('#container')).toBe('<div class=\"test\">content</div>')\n        expect(afterEnterSpy).toBeCalled()\n      },\n      E2E_TIMEOUT,\n    )\n\n    test(\n      'events with arguments',\n      async () => {\n        const beforeLeaveSpy = vi.fn()\n        const onLeaveSpy = vi.fn()\n        const afterLeaveSpy = vi.fn()\n        const beforeEnterSpy = vi.fn()\n        const onEnterSpy = vi.fn()\n        const afterEnterSpy = vi.fn()\n\n        await page().exposeFunction('onLeaveSpy', onLeaveSpy)\n        await page().exposeFunction('onEnterSpy', onEnterSpy)\n        await page().exposeFunction('beforeLeaveSpy', beforeLeaveSpy)\n        await page().exposeFunction('beforeEnterSpy', beforeEnterSpy)\n        await page().exposeFunction('afterLeaveSpy', afterLeaveSpy)\n        await page().exposeFunction('afterEnterSpy', afterEnterSpy)\n\n        await page().evaluate(() => {\n          const {\n            beforeEnterSpy,\n            onEnterSpy,\n            afterEnterSpy,\n            beforeLeaveSpy,\n            onLeaveSpy,\n            afterLeaveSpy,\n          } = window as any\n          const { createApp, ref } = (window as any).Vue\n          createApp({\n            template: `\n            <div id=\"container\">\n              <transition\n                :css=\"false\"\n                name=\"test\"\n                @before-enter=\"beforeEnterSpy\"\n                @enter=\"onEnterSpy\"\n                @after-enter=\"afterEnterSpy\"\n                @before-leave=\"beforeLeaveSpy\"\n                @leave=\"onLeaveSpy\"\n                @after-leave=\"afterLeaveSpy\">\n                <div v-if=\"toggle\" class=\"test\">content</div>\n              </transition>\n            </div>\n            <button id=\"toggleBtn\" @click=\"click\">button</button>\n          `,\n            setup: () => {\n              const toggle = ref(true)\n              const click = () => (toggle.value = !toggle.value)\n              return {\n                toggle,\n                click,\n                beforeEnterSpy(el: Element) {\n                  beforeEnterSpy()\n                  el.classList.add('before-enter')\n                },\n                onEnterSpy(el: Element, done: () => void) {\n                  onEnterSpy()\n                  el.classList.add('enter')\n                  setTimeout(done, 200)\n                },\n                afterEnterSpy(el: Element) {\n                  afterEnterSpy()\n                  el.classList.add('after-enter')\n                },\n                beforeLeaveSpy(el: HTMLDivElement) {\n                  beforeLeaveSpy()\n                  el.classList.add('before-leave')\n                },\n                onLeaveSpy(el: HTMLDivElement, done: () => void) {\n                  onLeaveSpy()\n                  el.classList.add('leave')\n                  setTimeout(done, 200)\n                },\n                afterLeaveSpy: (el: Element) => {\n                  afterLeaveSpy()\n                },\n              }\n            },\n          }).mount('#app')\n        })\n        expect(await html('#container')).toBe('<div class=\"test\">content</div>')\n\n        // leave\n        await click('#toggleBtn')\n        expect(beforeLeaveSpy).toBeCalled()\n        expect(onLeaveSpy).toBeCalled()\n        expect(afterLeaveSpy).not.toBeCalled()\n        expect(await classList('.test')).toStrictEqual([\n          'test',\n          'before-leave',\n          'leave',\n        ])\n\n        await timeout(200 + buffer)\n        expect(afterLeaveSpy).toBeCalled()\n        expect(await html('#container')).toBe('<!--v-if-->')\n\n        // enter\n        await click('#toggleBtn')\n        expect(beforeEnterSpy).toBeCalled()\n        expect(onEnterSpy).toBeCalled()\n        expect(afterEnterSpy).not.toBeCalled()\n        expect(await classList('.test')).toStrictEqual([\n          'test',\n          'before-enter',\n          'enter',\n        ])\n\n        await timeout(200 + buffer)\n        expect(afterEnterSpy).toBeCalled()\n        expect(await html('#container')).toBe(\n          '<div class=\"test before-enter enter after-enter\">content</div>',\n        )\n      },\n      E2E_TIMEOUT,\n    )\n\n    test('onEnterCancelled', async () => {\n      const enterCancelledSpy = vi.fn()\n\n      await page().exposeFunction('enterCancelledSpy', enterCancelledSpy)\n\n      await page().evaluate(() => {\n        const { enterCancelledSpy } = window as any\n        const { createApp, ref } = (window as any).Vue\n        createApp({\n          template: `\n            <div id=\"container\">\n              <transition\n                name=\"test\"\n                @enter-cancelled=\"enterCancelledSpy()\">\n                <div v-if=\"toggle\" class=\"test\">content</div>\n              </transition>\n            </div>\n            <button id=\"toggleBtn\" @click=\"click\">button</button>\n          `,\n          setup: () => {\n            const toggle = ref(false)\n            const click = () => (toggle.value = !toggle.value)\n            return {\n              toggle,\n              click,\n              enterCancelledSpy,\n            }\n          },\n        }).mount('#app')\n      })\n      expect(await html('#container')).toBe('<!--v-if-->')\n\n      // enter\n      expect(await classWhenTransitionStart()).toStrictEqual([\n        'test',\n        'test-enter-from',\n        'test-enter-active',\n      ])\n      await nextFrame()\n      expect(await classList('.test')).toStrictEqual([\n        'test',\n        'test-enter-active',\n        'test-enter-to',\n      ])\n\n      // cancel (leave)\n      expect(await classWhenTransitionStart()).toStrictEqual([\n        'test',\n        'test-leave-from',\n        'test-leave-active',\n      ])\n      expect(enterCancelledSpy).toBeCalled()\n      await nextFrame()\n      expect(await classList('.test')).toStrictEqual([\n        'test',\n        'test-leave-active',\n        'test-leave-to',\n      ])\n      await transitionFinish()\n      expect(await html('#container')).toBe('<!--v-if-->')\n    })\n\n    test(\n      'transition on appear',\n      async () => {\n        const appearClass = await page().evaluate(async () => {\n          const { createApp, ref } = (window as any).Vue\n          createApp({\n            template: `\n              <div id=\"container\">\n                <transition name=\"test\"\n                            appear\n                            appear-from-class=\"test-appear-from\"\n                            appear-to-class=\"test-appear-to\"\n                            appear-active-class=\"test-appear-active\">\n                  <div v-if=\"toggle\" class=\"test\">content</div>\n                </transition>\n              </div>\n              <button id=\"toggleBtn\" @click=\"click\">button</button>\n            `,\n            setup: () => {\n              const toggle = ref(true)\n              const click = () => (toggle.value = !toggle.value)\n              return { toggle, click }\n            },\n          }).mount('#app')\n          return Promise.resolve().then(() => {\n            return document.querySelector('.test')!.className.split(/\\s+/g)\n          })\n        })\n        // appear\n        expect(appearClass).toStrictEqual([\n          'test',\n          'test-appear-from',\n          'test-appear-active',\n        ])\n        await nextFrame()\n        expect(await classList('.test')).toStrictEqual([\n          'test',\n          'test-appear-active',\n          'test-appear-to',\n        ])\n        await transitionFinish()\n        expect(await html('#container')).toBe('<div class=\"test\">content</div>')\n\n        // leave\n        expect(await classWhenTransitionStart()).toStrictEqual([\n          'test',\n          'test-leave-from',\n          'test-leave-active',\n        ])\n        await nextFrame()\n        expect(await classList('.test')).toStrictEqual([\n          'test',\n          'test-leave-active',\n          'test-leave-to',\n        ])\n        await transitionFinish()\n        expect(await html('#container')).toBe('<!--v-if-->')\n\n        // enter\n        expect(await classWhenTransitionStart()).toStrictEqual([\n          'test',\n          'test-enter-from',\n          'test-enter-active',\n        ])\n        await nextFrame()\n        expect(await classList('.test')).toStrictEqual([\n          'test',\n          'test-enter-active',\n          'test-enter-to',\n        ])\n        await transitionFinish()\n        expect(await html('#container')).toBe('<div class=\"test\">content</div>')\n      },\n      E2E_TIMEOUT,\n    )\n\n    test(\n      'transition events with appear',\n      async () => {\n        const onLeaveSpy = vi.fn()\n        const onEnterSpy = vi.fn()\n        const onAppearSpy = vi.fn()\n        const beforeLeaveSpy = vi.fn()\n        const beforeEnterSpy = vi.fn()\n        const beforeAppearSpy = vi.fn()\n        const afterLeaveSpy = vi.fn()\n        const afterEnterSpy = vi.fn()\n        const afterAppearSpy = vi.fn()\n\n        await page().exposeFunction('onLeaveSpy', onLeaveSpy)\n        await page().exposeFunction('onEnterSpy', onEnterSpy)\n        await page().exposeFunction('onAppearSpy', onAppearSpy)\n        await page().exposeFunction('beforeLeaveSpy', beforeLeaveSpy)\n        await page().exposeFunction('beforeEnterSpy', beforeEnterSpy)\n        await page().exposeFunction('beforeAppearSpy', beforeAppearSpy)\n        await page().exposeFunction('afterLeaveSpy', afterLeaveSpy)\n        await page().exposeFunction('afterEnterSpy', afterEnterSpy)\n        await page().exposeFunction('afterAppearSpy', afterAppearSpy)\n\n        const appearClass = await page().evaluate(async () => {\n          const {\n            beforeAppearSpy,\n            onAppearSpy,\n            afterAppearSpy,\n            beforeEnterSpy,\n            onEnterSpy,\n            afterEnterSpy,\n            beforeLeaveSpy,\n            onLeaveSpy,\n            afterLeaveSpy,\n          } = window as any\n          const { createApp, ref } = (window as any).Vue\n          createApp({\n            template: `\n              <div id=\"container\">\n                <transition\n                  name=\"test\"\n                  appear\n                  appear-from-class=\"test-appear-from\"\n                  appear-to-class=\"test-appear-to\"\n                  appear-active-class=\"test-appear-active\"\n                  @before-enter=\"beforeEnterSpy()\"\n                  @enter=\"onEnterSpy()\"\n                  @after-enter=\"afterEnterSpy()\"\n                  @before-leave=\"beforeLeaveSpy()\"\n                  @leave=\"onLeaveSpy()\"\n                  @after-leave=\"afterLeaveSpy()\"\n                  @before-appear=\"beforeAppearSpy()\"\n                  @appear=\"onAppearSpy()\"\n                  @after-appear=\"afterAppearSpy()\">\n                  <div v-if=\"toggle\" class=\"test\">content</div>\n                </transition>\n              </div>\n              <button id=\"toggleBtn\" @click=\"click\">button</button>\n            `,\n            setup: () => {\n              const toggle = ref(true)\n              const click = () => (toggle.value = !toggle.value)\n              return {\n                toggle,\n                click,\n                beforeAppearSpy,\n                onAppearSpy,\n                afterAppearSpy,\n                beforeEnterSpy,\n                onEnterSpy,\n                afterEnterSpy,\n                beforeLeaveSpy,\n                onLeaveSpy,\n                afterLeaveSpy,\n              }\n            },\n          }).mount('#app')\n          return Promise.resolve().then(() => {\n            return document.querySelector('.test')!.className.split(/\\s+/g)\n          })\n        })\n        // appear\n        expect(appearClass).toStrictEqual([\n          'test',\n          'test-appear-from',\n          'test-appear-active',\n        ])\n        expect(beforeAppearSpy).toBeCalled()\n        expect(onAppearSpy).toBeCalled()\n        expect(afterAppearSpy).not.toBeCalled()\n        await nextFrame()\n        expect(await classList('.test')).toStrictEqual([\n          'test',\n          'test-appear-active',\n          'test-appear-to',\n        ])\n        expect(afterAppearSpy).not.toBeCalled()\n        await transitionFinish()\n        expect(await html('#container')).toBe('<div class=\"test\">content</div>')\n        expect(afterAppearSpy).toBeCalled()\n\n        expect(beforeEnterSpy).not.toBeCalled()\n        expect(onEnterSpy).not.toBeCalled()\n        expect(afterEnterSpy).not.toBeCalled()\n\n        // leave\n        expect(await classWhenTransitionStart()).toStrictEqual([\n          'test',\n          'test-leave-from',\n          'test-leave-active',\n        ])\n        expect(beforeLeaveSpy).toBeCalled()\n        expect(onLeaveSpy).toBeCalled()\n        expect(afterLeaveSpy).not.toBeCalled()\n        await nextFrame()\n        expect(await classList('.test')).toStrictEqual([\n          'test',\n          'test-leave-active',\n          'test-leave-to',\n        ])\n        expect(afterLeaveSpy).not.toBeCalled()\n        await transitionFinish()\n        expect(await html('#container')).toBe('<!--v-if-->')\n        expect(afterLeaveSpy).toBeCalled()\n\n        // enter\n        expect(await classWhenTransitionStart()).toStrictEqual([\n          'test',\n          'test-enter-from',\n          'test-enter-active',\n        ])\n        expect(beforeEnterSpy).toBeCalled()\n        expect(onEnterSpy).toBeCalled()\n        expect(afterEnterSpy).not.toBeCalled()\n        await nextFrame()\n        expect(await classList('.test')).toStrictEqual([\n          'test',\n          'test-enter-active',\n          'test-enter-to',\n        ])\n        expect(afterEnterSpy).not.toBeCalled()\n        await transitionFinish()\n        expect(await html('#container')).toBe('<div class=\"test\">content</div>')\n        expect(afterEnterSpy).toBeCalled()\n      },\n      E2E_TIMEOUT,\n    )\n\n    test(\n      'css: false',\n      async () => {\n        const onBeforeEnterSpy = vi.fn()\n        const onEnterSpy = vi.fn()\n        const onAfterEnterSpy = vi.fn()\n        const onBeforeLeaveSpy = vi.fn()\n        const onLeaveSpy = vi.fn()\n        const onAfterLeaveSpy = vi.fn()\n\n        await page().exposeFunction('onBeforeEnterSpy', onBeforeEnterSpy)\n        await page().exposeFunction('onEnterSpy', onEnterSpy)\n        await page().exposeFunction('onAfterEnterSpy', onAfterEnterSpy)\n        await page().exposeFunction('onBeforeLeaveSpy', onBeforeLeaveSpy)\n        await page().exposeFunction('onLeaveSpy', onLeaveSpy)\n        await page().exposeFunction('onAfterLeaveSpy', onAfterLeaveSpy)\n\n        await page().evaluate(() => {\n          const {\n            onBeforeEnterSpy,\n            onEnterSpy,\n            onAfterEnterSpy,\n            onBeforeLeaveSpy,\n            onLeaveSpy,\n            onAfterLeaveSpy,\n          } = window as any\n          const { createApp, ref } = (window as any).Vue\n          createApp({\n            template: `\n            <div id=\"container\">\n              <transition\n                :css=\"false\"\n                name=\"test\"\n                @before-enter=\"onBeforeEnterSpy()\"\n                @enter=\"onEnterSpy()\"\n                @after-enter=\"onAfterEnterSpy()\"\n                @before-leave=\"onBeforeLeaveSpy()\"\n                @leave=\"onLeaveSpy()\"\n                @after-leave=\"onAfterLeaveSpy()\">\n                <div v-if=\"toggle\" class=\"test\">content</div>\n              </transition>\n            </div>\n            <button id=\"toggleBtn\" @click=\"click\"></button>\n          `,\n            setup: () => {\n              const toggle = ref(true)\n              const click = () => (toggle.value = !toggle.value)\n              return {\n                toggle,\n                click,\n                onBeforeEnterSpy,\n                onEnterSpy,\n                onAfterEnterSpy,\n                onBeforeLeaveSpy,\n                onLeaveSpy,\n                onAfterLeaveSpy,\n              }\n            },\n          }).mount('#app')\n        })\n        expect(await html('#container')).toBe('<div class=\"test\">content</div>')\n\n        // leave\n        await click('#toggleBtn')\n        expect(onBeforeLeaveSpy).toBeCalled()\n        expect(onLeaveSpy).toBeCalled()\n        expect(onAfterLeaveSpy).toBeCalled()\n        expect(await html('#container')).toBe('<!--v-if-->')\n        // enter\n        await classWhenTransitionStart()\n        expect(onBeforeEnterSpy).toBeCalled()\n        expect(onEnterSpy).toBeCalled()\n        expect(onAfterEnterSpy).toBeCalled()\n        expect(await html('#container')).toBe('<div class=\"test\">content</div>')\n      },\n      E2E_TIMEOUT,\n    )\n\n    test(\n      'no transition detected',\n      async () => {\n        await page().evaluate(() => {\n          const { createApp, ref } = (window as any).Vue\n          createApp({\n            template: `\n            <div id=\"container\">\n              <transition name=\"noop\">\n                <div v-if=\"toggle\">content</div>\n              </transition>\n            </div>\n            <button id=\"toggleBtn\" @click=\"click\">button</button>\n          `,\n            setup: () => {\n              const toggle = ref(true)\n              const click = () => (toggle.value = !toggle.value)\n              return { toggle, click }\n            },\n          }).mount('#app')\n        })\n        expect(await html('#container')).toBe('<div>content</div>')\n\n        // leave\n        expect(await classWhenTransitionStart()).toStrictEqual([\n          'noop-leave-from',\n          'noop-leave-active',\n        ])\n        await nextFrame()\n        expect(await html('#container')).toBe('<!--v-if-->')\n\n        // enter\n        expect(await classWhenTransitionStart()).toStrictEqual([\n          'noop-enter-from',\n          'noop-enter-active',\n        ])\n        await nextFrame()\n        expect(await html('#container')).toBe('<div class=\"\">content</div>')\n      },\n      E2E_TIMEOUT,\n    )\n\n    test(\n      'animations',\n      async () => {\n        await page().evaluate(() => {\n          const { createApp, ref } = (window as any).Vue\n          createApp({\n            template: `\n              <div id=\"container\">\n                <transition name=\"test-anim\">\n                  <div v-if=\"toggle\">content</div>\n                </transition>\n              </div>\n              <button id=\"toggleBtn\" @click=\"click\">button</button>\n            `,\n            setup: () => {\n              const toggle = ref(true)\n              const click = () => (toggle.value = !toggle.value)\n              return { toggle, click }\n            },\n          }).mount('#app')\n        })\n        expect(await html('#container')).toBe('<div>content</div>')\n\n        // leave\n        expect(await classWhenTransitionStart()).toStrictEqual([\n          'test-anim-leave-from',\n          'test-anim-leave-active',\n        ])\n        await nextFrame()\n        expect(await classList('#container div')).toStrictEqual([\n          'test-anim-leave-active',\n          'test-anim-leave-to',\n        ])\n        await transitionFinish(duration * 2)\n        expect(await html('#container')).toBe('<!--v-if-->')\n\n        // enter\n        expect(await classWhenTransitionStart()).toStrictEqual([\n          'test-anim-enter-from',\n          'test-anim-enter-active',\n        ])\n        await nextFrame()\n        expect(await classList('#container div')).toStrictEqual([\n          'test-anim-enter-active',\n          'test-anim-enter-to',\n        ])\n        await transitionFinish()\n        expect(await html('#container')).toBe('<div class=\"\">content</div>')\n      },\n      E2E_TIMEOUT,\n    )\n\n    test(\n      'explicit transition type',\n      async () => {\n        await page().evaluate(() => {\n          const { createApp, ref } = (window as any).Vue\n          createApp({\n            template: `\n              <div id=\"container\"><transition name=\"test-anim-long\" type=\"animation\"><div v-if=\"toggle\">content</div></transition></div>\n              <button id=\"toggleBtn\" @click=\"click\">button</button>\n            `,\n            setup: () => {\n              const toggle = ref(true)\n              const click = () => (toggle.value = !toggle.value)\n              return { toggle, click }\n            },\n          }).mount('#app')\n        })\n        expect(await html('#container')).toBe('<div>content</div>')\n\n        // leave\n        expect(await classWhenTransitionStart()).toStrictEqual([\n          'test-anim-long-leave-from',\n          'test-anim-long-leave-active',\n        ])\n        await nextFrame()\n        expect(await classList('#container div')).toStrictEqual([\n          'test-anim-long-leave-active',\n          'test-anim-long-leave-to',\n        ])\n\n        if (!process.env.CI) {\n          await new Promise(r => {\n            setTimeout(r, duration - buffer)\n          })\n          expect(await classList('#container div')).toStrictEqual([\n            'test-anim-long-leave-active',\n            'test-anim-long-leave-to',\n          ])\n        }\n\n        await transitionFinish(duration * 2)\n        expect(await html('#container')).toBe('<!--v-if-->')\n\n        // enter\n        expect(await classWhenTransitionStart()).toStrictEqual([\n          'test-anim-long-enter-from',\n          'test-anim-long-enter-active',\n        ])\n        await nextFrame()\n        expect(await classList('#container div')).toStrictEqual([\n          'test-anim-long-enter-active',\n          'test-anim-long-enter-to',\n        ])\n\n        if (!process.env.CI) {\n          await new Promise(r => {\n            setTimeout(r, duration - buffer)\n          })\n          expect(await classList('#container div')).toStrictEqual([\n            'test-anim-long-enter-active',\n            'test-anim-long-enter-to',\n          ])\n        }\n\n        await transitionFinish(duration * 2)\n        expect(await html('#container')).toBe('<div class=\"\">content</div>')\n      },\n      E2E_TIMEOUT,\n    )\n\n    test(\n      'transition on SVG elements',\n      async () => {\n        await page().evaluate(() => {\n          const { createApp, ref } = (window as any).Vue\n          createApp({\n            template: `\n              <svg id=\"container\">\n                <transition name=\"test\">\n                  <circle v-if=\"toggle\" cx=\"0\" cy=\"0\" r=\"10\" class=\"test\"></circle>\n                </transition>\n              </svg>\n              <button id=\"toggleBtn\" @click=\"click\">button</button>\n            `,\n            setup: () => {\n              const toggle = ref(true)\n              const click = () => (toggle.value = !toggle.value)\n              return { toggle, click }\n            },\n          }).mount('#app')\n        })\n        expect(await html('#container')).toBe(\n          '<circle cx=\"0\" cy=\"0\" r=\"10\" class=\"test\"></circle>',\n        )\n\n        const svgTransitionStart = () =>\n          page().evaluate(() => {\n            document.querySelector('button')!.click()\n            return Promise.resolve().then(() => {\n              return document\n                .querySelector('.test')!\n                .getAttribute('class')!\n                .split(/\\s+/g)\n            })\n          })\n\n        // leave\n        expect(await svgTransitionStart()).toStrictEqual([\n          'test',\n          'test-leave-from',\n          'test-leave-active',\n        ])\n        await nextFrame()\n        expect(await classList('.test')).toStrictEqual([\n          'test',\n          'test-leave-active',\n          'test-leave-to',\n        ])\n        await transitionFinish()\n        expect(await html('#container')).toBe('<!--v-if-->')\n\n        // enter\n        expect(await svgTransitionStart()).toStrictEqual([\n          'test',\n          'test-enter-from',\n          'test-enter-active',\n        ])\n        await nextFrame()\n        expect(await classList('.test')).toStrictEqual([\n          'test',\n          'test-enter-active',\n          'test-enter-to',\n        ])\n        await transitionFinish()\n        expect(await html('#container')).toBe(\n          '<circle cx=\"0\" cy=\"0\" r=\"10\" class=\"test\"></circle>',\n        )\n      },\n      E2E_TIMEOUT,\n    )\n\n    test(\n      'custom transition higher-order component',\n      async () => {\n        await page().evaluate(() => {\n          const { createApp, ref, h, Transition } = (window as any).Vue\n          createApp({\n            template: `\n              <div id=\"container\"><my-transition><div v-if=\"toggle\" class=\"test\">content</div></my-transition></div>\n              <button id=\"toggleBtn\" @click=\"click\">button</button>\n            `,\n            components: {\n              'my-transition': (props: any, { slots }: any) => {\n                return h(Transition, { name: 'test' }, slots)\n              },\n            },\n            setup: () => {\n              const toggle = ref(true)\n              const click = () => (toggle.value = !toggle.value)\n              return { toggle, click }\n            },\n          }).mount('#app')\n        })\n        expect(await html('#container')).toBe('<div class=\"test\">content</div>')\n\n        // leave\n        expect(await classWhenTransitionStart()).toStrictEqual([\n          'test',\n          'test-leave-from',\n          'test-leave-active',\n        ])\n        await nextFrame()\n        expect(await classList('.test')).toStrictEqual([\n          'test',\n          'test-leave-active',\n          'test-leave-to',\n        ])\n        await transitionFinish()\n        expect(await html('#container')).toBe('<!--v-if-->')\n\n        // enter\n        expect(await classWhenTransitionStart()).toStrictEqual([\n          'test',\n          'test-enter-from',\n          'test-enter-active',\n        ])\n        await nextFrame()\n        expect(await classList('.test')).toStrictEqual([\n          'test',\n          'test-enter-active',\n          'test-enter-to',\n        ])\n        await transitionFinish()\n        expect(await html('#container')).toBe('<div class=\"test\">content</div>')\n      },\n      E2E_TIMEOUT,\n    )\n\n    test(\n      'transition on child components with empty root node',\n      async () => {\n        await page().evaluate(() => {\n          const { createApp, ref } = (window as any).Vue\n          createApp({\n            template: `\n              <div id=\"container\">\n                <transition name=\"test\">\n                  <component class=\"test\" :is=\"view\"></component>\n                </transition>\n              </div>\n              <button id=\"toggleBtn\" @click=\"click\">button</button>\n              <button id=\"changeViewBtn\" @click=\"change\">button</button>\n            `,\n            components: {\n              one: {\n                template: '<div v-if=\"false\">one</div>',\n              },\n              two: {\n                template: '<div>two</div>',\n              },\n            },\n            setup: () => {\n              const toggle = ref(true)\n              const view = ref('one')\n              const click = () => (toggle.value = !toggle.value)\n              const change = () =>\n                (view.value = view.value === 'one' ? 'two' : 'one')\n              return { toggle, click, change, view }\n            },\n          }).mount('#app')\n        })\n        expect(await html('#container')).toBe('<!--v-if-->')\n\n        // change view -> 'two'\n        await page().evaluate(() => {\n          ;(document.querySelector('#changeViewBtn') as any)!.click()\n        })\n        // enter\n        expect(await classWhenTransitionStart()).toStrictEqual([\n          'test',\n          'test-enter-from',\n          'test-enter-active',\n        ])\n        await nextFrame()\n        expect(await classList('.test')).toStrictEqual([\n          'test',\n          'test-enter-active',\n          'test-enter-to',\n        ])\n        await transitionFinish()\n        expect(await html('#container')).toBe('<div class=\"test\">two</div>')\n\n        // change view -> 'one'\n        await page().evaluate(() => {\n          ;(document.querySelector('#changeViewBtn') as any)!.click()\n        })\n        // leave\n        expect(await classWhenTransitionStart()).toStrictEqual([\n          'test',\n          'test-leave-from',\n          'test-leave-active',\n        ])\n        await nextFrame()\n        expect(await classList('.test')).toStrictEqual([\n          'test',\n          'test-leave-active',\n          'test-leave-to',\n        ])\n        await transitionFinish()\n        expect(await html('#container')).toBe('<!--v-if-->')\n      },\n      E2E_TIMEOUT,\n    )\n\n    // issue https://github.com/vuejs/core/issues/7649\n    test(\n      'transition with v-if at component root-level',\n      async () => {\n        await page().evaluate(() => {\n          const { createApp, ref } = (window as any).Vue\n          createApp({\n            template: `\n              <div id=\"container\">\n                <transition name=\"test\" mode=\"out-in\">\n                  <component class=\"test\" :is=\"view\"></component>\n                </transition>\n              </div>\n              <button id=\"toggleBtn\" @click=\"click\">button</button>\n              <button id=\"changeViewBtn\" @click=\"change\">button</button>\n            `,\n            components: {\n              one: {\n                template: '<div v-if=\"false\">one</div>',\n              },\n              two: {\n                template: '<div>two</div>',\n              },\n            },\n            setup: () => {\n              const toggle = ref(true)\n              const view = ref('one')\n              const click = () => (toggle.value = !toggle.value)\n              const change = () =>\n                (view.value = view.value === 'one' ? 'two' : 'one')\n              return { toggle, click, change, view }\n            },\n          }).mount('#app')\n        })\n        expect(await html('#container')).toBe('<!--v-if-->')\n\n        // change view -> 'two'\n        await page().evaluate(() => {\n          ;(document.querySelector('#changeViewBtn') as any)!.click()\n        })\n        // enter\n        expect(await classWhenTransitionStart()).toStrictEqual([\n          'test',\n          'test-enter-from',\n          'test-enter-active',\n        ])\n        await nextFrame()\n        expect(await classList('.test')).toStrictEqual([\n          'test',\n          'test-enter-active',\n          'test-enter-to',\n        ])\n        await transitionFinish()\n        expect(await html('#container')).toBe('<div class=\"test\">two</div>')\n\n        // change view -> 'one'\n        await page().evaluate(() => {\n          ;(document.querySelector('#changeViewBtn') as any)!.click()\n        })\n        // leave\n        expect(await classWhenTransitionStart()).toStrictEqual([\n          'test',\n          'test-leave-from',\n          'test-leave-active',\n        ])\n        await nextFrame()\n        expect(await classList('.test')).toStrictEqual([\n          'test',\n          'test-leave-active',\n          'test-leave-to',\n        ])\n        await transitionFinish()\n        expect(await html('#container')).toBe('<!--v-if-->')\n      },\n      E2E_TIMEOUT,\n    )\n\n    // #3716\n    test(\n      'wrapping transition + fallthrough attrs',\n      async () => {\n        await page().evaluate(() => {\n          const { createApp, ref } = (window as any).Vue\n          createApp({\n            components: {\n              'my-transition': {\n                template: `\n                  <transition foo=\"1\" name=\"test\">\n                    <slot></slot>\n                  </transition>\n                `,\n              },\n            },\n            template: `\n            <div id=\"container\">\n              <my-transition>\n                <div v-if=\"toggle\">content</div>\n              </my-transition>\n            </div>\n            <button id=\"toggleBtn\" @click=\"click\">button</button>\n          `,\n            setup: () => {\n              const toggle = ref(true)\n              const click = () => (toggle.value = !toggle.value)\n              return { toggle, click }\n            },\n          }).mount('#app')\n        })\n        expect(await html('#container')).toBe('<div foo=\"1\">content</div>')\n\n        await click('#toggleBtn')\n        // toggle again before leave finishes\n        await nextTick()\n        await click('#toggleBtn')\n\n        await transitionFinish()\n        expect(await html('#container')).toBe(\n          '<div foo=\"1\" class=\"\">content</div>',\n        )\n      },\n      E2E_TIMEOUT,\n    )\n\n    // #11061\n    test(\n      'transition + fallthrough attrs (in-out mode)',\n      async () => {\n        const beforeLeaveSpy = vi.fn()\n        const onLeaveSpy = vi.fn()\n        const afterLeaveSpy = vi.fn()\n        const beforeEnterSpy = vi.fn()\n        const onEnterSpy = vi.fn()\n        const afterEnterSpy = vi.fn()\n\n        await page().exposeFunction('onLeaveSpy', onLeaveSpy)\n        await page().exposeFunction('onEnterSpy', onEnterSpy)\n        await page().exposeFunction('beforeLeaveSpy', beforeLeaveSpy)\n        await page().exposeFunction('beforeEnterSpy', beforeEnterSpy)\n        await page().exposeFunction('afterLeaveSpy', afterLeaveSpy)\n        await page().exposeFunction('afterEnterSpy', afterEnterSpy)\n\n        await page().evaluate(() => {\n          const { onEnterSpy, onLeaveSpy } = window as any\n          const { createApp, ref } = (window as any).Vue\n          createApp({\n            components: {\n              one: {\n                template: '<div>one</div>',\n              },\n              two: {\n                template: '<div>two</div>',\n              },\n            },\n            template: `\n            <div id=\"container\">\n              <transition foo=\"1\" name=\"test\" mode=\"in-out\" \n                @before-enter=\"beforeEnterSpy()\"\n                @enter=\"onEnterSpy()\"\n                @after-enter=\"afterEnterSpy()\"\n                @before-leave=\"beforeLeaveSpy()\"\n                @leave=\"onLeaveSpy()\"\n                @after-leave=\"afterLeaveSpy()\">\n                <component :is=\"view\"></component>\n              </transition>\n            </div>\n            <button id=\"toggleBtn\" @click=\"click\">button</button>\n          `,\n            setup: () => {\n              const view = ref('one')\n              const click = () =>\n                (view.value = view.value === 'one' ? 'two' : 'one')\n              return {\n                view,\n                click,\n                beforeEnterSpy,\n                onEnterSpy,\n                afterEnterSpy,\n                beforeLeaveSpy,\n                onLeaveSpy,\n                afterLeaveSpy,\n              }\n            },\n          }).mount('#app')\n        })\n        expect(await html('#container')).toBe('<div foo=\"1\">one</div>')\n\n        // toggle\n        await click('#toggleBtn')\n        await nextTick()\n        await transitionFinish()\n        expect(beforeEnterSpy).toBeCalledTimes(1)\n        expect(onEnterSpy).toBeCalledTimes(1)\n        expect(afterEnterSpy).toBeCalledTimes(1)\n        expect(beforeLeaveSpy).toBeCalledTimes(1)\n        expect(onLeaveSpy).toBeCalledTimes(1)\n        expect(afterLeaveSpy).toBeCalledTimes(1)\n\n        expect(await html('#container')).toBe('<div foo=\"1\" class=\"\">two</div>')\n\n        // toggle back\n        await click('#toggleBtn')\n        await nextTick()\n        await transitionFinish()\n        expect(beforeEnterSpy).toBeCalledTimes(2)\n        expect(onEnterSpy).toBeCalledTimes(2)\n        expect(afterEnterSpy).toBeCalledTimes(2)\n        expect(beforeLeaveSpy).toBeCalledTimes(2)\n        expect(onLeaveSpy).toBeCalledTimes(2)\n        expect(afterLeaveSpy).toBeCalledTimes(2)\n\n        expect(await html('#container')).toBe('<div foo=\"1\" class=\"\">one</div>')\n      },\n      E2E_TIMEOUT,\n    )\n  })\n\n  describe('transition with KeepAlive', () => {\n    test(\n      'unmount innerChild (out-in mode)',\n      async () => {\n        const unmountSpy = vi.fn()\n        await page().exposeFunction('unmountSpy', unmountSpy)\n        await page().evaluate(() => {\n          const { unmountSpy } = window as any\n          const { createApp, ref, h, onUnmounted } = (window as any).Vue\n          createApp({\n            template: `\n            <div id=\"container\">\n              <transition mode=\"out-in\">\n                <KeepAlive :include=\"includeRef\">\n                  <TrueBranch v-if=\"toggle\"></TrueBranch>\n                </KeepAlive>\n              </transition>\n            </div>\n            <button id=\"toggleBtn\" @click=\"click\">button</button>\n          `,\n            components: {\n              TrueBranch: {\n                name: 'TrueBranch',\n                setup() {\n                  onUnmounted(unmountSpy)\n                  const count = ref(0)\n                  return () => h('div', count.value)\n                },\n              },\n            },\n            setup: () => {\n              const includeRef = ref(['TrueBranch'])\n              const toggle = ref(true)\n              const click = () => {\n                toggle.value = !toggle.value\n                if (toggle.value) {\n                  includeRef.value = ['TrueBranch']\n                } else {\n                  includeRef.value = []\n                }\n              }\n              return { toggle, click, unmountSpy, includeRef }\n            },\n          }).mount('#app')\n        })\n\n        await transitionFinish()\n        expect(await html('#container')).toBe('<div>0</div>')\n\n        await click('#toggleBtn')\n\n        await transitionFinish()\n        expect(await html('#container')).toBe('<!--v-if-->')\n        expect(unmountSpy).toBeCalledTimes(1)\n      },\n      E2E_TIMEOUT,\n    )\n\n    // #11775\n    test(\n      'switch child then update include (out-in mode)',\n      async () => {\n        const onUpdatedSpyA = vi.fn()\n        const onUnmountedSpyC = vi.fn()\n\n        await page().exposeFunction('onUpdatedSpyA', onUpdatedSpyA)\n        await page().exposeFunction('onUnmountedSpyC', onUnmountedSpyC)\n\n        await page().evaluate(() => {\n          const { onUpdatedSpyA, onUnmountedSpyC } = window as any\n          const { createApp, ref, shallowRef, h, onUpdated, onUnmounted } = (\n            window as any\n          ).Vue\n          createApp({\n            template: `\n            <div id=\"container\">\n              <transition mode=\"out-in\">\n                <KeepAlive :include=\"includeRef\">\n                  <component :is=\"current\" />\n                </KeepAlive>\n              </transition>\n            </div>\n            <button id=\"switchToB\" @click=\"switchToB\">switchToB</button>\n            <button id=\"switchToC\" @click=\"switchToC\">switchToC</button>\n            <button id=\"switchToA\" @click=\"switchToA\">switchToA</button>\n          `,\n            components: {\n              CompA: {\n                name: 'CompA',\n                setup() {\n                  onUpdated(onUpdatedSpyA)\n                  return () => h('div', 'CompA')\n                },\n              },\n              CompB: {\n                name: 'CompB',\n                setup() {\n                  return () => h('div', 'CompB')\n                },\n              },\n              CompC: {\n                name: 'CompC',\n                setup() {\n                  onUnmounted(onUnmountedSpyC)\n                  return () => h('div', 'CompC')\n                },\n              },\n            },\n            setup: () => {\n              const includeRef = ref(['CompA', 'CompB', 'CompC'])\n              const current = shallowRef('CompA')\n              const switchToB = () => (current.value = 'CompB')\n              const switchToC = () => (current.value = 'CompC')\n              const switchToA = () => {\n                current.value = 'CompA'\n                includeRef.value = ['CompA']\n              }\n              return { current, switchToB, switchToC, switchToA, includeRef }\n            },\n          }).mount('#app')\n        })\n\n        await transitionFinish()\n        expect(await html('#container')).toBe('<div>CompA</div>')\n\n        await click('#switchToB')\n        await nextTick()\n        await click('#switchToC')\n        await transitionFinish()\n        expect(await html('#container')).toBe('<div class=\"\">CompC</div>')\n\n        await click('#switchToA')\n        await transitionFinish()\n        expect(await html('#container')).toBe('<div class=\"\">CompA</div>')\n\n        // expect CompA only update once\n        expect(onUpdatedSpyA).toBeCalledTimes(1)\n        expect(onUnmountedSpyC).toBeCalledTimes(1)\n      },\n      E2E_TIMEOUT,\n    )\n\n    // #10827\n    test(\n      'switch and update child then update include (out-in mode)',\n      async () => {\n        const onUnmountedSpyB = vi.fn()\n        await page().exposeFunction('onUnmountedSpyB', onUnmountedSpyB)\n\n        await page().evaluate(() => {\n          const { onUnmountedSpyB } = window as any\n          const {\n            createApp,\n            ref,\n            shallowRef,\n            h,\n            provide,\n            inject,\n            onUnmounted,\n          } = (window as any).Vue\n          createApp({\n            template: `\n            <div id=\"container\">\n              <transition name=\"test-anim\" mode=\"out-in\">\n                <KeepAlive :include=\"includeRef\">\n                  <component :is=\"current\" />\n                </KeepAlive>\n              </transition>\n            </div>\n            <button id=\"switchToA\" @click=\"switchToA\">switchToA</button>\n            <button id=\"switchToB\" @click=\"switchToB\">switchToB</button>\n          `,\n            components: {\n              CompA: {\n                name: 'CompA',\n                setup() {\n                  const current = inject('current')\n                  return () => h('div', current.value)\n                },\n              },\n              CompB: {\n                name: 'CompB',\n                setup() {\n                  const current = inject('current')\n                  onUnmounted(onUnmountedSpyB)\n                  return () => h('div', current.value)\n                },\n              },\n            },\n            setup: () => {\n              const includeRef = ref(['CompA'])\n              const current = shallowRef('CompA')\n              provide('current', current)\n\n              const switchToB = () => {\n                current.value = 'CompB'\n                includeRef.value = ['CompA', 'CompB']\n              }\n              const switchToA = () => {\n                current.value = 'CompA'\n                includeRef.value = ['CompA']\n              }\n              return { current, switchToB, switchToA, includeRef }\n            },\n          }).mount('#app')\n        })\n\n        await transitionFinish()\n        expect(await html('#container')).toBe('<div>CompA</div>')\n\n        await click('#switchToB')\n        await transitionFinish()\n        await transitionFinish()\n        expect(await html('#container')).toBe('<div class=\"\">CompB</div>')\n\n        await click('#switchToA')\n        await transitionFinish()\n        await transitionFinish()\n        expect(await html('#container')).toBe('<div class=\"\">CompA</div>')\n\n        expect(onUnmountedSpyB).toBeCalledTimes(1)\n      },\n      E2E_TIMEOUT,\n    )\n\n    // #12860\n    test(\n      'unmount children',\n      async () => {\n        const unmountSpy = vi.fn()\n        let storageContainer: ElementHandle<HTMLDivElement>\n        const setStorageContainer = (container: any) =>\n          (storageContainer = container)\n        await page().exposeFunction('unmountSpy', unmountSpy)\n        await page().exposeFunction('setStorageContainer', setStorageContainer)\n        await page().evaluate(() => {\n          const { unmountSpy, setStorageContainer } = window as any\n          const { createApp, ref, h, onUnmounted, getCurrentInstance } = (\n            window as any\n          ).Vue\n          createApp({\n            template: `\n            <div id=\"container\">\n              <transition>\n                <KeepAlive :include=\"includeRef\">\n                  <TrueBranch v-if=\"toggle\"></TrueBranch>\n                </KeepAlive>\n              </transition>\n            </div>\n            <button id=\"toggleBtn\" @click=\"click\">button</button>\n          `,\n            components: {\n              TrueBranch: {\n                name: 'TrueBranch',\n                setup() {\n                  const instance = getCurrentInstance()\n                  onUnmounted(() => {\n                    unmountSpy()\n                    setStorageContainer(instance.__keepAliveStorageContainer)\n                  })\n                  const count = ref(0)\n                  return () => h('div', count.value)\n                },\n              },\n            },\n            setup: () => {\n              const includeRef = ref(['TrueBranch'])\n              const toggle = ref(true)\n              const click = () => {\n                toggle.value = !toggle.value\n                if (toggle.value) {\n                  includeRef.value = ['TrueBranch']\n                } else {\n                  includeRef.value = []\n                }\n              }\n              return { toggle, click, unmountSpy, includeRef }\n            },\n          }).mount('#app')\n        })\n\n        await transitionFinish()\n        expect(await html('#container')).toBe('<div>0</div>')\n\n        await click('#toggleBtn')\n        await transitionFinish()\n        expect(await html('#container')).toBe('<!--v-if-->')\n        expect(unmountSpy).toBeCalledTimes(1)\n        expect(await storageContainer!.evaluate(x => x.innerHTML)).toBe(``)\n      },\n      E2E_TIMEOUT,\n    )\n\n    // #13153\n    test(\n      'move kept-alive node before v-show transition leave finishes',\n      async () => {\n        await page().evaluate(() => {\n          const { createApp, ref } = (window as any).Vue\n          const show = ref(true)\n          createApp({\n            template: `\n            <div id=\"container\">\n              <KeepAlive :include=\"['Comp1', 'Comp2']\">\n                <component :is=\"state === 1 ? 'Comp1' : 'Comp2'\"/>\n              </KeepAlive>\n            </div>\n            <button id=\"toggleBtn\" @click=\"click\">button</button>\n          `,\n            setup: () => {\n              const state = ref(1)\n              const click = () => (state.value = state.value === 1 ? 2 : 1)\n              return { state, click }\n            },\n            components: {\n              Comp1: {\n                components: {\n                  Item: {\n                    name: 'Item',\n                    setup() {\n                      return { show }\n                    },\n                    template: `\n                      <Transition name=\"test\">\n                        <div v-show=\"show\" >\n                          <h2>{{ show ? \"I should show\" : \"I shouldn't show \" }}</h2>\n                        </div>\n                      </Transition>\n                    `,\n                  },\n                },\n                name: 'Comp1',\n                setup() {\n                  const toggle = () => (show.value = !show.value)\n                  return { show, toggle }\n                },\n                template: `\n                  <Item />\n                  <h2>This is page1</h2>\n                  <button id=\"changeShowBtn\" @click=\"toggle\">{{ show }}</button>\n                `,\n              },\n              Comp2: {\n                name: 'Comp2',\n                template: `<h2>This is page2</h2>`,\n              },\n            },\n          }).mount('#app')\n        })\n\n        expect(await html('#container')).toBe(\n          `<div><h2>I should show</h2></div>` +\n            `<h2>This is page1</h2>` +\n            `<button id=\"changeShowBtn\">true</button>`,\n        )\n\n        // trigger v-show transition leave\n        await click('#changeShowBtn')\n        await nextTick()\n        expect(await html('#container')).toBe(\n          `<div class=\"test-leave-from test-leave-active\"><h2>I shouldn't show </h2></div>` +\n            `<h2>This is page1</h2>` +\n            `<button id=\"changeShowBtn\">false</button>`,\n        )\n\n        // switch to page2, before leave finishes\n        // expect v-show element's display to be none\n        await click('#toggleBtn')\n        await nextTick()\n        expect(await html('#container')).toBe(\n          `<div class=\"test-leave-from test-leave-active\" style=\"display: none;\"><h2>I shouldn't show </h2></div>` +\n            `<h2>This is page2</h2>`,\n        )\n\n        // switch back to page1\n        // expect v-show element's display to be none\n        await click('#toggleBtn')\n        await nextTick()\n        expect(await html('#container')).toBe(\n          `<div class=\"test-enter-from test-enter-active\" style=\"display: none;\"><h2>I shouldn't show </h2></div>` +\n            `<h2>This is page1</h2>` +\n            `<button id=\"changeShowBtn\">false</button>`,\n        )\n\n        await transitionFinish()\n        expect(await html('#container')).toBe(\n          `<div class=\"\" style=\"display: none;\"><h2>I shouldn't show </h2></div>` +\n            `<h2>This is page1</h2>` +\n            `<button id=\"changeShowBtn\">false</button>`,\n        )\n      },\n      E2E_TIMEOUT,\n    )\n  })\n\n  describe('transition with Suspense', () => {\n    // #1583\n    test(\n      'async component transition inside Suspense',\n      async () => {\n        const onLeaveSpy = vi.fn()\n        const onEnterSpy = vi.fn()\n\n        await page().exposeFunction('onLeaveSpy', onLeaveSpy)\n        await page().exposeFunction('onEnterSpy', onEnterSpy)\n\n        await page().evaluate(() => {\n          const { onEnterSpy, onLeaveSpy } = window as any\n          const { createApp, ref, h } = (window as any).Vue\n          createApp({\n            template: `\n            <div id=\"container\">\n              <transition @enter=\"onEnterSpy()\" @leave=\"onLeaveSpy()\">\n                <Suspense>\n                  <Comp v-if=\"toggle\" class=\"test\">content</Comp>\n                </Suspense>\n              </transition>\n            </div>\n            <button id=\"toggleBtn\" @click=\"click\">button</button>\n          `,\n            components: {\n              Comp: {\n                async setup() {\n                  return () => h('div', { class: 'test' }, 'content')\n                },\n              },\n            },\n            setup: () => {\n              const toggle = ref(true)\n              const click = () => (toggle.value = !toggle.value)\n              return { toggle, click, onEnterSpy, onLeaveSpy }\n            },\n          }).mount('#app')\n        })\n\n        expect(onEnterSpy).toBeCalledTimes(1)\n        await nextFrame()\n        expect(await html('#container')).toBe(\n          '<div class=\"test v-enter-active v-enter-to\">content</div>',\n        )\n        await transitionFinish()\n        expect(await html('#container')).toBe('<div class=\"test\">content</div>')\n\n        // leave\n        expect(await classWhenTransitionStart()).toStrictEqual([\n          'test',\n          'v-leave-from',\n          'v-leave-active',\n        ])\n        expect(onLeaveSpy).toBeCalledTimes(1)\n        await nextFrame()\n        expect(await classList('.test')).toStrictEqual([\n          'test',\n          'v-leave-active',\n          'v-leave-to',\n        ])\n        await transitionFinish()\n        expect(await html('#container')).toBe('<!--v-if-->')\n\n        // enter\n        const enterClass = await page().evaluate(async () => {\n          ;(document.querySelector('#toggleBtn') as any)!.click()\n          // nextTrick for patch start\n          await Promise.resolve()\n          // nextTrick for Suspense resolve\n          await Promise.resolve()\n          // nextTrick for dom transition start\n          await Promise.resolve()\n          return document\n            .querySelector('#container div')!\n            .className.split(/\\s+/g)\n        })\n        expect(enterClass).toStrictEqual([\n          'test',\n          'v-enter-from',\n          'v-enter-active',\n        ])\n        expect(onEnterSpy).toBeCalledTimes(2)\n        await nextFrame()\n        expect(await classList('.test')).toStrictEqual([\n          'test',\n          'v-enter-active',\n          'v-enter-to',\n        ])\n        await transitionFinish()\n        expect(await html('#container')).toBe('<div class=\"test\">content</div>')\n      },\n      E2E_TIMEOUT,\n    )\n\n    // #1689\n    test(\n      'static node transition inside Suspense',\n      async () => {\n        await page().evaluate(() => {\n          const { createApp, ref } = (window as any).Vue\n          createApp({\n            template: `\n            <div id=\"container\">\n              <transition>\n                <Suspense>\n                  <div v-if=\"toggle\" class=\"test\">content</div>\n                </Suspense>\n              </transition>\n            </div>\n            <button id=\"toggleBtn\" @click=\"click\">button</button>\n          `,\n            setup: () => {\n              const toggle = ref(true)\n              const click = () => (toggle.value = !toggle.value)\n              return { toggle, click }\n            },\n          }).mount('#app')\n        })\n        expect(await html('#container')).toBe('<div class=\"test\">content</div>')\n\n        // leave\n        expect(await classWhenTransitionStart()).toStrictEqual([\n          'test',\n          'v-leave-from',\n          'v-leave-active',\n        ])\n        await nextFrame()\n        expect(await classList('.test')).toStrictEqual([\n          'test',\n          'v-leave-active',\n          'v-leave-to',\n        ])\n        await transitionFinish()\n        expect(await html('#container')).toBe('<!--v-if-->')\n\n        // enter\n        expect(await classWhenTransitionStart()).toStrictEqual([\n          'test',\n          'v-enter-from',\n          'v-enter-active',\n        ])\n        await nextFrame()\n        expect(await classList('.test')).toStrictEqual([\n          'test',\n          'v-enter-active',\n          'v-enter-to',\n        ])\n        await transitionFinish()\n        expect(await html('#container')).toBe('<div class=\"test\">content</div>')\n      },\n      E2E_TIMEOUT,\n    )\n\n    test(\n      'out-in mode with Suspense',\n      async () => {\n        const onLeaveSpy = vi.fn()\n        const onEnterSpy = vi.fn()\n\n        await page().exposeFunction('onLeaveSpy', onLeaveSpy)\n        await page().exposeFunction('onEnterSpy', onEnterSpy)\n\n        await page().evaluate(() => {\n          const { createApp, shallowRef, h } = (window as any).Vue\n          const One = {\n            async setup() {\n              return () => h('div', { class: 'test' }, 'one')\n            },\n          }\n          const Two = {\n            async setup() {\n              return () => h('div', { class: 'test' }, 'two')\n            },\n          }\n          createApp({\n            template: `\n              <div id=\"container\">\n                <transition mode=\"out-in\">\n                  <Suspense>\n                    <component :is=\"view\"/>\n                  </Suspense>\n                </transition>\n              </div>\n              <button id=\"toggleBtn\" @click=\"click\">button</button>\n            `,\n            setup: () => {\n              const view = shallowRef(One)\n              const click = () => {\n                view.value = view.value === One ? Two : One\n              }\n              return { view, click }\n            },\n          }).mount('#app')\n        })\n\n        await nextFrame()\n        expect(await html('#container')).toBe(\n          '<div class=\"test v-enter-active v-enter-to\">one</div>',\n        )\n        await transitionFinish()\n        expect(await html('#container')).toBe('<div class=\"test\">one</div>')\n\n        // leave\n        await classWhenTransitionStart()\n        await nextFrame()\n        expect(await html('#container')).toBe(\n          '<div class=\"test v-leave-active v-leave-to\">one</div>',\n        )\n        await transitionFinish()\n        await nextFrame()\n        // expect(await html('#container')).toBe(\n        //   '<div class=\"test v-enter-active v-enter-to\">two</div>'\n        // )\n        await transitionFinish()\n        expect(await html('#container')).toBe('<div class=\"test\">two</div>')\n      },\n      E2E_TIMEOUT,\n    )\n\n    // #3963\n    test(\n      'Suspense fallback should work with transition',\n      async () => {\n        await page().evaluate(() => {\n          const { createApp, shallowRef, h } = (window as any).Vue\n\n          const One = {\n            template: `<div>{{ msg }}</div>`,\n            setup() {\n              return new Promise(_resolve => {\n                // @ts-expect-error\n                window.resolve = () =>\n                  _resolve({\n                    msg: 'success',\n                  })\n              })\n            },\n          }\n\n          createApp({\n            template: `\n              <div id=\"container\">\n                <transition mode=\"out-in\">\n                  <Suspense :timeout=\"0\">\n                    <template #default>\n                      <component :is=\"view\" />\n                    </template>\n                    <template #fallback>\n                      <div>Loading...</div>\n                    </template>\n                  </Suspense>\n                </transition>\n              </div>\n              <button id=\"toggleBtn\" @click=\"click\">button</button>\n            `,\n            setup: () => {\n              const view = shallowRef(null)\n              const click = () => {\n                view.value = view.value ? null : h(One)\n              }\n              return { view, click }\n            },\n          }).mount('#app')\n        })\n\n        expect(await html('#container')).toBe('<!---->')\n\n        await click('#toggleBtn')\n        await nextFrame()\n        expect(await html('#container')).toBe('<div class=\"\">Loading...</div>')\n\n        await page().evaluate(() => {\n          // @ts-expect-error\n          window.resolve()\n        })\n\n        await transitionFinish(duration * 2)\n        expect(await html('#container')).toBe('<div class=\"\">success</div>')\n      },\n      E2E_TIMEOUT,\n    )\n\n    // #5844\n    test('children mount should be called after html changes', async () => {\n      const fooMountSpy = vi.fn()\n      const barMountSpy = vi.fn()\n\n      await page().exposeFunction('fooMountSpy', fooMountSpy)\n      await page().exposeFunction('barMountSpy', barMountSpy)\n\n      await page().evaluate(() => {\n        const { fooMountSpy, barMountSpy } = window as any\n        const { createApp, ref, h, onMounted } = (window as any).Vue\n        createApp({\n          template: `\n          <div id=\"container\">\n            <transition mode=\"out-in\">\n              <Suspense>\n                <Foo v-if=\"toggle\" />\n                <Bar v-else />\n              </Suspense>\n            </transition>\n          </div>\n          <button id=\"toggleBtn\" @click=\"click\">button</button>\n        `,\n          components: {\n            Foo: {\n              setup() {\n                const el = ref(null)\n                onMounted(() => {\n                  fooMountSpy(\n                    !!el.value,\n                    !!document.getElementById('foo'),\n                    !!document.getElementById('bar'),\n                  )\n                })\n\n                return () => h('div', { ref: el, id: 'foo' }, 'Foo')\n              },\n            },\n            Bar: {\n              setup() {\n                const el = ref(null)\n                onMounted(() => {\n                  barMountSpy(\n                    !!el.value,\n                    !!document.getElementById('foo'),\n                    !!document.getElementById('bar'),\n                  )\n                })\n\n                return () => h('div', { ref: el, id: 'bar' }, 'Bar')\n              },\n            },\n          },\n          setup: () => {\n            const toggle = ref(true)\n            const click = () => (toggle.value = !toggle.value)\n            return { toggle, click }\n          },\n        }).mount('#app')\n      })\n\n      await nextFrame()\n      expect(await html('#container')).toBe('<div id=\"foo\">Foo</div>')\n      await transitionFinish()\n\n      expect(fooMountSpy).toBeCalledTimes(1)\n      expect(fooMountSpy).toHaveBeenNthCalledWith(1, true, true, false)\n\n      await page().evaluate(async () => {\n        ;(document.querySelector('#toggleBtn') as any)!.click()\n        // nextTrick for patch start\n        await Promise.resolve()\n        // nextTrick for Suspense resolve\n        await Promise.resolve()\n        // nextTrick for dom transition start\n        await Promise.resolve()\n        return document.querySelector('#container div')!.className.split(/\\s+/g)\n      })\n\n      await nextFrame()\n      await transitionFinish()\n\n      expect(await html('#container')).toBe('<div id=\"bar\" class=\"\">Bar</div>')\n\n      expect(barMountSpy).toBeCalledTimes(1)\n      expect(barMountSpy).toHaveBeenNthCalledWith(1, true, false, true)\n    })\n\n    // #8105\n    test(\n      'trigger again when transition is not finished',\n      async () => {\n        await page().evaluate(duration => {\n          const { createApp, shallowRef, h } = (window as any).Vue\n          const One = {\n            async setup() {\n              return () => h('div', { class: 'test' }, 'one')\n            },\n          }\n          const Two = {\n            async setup() {\n              return () => h('div', { class: 'test' }, 'two')\n            },\n          }\n          createApp({\n            template: `\n            <div id=\"container\">\n              <transition name=\"test\" mode=\"out-in\" duration=\"${duration}\">\n                <Suspense>\n                  <component :is=\"view\"/>\n                </Suspense>\n              </transition>\n            </div>\n            <button id=\"toggleBtn\" @click=\"click\">button</button>\n          `,\n            setup: () => {\n              const view = shallowRef(One)\n              const click = () => {\n                view.value = view.value === One ? Two : One\n              }\n              return { view, click }\n            },\n          }).mount('#app')\n        }, duration)\n\n        await nextFrame()\n        expect(await html('#container')).toBe(\n          '<div class=\"test test-enter-active test-enter-to\">one</div>',\n        )\n\n        await transitionFinish()\n        expect(await html('#container')).toBe('<div class=\"test\">one</div>')\n\n        // trigger twice\n        classWhenTransitionStart()\n        classWhenTransitionStart()\n        await nextFrame()\n        expect(await html('#container')).toBe(\n          '<div class=\"test test-leave-active test-leave-to\">one</div>',\n        )\n\n        await transitionFinish()\n        await nextFrame()\n        expect(await html('#container')).toBe(\n          '<div class=\"test test-enter-active test-enter-to\">one</div>',\n        )\n\n        await transitionFinish()\n        await nextFrame()\n        expect(await html('#container')).toBe('<div class=\"test\">one</div>')\n      },\n      E2E_TIMEOUT,\n    )\n\n    // #9996\n    test(\n      'trigger again when transition is not finished & correctly anchor',\n      async () => {\n        await page().evaluate(duration => {\n          const { createApp, shallowRef, h } = (window as any).Vue\n          const One = {\n            async setup() {\n              return () => h('div', { class: 'test' }, 'one')\n            },\n          }\n          const Two = {\n            async setup() {\n              return () => h('div', { class: 'test' }, 'two')\n            },\n          }\n          createApp({\n            template: `\n            <div id=\"container\">\n              <div>Top</div>\n              <transition name=\"test\" mode=\"out-in\" :duration=\"${duration}\">\n                <Suspense>\n                  <component :is=\"view\"/>\n                </Suspense>\n              </transition>\n              <div>Bottom</div>\n            </div>\n            <button id=\"toggleBtn\" @click=\"click\">button</button>\n          `,\n            setup: () => {\n              const view = shallowRef(One)\n              const click = () => {\n                view.value = view.value === One ? Two : One\n              }\n              return { view, click }\n            },\n          }).mount('#app')\n        }, duration)\n\n        await nextFrame()\n        expect(await html('#container')).toBe(\n          '<div>Top</div><div class=\"test test-enter-active test-enter-to\">one</div><div>Bottom</div>',\n        )\n\n        await transitionFinish()\n        expect(await html('#container')).toBe(\n          '<div>Top</div><div class=\"test\">one</div><div>Bottom</div>',\n        )\n\n        // trigger twice\n        classWhenTransitionStart()\n        await nextFrame()\n        expect(await html('#container')).toBe(\n          '<div>Top</div><div class=\"test test-leave-active test-leave-to\">one</div><div>Bottom</div>',\n        )\n\n        await transitionFinish()\n        await nextFrame()\n        expect(await html('#container')).toBe(\n          '<div>Top</div><div class=\"test test-enter-active test-enter-to\">two</div><div>Bottom</div>',\n        )\n\n        await transitionFinish()\n        await nextFrame()\n        expect(await html('#container')).toBe(\n          '<div>Top</div><div class=\"test\">two</div><div>Bottom</div>',\n        )\n      },\n      E2E_TIMEOUT,\n    )\n\n    // #11806\n    test(\n      'switch between Async and Sync child when transition is not finished',\n      async () => {\n        await page().evaluate(() => {\n          const { createApp, shallowRef, h, nextTick } = (window as any).Vue\n          createApp({\n            template: `\n            <div id=\"container\">\n              <Transition mode=\"out-in\">\n                <Suspense>\n                  <component :is=\"view\"/>\n                </Suspense>\n              </Transition>\n            </div>\n            <button id=\"toggleBtn\" @click=\"click\">button</button>\n          `,\n            setup: () => {\n              const view = shallowRef('SyncB')\n              const click = async () => {\n                view.value = 'SyncA'\n                await nextTick()\n                view.value = 'AsyncB'\n                await nextTick()\n                view.value = 'SyncB'\n              }\n              return { view, click }\n            },\n            components: {\n              SyncA: {\n                setup() {\n                  return () => h('div', 'SyncA')\n                },\n              },\n              AsyncB: {\n                async setup() {\n                  await nextTick()\n                  return () => h('div', 'AsyncB')\n                },\n              },\n              SyncB: {\n                setup() {\n                  return () => h('div', 'SyncB')\n                },\n              },\n            },\n          }).mount('#app')\n        })\n\n        expect(await html('#container')).toBe('<div>SyncB</div>')\n\n        await click('#toggleBtn')\n        await nextFrame()\n        await transitionFinish()\n        await transitionFinish()\n        expect(await html('#container')).toBe('<div class=\"\">SyncB</div>')\n      },\n      E2E_TIMEOUT,\n    )\n  })\n\n  describe('transition with Teleport', () => {\n    test(\n      'apply transition to teleport child',\n      async () => {\n        await page().evaluate(() => {\n          const { createApp, ref, h } = (window as any).Vue\n          createApp({\n            template: `\n            <div id=\"target\"></div>\n            <div id=\"container\">\n              <transition>\n                <Teleport to=\"#target\">\n                  <!-- comment -->\n                  <Comp v-if=\"toggle\" class=\"test\">content</Comp>\n                </Teleport>\n              </transition>\n            </div>\n            <button id=\"toggleBtn\" @click=\"click\">button</button>\n          `,\n            components: {\n              Comp: {\n                setup() {\n                  return () => h('div', { class: 'test' }, 'content')\n                },\n              },\n            },\n            setup: () => {\n              const toggle = ref(false)\n              const click = () => (toggle.value = !toggle.value)\n              return { toggle, click }\n            },\n          }).mount('#app')\n        })\n\n        expect(await html('#target')).toBe('<!-- comment --><!--v-if-->')\n        expect(await html('#container')).toBe(\n          '<!--teleport start--><!--teleport end-->',\n        )\n\n        const classWhenTransitionStart = () =>\n          page().evaluate(() => {\n            ;(document.querySelector('#toggleBtn') as any)!.click()\n            return Promise.resolve().then(() => {\n              // find the class of teleported node\n              return document\n                .querySelector('#target div')!\n                .className.split(/\\s+/g)\n            })\n          })\n\n        // enter\n        expect(await classWhenTransitionStart()).toStrictEqual([\n          'test',\n          'v-enter-from',\n          'v-enter-active',\n        ])\n        await nextFrame()\n        expect(await classList('.test')).toStrictEqual([\n          'test',\n          'v-enter-active',\n          'v-enter-to',\n        ])\n        await transitionFinish()\n        expect(await html('#target')).toBe(\n          '<!-- comment --><div class=\"test\">content</div>',\n        )\n\n        // leave\n        expect(await classWhenTransitionStart()).toStrictEqual([\n          'test',\n          'v-leave-from',\n          'v-leave-active',\n        ])\n        await nextFrame()\n        expect(await classList('.test')).toStrictEqual([\n          'test',\n          'v-leave-active',\n          'v-leave-to',\n        ])\n        await transitionFinish()\n        expect(await html('#target')).toBe('<!-- comment --><!--v-if-->')\n        expect(await html('#container')).toBe(\n          '<!--teleport start--><!--teleport end-->',\n        )\n      },\n      E2E_TIMEOUT,\n    )\n  })\n\n  describe('transition with v-show', () => {\n    test(\n      'named transition with v-show',\n      async () => {\n        await page().evaluate(() => {\n          const { createApp, ref } = (window as any).Vue\n          createApp({\n            template: `\n            <div id=\"container\">\n              <transition name=\"test\">\n                <div v-show=\"toggle\" class=\"test\">content</div>\n              </transition>\n            </div>\n            <button id=\"toggleBtn\" @click=\"click\">button</button>\n          `,\n            setup: () => {\n              const toggle = ref(true)\n              const click = () => (toggle.value = !toggle.value)\n              return { toggle, click }\n            },\n          }).mount('#app')\n        })\n        expect(await html('#container')).toBe('<div class=\"test\">content</div>')\n        expect(await isVisible('.test')).toBe(true)\n\n        // leave\n        expect(await classWhenTransitionStart()).toStrictEqual([\n          'test',\n          'test-leave-from',\n          'test-leave-active',\n        ])\n        await nextFrame()\n        expect(await classList('.test')).toStrictEqual([\n          'test',\n          'test-leave-active',\n          'test-leave-to',\n        ])\n        await transitionFinish()\n        expect(await isVisible('.test')).toBe(false)\n\n        // enter\n        expect(await classWhenTransitionStart()).toStrictEqual([\n          'test',\n          'test-enter-from',\n          'test-enter-active',\n        ])\n        await nextFrame()\n        expect(await classList('.test')).toStrictEqual([\n          'test',\n          'test-enter-active',\n          'test-enter-to',\n        ])\n        await transitionFinish()\n        expect(await html('#container')).toBe(\n          '<div class=\"test\" style=\"\">content</div>',\n        )\n      },\n      E2E_TIMEOUT,\n    )\n\n    test(\n      'transition events with v-show',\n      async () => {\n        const beforeLeaveSpy = vi.fn()\n        const onLeaveSpy = vi.fn()\n        const afterLeaveSpy = vi.fn()\n        const beforeEnterSpy = vi.fn()\n        const onEnterSpy = vi.fn()\n        const afterEnterSpy = vi.fn()\n\n        await page().exposeFunction('onLeaveSpy', onLeaveSpy)\n        await page().exposeFunction('onEnterSpy', onEnterSpy)\n        await page().exposeFunction('beforeLeaveSpy', beforeLeaveSpy)\n        await page().exposeFunction('beforeEnterSpy', beforeEnterSpy)\n        await page().exposeFunction('afterLeaveSpy', afterLeaveSpy)\n        await page().exposeFunction('afterEnterSpy', afterEnterSpy)\n\n        await page().evaluate(() => {\n          const {\n            beforeEnterSpy,\n            onEnterSpy,\n            afterEnterSpy,\n            beforeLeaveSpy,\n            onLeaveSpy,\n            afterLeaveSpy,\n          } = window as any\n          const { createApp, ref } = (window as any).Vue\n          createApp({\n            template: `\n            <div id=\"container\">\n              <transition\n                name=\"test\"\n                @before-enter=\"beforeEnterSpy()\"\n                @enter=\"onEnterSpy()\"\n                @after-enter=\"afterEnterSpy()\"\n                @before-leave=\"beforeLeaveSpy()\"\n                @leave=\"onLeaveSpy()\"\n                @after-leave=\"afterLeaveSpy()\">\n                <div v-show=\"toggle\" class=\"test\">content</div>\n              </transition>\n            </div>\n            <button id=\"toggleBtn\" @click=\"click\">button</button>\n          `,\n            setup: () => {\n              const toggle = ref(true)\n              const click = () => (toggle.value = !toggle.value)\n              return {\n                toggle,\n                click,\n                beforeEnterSpy,\n                onEnterSpy,\n                afterEnterSpy,\n                beforeLeaveSpy,\n                onLeaveSpy,\n                afterLeaveSpy,\n              }\n            },\n          }).mount('#app')\n        })\n        expect(await html('#container')).toBe('<div class=\"test\">content</div>')\n\n        // leave\n        expect(await classWhenTransitionStart()).toStrictEqual([\n          'test',\n          'test-leave-from',\n          'test-leave-active',\n        ])\n        expect(beforeLeaveSpy).toBeCalled()\n        expect(onLeaveSpy).toBeCalled()\n        expect(afterLeaveSpy).not.toBeCalled()\n        await nextFrame()\n        expect(await classList('.test')).toStrictEqual([\n          'test',\n          'test-leave-active',\n          'test-leave-to',\n        ])\n        expect(afterLeaveSpy).not.toBeCalled()\n        await transitionFinish()\n        expect(await isVisible('.test')).toBe(false)\n        expect(afterLeaveSpy).toBeCalled()\n\n        // enter\n        expect(await classWhenTransitionStart()).toStrictEqual([\n          'test',\n          'test-enter-from',\n          'test-enter-active',\n        ])\n        expect(beforeEnterSpy).toBeCalled()\n        expect(onEnterSpy).toBeCalled()\n        expect(afterEnterSpy).not.toBeCalled()\n        await nextFrame()\n        expect(await classList('.test')).toStrictEqual([\n          'test',\n          'test-enter-active',\n          'test-enter-to',\n        ])\n        expect(afterEnterSpy).not.toBeCalled()\n        await transitionFinish()\n        expect(await html('#container')).toBe(\n          '<div class=\"test\" style=\"\">content</div>',\n        )\n        expect(afterEnterSpy).toBeCalled()\n      },\n      E2E_TIMEOUT,\n    )\n\n    test(\n      'onLeaveCancelled (v-show only)',\n      async () => {\n        const onLeaveCancelledSpy = vi.fn()\n\n        await page().exposeFunction('onLeaveCancelledSpy', onLeaveCancelledSpy)\n        await page().evaluate(() => {\n          const { onLeaveCancelledSpy } = window as any\n          const { createApp, ref } = (window as any).Vue\n          createApp({\n            template: `\n            <div id=\"container\">\n              <transition name=\"test\" @leave-cancelled=\"onLeaveCancelledSpy()\">\n                <div v-show=\"toggle\" class=\"test\">content</div>\n              </transition>\n            </div>\n            <button id=\"toggleBtn\" @click=\"click\">button</button>\n          `,\n            setup: () => {\n              const toggle = ref(true)\n              const click = () => (toggle.value = !toggle.value)\n              return { toggle, click, onLeaveCancelledSpy }\n            },\n          }).mount('#app')\n        })\n        expect(await html('#container')).toBe('<div class=\"test\">content</div>')\n        expect(await isVisible('.test')).toBe(true)\n\n        // leave\n        expect(await classWhenTransitionStart()).toStrictEqual([\n          'test',\n          'test-leave-from',\n          'test-leave-active',\n        ])\n        await nextFrame()\n        expect(await classList('.test')).toStrictEqual([\n          'test',\n          'test-leave-active',\n          'test-leave-to',\n        ])\n\n        // cancel (enter)\n        expect(await classWhenTransitionStart()).toStrictEqual([\n          'test',\n          'test-enter-from',\n          'test-enter-active',\n        ])\n        expect(onLeaveCancelledSpy).toBeCalled()\n        await nextFrame()\n        expect(await classList('.test')).toStrictEqual([\n          'test',\n          'test-enter-active',\n          'test-enter-to',\n        ])\n        await transitionFinish()\n        expect(await html('#container')).toBe(\n          '<div class=\"test\" style=\"\">content</div>',\n        )\n      },\n      E2E_TIMEOUT,\n    )\n\n    test(\n      'transition on appear with v-show',\n      async () => {\n        const beforeEnterSpy = vi.fn()\n        const onEnterSpy = vi.fn()\n        const afterEnterSpy = vi.fn()\n\n        await page().exposeFunction('onEnterSpy', onEnterSpy)\n        await page().exposeFunction('beforeEnterSpy', beforeEnterSpy)\n        await page().exposeFunction('afterEnterSpy', afterEnterSpy)\n\n        const appearClass = await page().evaluate(async () => {\n          const { createApp, ref } = (window as any).Vue\n          const { beforeEnterSpy, onEnterSpy, afterEnterSpy } = window as any\n          createApp({\n            template: `\n              <div id=\"container\">\n                <transition name=\"test\"\n                            appear\n                            appear-from-class=\"test-appear-from\"\n                            appear-to-class=\"test-appear-to\"\n                            appear-active-class=\"test-appear-active\"\n                            @before-enter=\"beforeEnterSpy()\"\n                            @enter=\"onEnterSpy()\"\n                            @after-enter=\"afterEnterSpy()\">\n                  <div v-show=\"toggle\" class=\"test\">content</div>\n                </transition>\n              </div>\n              <button id=\"toggleBtn\" @click=\"click\">button</button>\n            `,\n            setup: () => {\n              const toggle = ref(true)\n              const click = () => (toggle.value = !toggle.value)\n              return {\n                toggle,\n                click,\n                beforeEnterSpy,\n                onEnterSpy,\n                afterEnterSpy,\n              }\n            },\n          }).mount('#app')\n          return Promise.resolve().then(() => {\n            return document.querySelector('.test')!.className.split(/\\s+/g)\n          })\n        })\n\n        expect(beforeEnterSpy).toBeCalledTimes(1)\n        expect(onEnterSpy).toBeCalledTimes(1)\n        expect(afterEnterSpy).toBeCalledTimes(0)\n\n        // appear\n        expect(appearClass).toStrictEqual([\n          'test',\n          'test-appear-from',\n          'test-appear-active',\n        ])\n        await nextFrame()\n        expect(await classList('.test')).toStrictEqual([\n          'test',\n          'test-appear-active',\n          'test-appear-to',\n        ])\n        await transitionFinish()\n        expect(await html('#container')).toBe('<div class=\"test\">content</div>')\n\n        expect(beforeEnterSpy).toBeCalledTimes(1)\n        expect(onEnterSpy).toBeCalledTimes(1)\n        expect(afterEnterSpy).toBeCalledTimes(1)\n\n        // leave\n        expect(await classWhenTransitionStart()).toStrictEqual([\n          'test',\n          'test-leave-from',\n          'test-leave-active',\n        ])\n        await nextFrame()\n        expect(await classList('.test')).toStrictEqual([\n          'test',\n          'test-leave-active',\n          'test-leave-to',\n        ])\n        await transitionFinish()\n        expect(await isVisible('.test')).toBe(false)\n\n        // enter\n        expect(await classWhenTransitionStart()).toStrictEqual([\n          'test',\n          'test-enter-from',\n          'test-enter-active',\n        ])\n        await nextFrame()\n        expect(await classList('.test')).toStrictEqual([\n          'test',\n          'test-enter-active',\n          'test-enter-to',\n        ])\n        await transitionFinish()\n        expect(await html('#container')).toBe(\n          '<div class=\"test\" style=\"\">content</div>',\n        )\n      },\n      E2E_TIMEOUT,\n    )\n\n    // #4845\n    test(\n      'transition events should not call onEnter with v-show false',\n      async () => {\n        const beforeEnterSpy = vi.fn()\n        const onEnterSpy = vi.fn()\n        const afterEnterSpy = vi.fn()\n\n        await page().exposeFunction('onEnterSpy', onEnterSpy)\n        await page().exposeFunction('beforeEnterSpy', beforeEnterSpy)\n        await page().exposeFunction('afterEnterSpy', afterEnterSpy)\n\n        await page().evaluate(() => {\n          const { beforeEnterSpy, onEnterSpy, afterEnterSpy } = window as any\n          const { createApp, ref } = (window as any).Vue\n          createApp({\n            template: `\n            <div id=\"container\">\n              <transition\n                name=\"test\"\n                appear\n                @before-enter=\"beforeEnterSpy()\"\n                @enter=\"onEnterSpy()\"\n                @after-enter=\"afterEnterSpy()\">\n                <div v-show=\"toggle\" class=\"test\">content</div>\n              </transition>\n            </div>\n            <button id=\"toggleBtn\" @click=\"click\">button</button>\n          `,\n            setup: () => {\n              const toggle = ref(false)\n              const click = () => (toggle.value = !toggle.value)\n              return {\n                toggle,\n                click,\n                beforeEnterSpy,\n                onEnterSpy,\n                afterEnterSpy,\n              }\n            },\n          }).mount('#app')\n        })\n        await nextTick()\n\n        expect(await isVisible('.test')).toBe(false)\n\n        expect(beforeEnterSpy).toBeCalledTimes(0)\n        expect(onEnterSpy).toBeCalledTimes(0)\n        // enter\n        expect(await classWhenTransitionStart()).toStrictEqual([\n          'test',\n          'test-enter-from',\n          'test-enter-active',\n        ])\n        expect(beforeEnterSpy).toBeCalledTimes(1)\n        expect(onEnterSpy).toBeCalledTimes(1)\n        expect(afterEnterSpy).not.toBeCalled()\n        await nextFrame()\n        expect(await classList('.test')).toStrictEqual([\n          'test',\n          'test-enter-active',\n          'test-enter-to',\n        ])\n        expect(afterEnterSpy).not.toBeCalled()\n        await transitionFinish()\n        expect(await html('#container')).toBe(\n          '<div class=\"test\" style=\"\">content</div>',\n        )\n        expect(afterEnterSpy).toBeCalled()\n      },\n      E2E_TIMEOUT,\n    )\n  })\n\n  describe('explicit durations', () => {\n    test(\n      'single value',\n      async () => {\n        await page().evaluate(duration => {\n          const { createApp, ref } = (window as any).Vue\n          createApp({\n            template: `\n              <div id=\"container\">\n                <transition name=\"test\" duration=\"${duration * 2}\">\n                  <div v-if=\"toggle\" class=\"test\">content</div>\n                </transition>\n              </div>\n              <button id=\"toggleBtn\" @click=\"click\">button</button>\n            `,\n            setup: () => {\n              const toggle = ref(true)\n              const click = () => (toggle.value = !toggle.value)\n              return { toggle, click }\n            },\n          }).mount('#app')\n        }, duration)\n        expect(await html('#container')).toBe('<div class=\"test\">content</div>')\n\n        // leave\n        expect(await classWhenTransitionStart()).toStrictEqual([\n          'test',\n          'test-leave-from',\n          'test-leave-active',\n        ])\n        await nextFrame()\n        expect(await classList('.test')).toStrictEqual([\n          'test',\n          'test-leave-active',\n          'test-leave-to',\n        ])\n        await transitionFinish(duration * 2)\n        expect(await html('#container')).toBe('<!--v-if-->')\n\n        // enter\n        expect(await classWhenTransitionStart()).toStrictEqual([\n          'test',\n          'test-enter-from',\n          'test-enter-active',\n        ])\n        await nextFrame()\n        expect(await classList('.test')).toStrictEqual([\n          'test',\n          'test-enter-active',\n          'test-enter-to',\n        ])\n        await transitionFinish(duration * 2)\n        expect(await html('#container')).toBe('<div class=\"test\">content</div>')\n      },\n      E2E_TIMEOUT,\n    )\n\n    test(\n      'enter with explicit durations',\n      async () => {\n        await page().evaluate(duration => {\n          const { createApp, ref } = (window as any).Vue\n          createApp({\n            template: `\n              <div id=\"container\">\n                <transition name=\"test\" :duration=\"{ enter: ${duration * 2} }\">\n                  <div v-if=\"toggle\" class=\"test\">content</div>\n                </transition>\n              </div>\n              <button id=\"toggleBtn\" @click=\"click\">button</button>\n            `,\n            setup: () => {\n              const toggle = ref(true)\n              const click = () => (toggle.value = !toggle.value)\n              return { toggle, click }\n            },\n          }).mount('#app')\n        }, duration)\n        expect(await html('#container')).toBe('<div class=\"test\">content</div>')\n\n        // leave\n        expect(await classWhenTransitionStart()).toStrictEqual([\n          'test',\n          'test-leave-from',\n          'test-leave-active',\n        ])\n        await nextFrame()\n        expect(await classList('.test')).toStrictEqual([\n          'test',\n          'test-leave-active',\n          'test-leave-to',\n        ])\n        await transitionFinish()\n        expect(await html('#container')).toBe('<!--v-if-->')\n\n        // enter\n        expect(await classWhenTransitionStart()).toStrictEqual([\n          'test',\n          'test-enter-from',\n          'test-enter-active',\n        ])\n        await nextFrame()\n        expect(await classList('.test')).toStrictEqual([\n          'test',\n          'test-enter-active',\n          'test-enter-to',\n        ])\n        await transitionFinish(duration * 2)\n        expect(await html('#container')).toBe('<div class=\"test\">content</div>')\n      },\n      E2E_TIMEOUT,\n    )\n\n    test(\n      'leave with explicit durations',\n      async () => {\n        await page().evaluate(duration => {\n          const { createApp, ref } = (window as any).Vue\n          createApp({\n            template: `\n              <div id=\"container\">\n                <transition name=\"test\" :duration=\"{ leave: ${duration * 2} }\">\n                  <div v-if=\"toggle\" class=\"test\">content</div>\n                </transition>\n              </div>\n              <button id=\"toggleBtn\" @click=\"click\">button</button>\n            `,\n            setup: () => {\n              const toggle = ref(true)\n              const click = () => (toggle.value = !toggle.value)\n              return { toggle, click }\n            },\n          }).mount('#app')\n        }, duration)\n        expect(await html('#container')).toBe('<div class=\"test\">content</div>')\n\n        // leave\n        expect(await classWhenTransitionStart()).toStrictEqual([\n          'test',\n          'test-leave-from',\n          'test-leave-active',\n        ])\n        await nextFrame()\n        expect(await classList('.test')).toStrictEqual([\n          'test',\n          'test-leave-active',\n          'test-leave-to',\n        ])\n        await transitionFinish(duration * 2)\n        expect(await html('#container')).toBe('<!--v-if-->')\n\n        // enter\n        expect(await classWhenTransitionStart()).toStrictEqual([\n          'test',\n          'test-enter-from',\n          'test-enter-active',\n        ])\n        await nextFrame()\n        expect(await classList('.test')).toStrictEqual([\n          'test',\n          'test-enter-active',\n          'test-enter-to',\n        ])\n        await transitionFinish()\n        expect(await html('#container')).toBe('<div class=\"test\">content</div>')\n      },\n      E2E_TIMEOUT,\n    )\n\n    test(\n      'separate enter and leave',\n      async () => {\n        await page().evaluate(duration => {\n          const { createApp, ref } = (window as any).Vue\n          createApp({\n            template: `\n              <div id=\"container\">\n                <transition name=\"test\" :duration=\"{\n                  enter: ${duration * 4},\n                  leave: ${duration * 2}\n                }\">\n                  <div v-if=\"toggle\" class=\"test\">content</div>\n                </transition>\n              </div>\n              <button id=\"toggleBtn\" @click=\"click\">button</button>\n            `,\n            setup: () => {\n              const toggle = ref(true)\n              const click = () => (toggle.value = !toggle.value)\n              return { toggle, click }\n            },\n          }).mount('#app')\n        }, duration)\n        expect(await html('#container')).toBe('<div class=\"test\">content</div>')\n\n        // leave\n        expect(await classWhenTransitionStart()).toStrictEqual([\n          'test',\n          'test-leave-from',\n          'test-leave-active',\n        ])\n        await nextFrame()\n        expect(await classList('.test')).toStrictEqual([\n          'test',\n          'test-leave-active',\n          'test-leave-to',\n        ])\n        await transitionFinish(duration * 2)\n        expect(await html('#container')).toBe('<!--v-if-->')\n\n        // enter\n        expect(await classWhenTransitionStart()).toStrictEqual([\n          'test',\n          'test-enter-from',\n          'test-enter-active',\n        ])\n        await nextFrame()\n        expect(await classList('.test')).toStrictEqual([\n          'test',\n          'test-enter-active',\n          'test-enter-to',\n        ])\n        await transitionFinish(duration * 4)\n        expect(await html('#container')).toBe('<div class=\"test\">content</div>')\n      },\n      E2E_TIMEOUT,\n    )\n\n    test(\n      'warn invalid durations',\n      async () => {\n        createApp({\n          template: `\n            <div id=\"container\">\n              <transition name=\"test\" :duration=\"NaN\">\n                <div class=\"test\">content</div>\n              </transition>\n            </div>\n          `,\n        }).mount(document.createElement('div'))\n        expect(\n          `[Vue warn]: <transition> explicit duration is NaN - ` +\n            'the duration expression might be incorrect.',\n        ).toHaveBeenWarned()\n\n        createApp({\n          template: `\n            <div id=\"container\">\n              <transition name=\"test\" :duration=\"{\n                enter: {},\n                leave: {}\n              }\">\n                <div class=\"test\">content</div>\n              </transition>\n            </div>\n          `,\n        }).mount(document.createElement('div'))\n        expect(\n          `[Vue warn]: <transition> explicit duration is not a valid number - ` +\n            `got ${JSON.stringify({})}`,\n        ).toHaveBeenWarned()\n      },\n      E2E_TIMEOUT,\n    )\n  })\n\n  test('reflow after *-leave-from before *-leave-active', async () => {\n    await page().evaluate(() => {\n      const { createApp, ref } = (window as any).Vue\n      createApp({\n        template: `\n          <div id=\"container\">\n            <transition name=\"test-reflow\">\n              <div v-if=\"toggle\" class=\"test-reflow\">content</div>\n            </transition>\n          </div>\n          <button id=\"toggleBtn\" @click=\"click\">button</button>\n        `,\n        setup: () => {\n          const toggle = ref(false)\n          const click = () => (toggle.value = !toggle.value)\n          return {\n            toggle,\n            click,\n          }\n        },\n      }).mount('#app')\n    })\n\n    // if transition starts while there's v-leave-active added along with v-leave-from, its bad, it has to start when it doesnt have the v-leave-from\n\n    // enter\n    await classWhenTransitionStart()\n    await transitionFinish()\n\n    // leave\n    expect(await classWhenTransitionStart()).toStrictEqual([\n      'test-reflow',\n      'test-reflow-leave-from',\n      'test-reflow-leave-active',\n    ])\n\n    expect(await style('.test-reflow', 'opacity')).toStrictEqual('0.9')\n\n    await nextFrame()\n    expect(await classList('.test-reflow')).toStrictEqual([\n      'test-reflow',\n      'test-reflow-leave-active',\n      'test-reflow-leave-to',\n    ])\n\n    await transitionFinish()\n    expect(await html('#container')).toBe('<!--v-if-->')\n  })\n\n  test('warn when used on multiple elements', async () => {\n    createApp({\n      render() {\n        return h(Transition, null, {\n          default: () => [h('div'), h('div')],\n        })\n      },\n    }).mount(document.createElement('div'))\n    expect(\n      '<transition> can only be used on a single element or component',\n    ).toHaveBeenWarned()\n  })\n\n  test('warn when invalid transition mode', () => {\n    createApp({\n      template: `\n        <div id=\"container\">\n          <transition name=\"test\" mode=\"none\">\n            <div class=\"test\">content</div>\n          </transition>\n        </div>\n      `,\n    }).mount(document.createElement('div'))\n    expect(`invalid <transition> mode: none`).toHaveBeenWarned()\n  })\n\n  // #3227\n  test(`HOC w/ merged hooks`, async () => {\n    const innerSpy = vi.fn()\n    const outerSpy = vi.fn()\n\n    const MyTransition = {\n      render(this: any) {\n        return h(\n          Transition,\n          {\n            onLeave(el, end) {\n              innerSpy()\n              end()\n            },\n          },\n          this.$slots.default,\n        )\n      },\n    }\n\n    const toggle = ref(true)\n\n    const root = document.createElement('div')\n    createApp({\n      render() {\n        return h(MyTransition, { onLeave: () => outerSpy() }, () =>\n          toggle.value ? h('div') : null,\n        )\n      },\n    }).mount(root)\n\n    expect(root.innerHTML).toBe(`<div></div>`)\n\n    toggle.value = false\n    await nextTick()\n    expect(innerSpy).toHaveBeenCalledTimes(1)\n    expect(outerSpy).toHaveBeenCalledTimes(1)\n    expect(root.innerHTML).toBe(`<!---->`)\n  })\n\n  test(\n    'should work with dev root fragment',\n    async () => {\n      await page().evaluate(() => {\n        const { createApp, ref } = (window as any).Vue\n        createApp({\n          components: {\n            Comp: {\n              template: `\n                  <!-- Broken! -->\n                  <div><slot /></div>\n                `,\n            },\n          },\n          template: `\n            <div id=\"container\">\n              <transition>\n                <Comp class=\"test\" v-if=\"toggle\">\n                  <div>content</div>\n                </Comp>\n              </transition>\n            </div>\n            <button id=\"toggleBtn\" @click=\"click\">button</button>\n          `,\n          setup: () => {\n            const toggle = ref(true)\n            const click = () => (toggle.value = !toggle.value)\n            return { toggle, click }\n          },\n        }).mount('#app')\n      })\n      expect(await html('#container')).toBe(\n        '<!-- Broken! --><div class=\"test\"><div>content</div></div>',\n      )\n\n      // leave\n      expect(await classWhenTransitionStart()).toStrictEqual([\n        'test',\n        'v-leave-from',\n        'v-leave-active',\n      ])\n      await nextFrame()\n      expect(await classList('.test')).toStrictEqual([\n        'test',\n        'v-leave-active',\n        'v-leave-to',\n      ])\n      await transitionFinish()\n      expect(await html('#container')).toBe('<!--v-if-->')\n\n      // enter\n      expect(await classWhenTransitionStart()).toStrictEqual([\n        'test',\n        'v-enter-from',\n        'v-enter-active',\n      ])\n      await nextFrame()\n      expect(await classList('.test')).toStrictEqual([\n        'test',\n        'v-enter-active',\n        'v-enter-to',\n      ])\n      await transitionFinish()\n      expect(await html('#container')).toBe(\n        '<!-- Broken! --><div class=\"test\"><div>content</div></div>',\n      )\n    },\n    E2E_TIMEOUT,\n  )\n\n  // #12091\n  test(\n    'prevent enter when leaving',\n    async () => {\n      const hooks: string[] = []\n      const pushHook = (hook: string) => hooks.push(hook)\n      await page().exposeFunction('pushHook', pushHook)\n      await page().evaluate(() => {\n        const { pushHook } = window as any\n        const { createApp, ref } = (window as any).Vue\n        const visible = ref(true)\n        createApp({\n          components: {\n            Comp: {\n              setup() {\n                visible.value = false\n                return () => null\n              },\n            },\n          },\n          template: `\n            <div id=\"content\" v-if=\"toggle\">\n              <div id=\"container\">\n                <transition\n                  appear\n                  @before-enter=\"pushHook('beforeEnter')\"\n                  @enter=\"pushHook('enter')\"\n                  @enter-cancelled=\"pushHook('enterCancelled')\"\n                  @after-enter=\"pushHook('afterEnter')\"\n                  @before-leave=\"pushHook('beforeLeave')\"\n                  @leave=\"pushHook('leave')\"\n                  @after-leave=\"pushHook('afterLeave')\"\n                >\n                  <div v-if=\"visible\">content</div>\n                </transition>\n              </div>\n              <Comp />\n            </div>\n            <button id=\"toggleBtn\" @click=\"click\">button</button>\n          `,\n          setup: () => {\n            const toggle = ref(false)\n            const click = () => (toggle.value = !toggle.value)\n            return {\n              toggle,\n              click,\n              pushHook,\n              visible,\n            }\n          },\n        }).mount('#app')\n      })\n\n      await click('#toggleBtn')\n      await nextTick()\n      await transitionFinish()\n\n      expect(hooks).toStrictEqual([\n        'beforeEnter',\n        'beforeLeave',\n        'leave',\n        'afterLeave',\n      ])\n      expect(await html('#content')).toBe(\n        '<div id=\"container\"><!--v-if--></div><!---->',\n      )\n    },\n    E2E_TIMEOUT,\n  )\n\n  // https://github.com/vuejs/core/issues/12181#issuecomment-2414380955\n  describe('not leaking', async () => {\n    test('switching VNodes', async () => {\n      const client = await page().createCDPSession()\n      await page().evaluate(async () => {\n        const { createApp, ref, nextTick } = (window as any).Vue\n        const empty = ref(true)\n\n        createApp({\n          components: {\n            Child: {\n              setup: () => {\n                // Big arrays kick GC earlier\n                const test = ref([...Array(30_000_000)].map((_, i) => ({ i })))\n                // TODO: Use a different TypeScript env for testing\n                // @ts-expect-error - Custom property and same lib as runtime is used\n                window.__REF__ = new WeakRef(test)\n\n                return { test }\n              },\n              template: `\n                <p>{{ test.length }}</p>\n              `,\n            },\n            Empty: {\n              template: '<div></div>',\n            },\n          },\n          template: `\n            <transition>\n              <component :is=\"empty ? 'Empty' : 'Child'\" />\n            </transition>\n          `,\n          setup() {\n            return { empty }\n          },\n        }).mount('#app')\n\n        await nextTick()\n        empty.value = false\n        await nextTick()\n        empty.value = true\n        await nextTick()\n      })\n\n      const isCollected = async () =>\n        // @ts-expect-error - Custom property\n        await page().evaluate(() => window.__REF__.deref() === undefined)\n\n      while ((await isCollected()) === false) {\n        await client.send('HeapProfiler.collectGarbage')\n      }\n\n      expect(await isCollected()).toBe(true)\n    })\n\n    // https://github.com/vuejs/core/issues/12181#issue-2588232334\n    test('switching deep vnodes edge case', async () => {\n      const client = await page().createCDPSession()\n      await page().evaluate(async () => {\n        const { createApp, ref, nextTick } = (window as any).Vue\n        const shown = ref(false)\n\n        createApp({\n          components: {\n            Child: {\n              setup: () => {\n                // Big arrays kick GC earlier\n                const test = ref([...Array(30_000_000)].map((_, i) => ({ i })))\n                // TODO: Use a different TypeScript env for testing\n                // @ts-expect-error - Custom property and same lib as runtime is used\n                window.__REF__ = new WeakRef(test)\n\n                return { test }\n              },\n              template: `\n                <p>{{ test.length }}</p>\n              `,\n            },\n            Wrapper: {\n              template: `\n                <transition>\n                  <div v-if=\"true\">\n                    <slot />\n                  </div>\n                </transition>\n              `,\n            },\n          },\n          template: `\n            <button id=\"toggleBtn\" @click=\"shown = !shown\">{{ shown ? 'Hide' : 'Show' }}</button>\n            <Wrapper>\n              <Child v-if=\"shown\" />\n              <div v-else></div>\n            </Wrapper>\n          `,\n          setup() {\n            return { shown }\n          },\n        }).mount('#app')\n\n        await nextTick()\n        shown.value = true\n        await nextTick()\n        shown.value = false\n        await nextTick()\n      })\n\n      const isCollected = async () =>\n        // @ts-expect-error - Custom property\n        await page().evaluate(() => window.__REF__.deref() === undefined)\n\n      while ((await isCollected()) === false) {\n        await client.send('HeapProfiler.collectGarbage')\n      }\n\n      expect(await isCollected()).toBe(true)\n    })\n  })\n})\n"
  },
  {
    "path": "packages/vue/__tests__/e2e/TransitionGroup.spec.ts",
    "content": "import { E2E_TIMEOUT, setupPuppeteer } from './e2eUtils'\nimport path from 'node:path'\nimport { createApp, ref } from 'vue'\n\ndescribe('e2e: TransitionGroup', () => {\n  const { page, html, nextFrame, timeout } = setupPuppeteer()\n  const baseUrl = `file://${path.resolve(__dirname, './transition.html')}`\n\n  const duration = process.env.CI ? 200 : 50\n  const buffer = process.env.CI ? 20 : 5\n\n  const htmlWhenTransitionStart = () =>\n    page().evaluate(() => {\n      ;(document.querySelector('#toggleBtn') as any)!.click()\n      return Promise.resolve().then(() => {\n        return document.querySelector('#container')!.innerHTML\n      })\n    })\n\n  const transitionFinish = (time = duration) => timeout(time + buffer)\n\n  beforeEach(async () => {\n    await page().goto(baseUrl)\n    await page().waitForSelector('#app')\n  })\n\n  test(\n    'enter',\n    async () => {\n      await page().evaluate(() => {\n        const { createApp, ref } = (window as any).Vue\n        createApp({\n          template: `\n              <div id=\"container\">\n\t\t\t\t\t\t\t\t<transition-group name=\"test\">\n\t\t\t\t\t\t\t\t\t<div v-for=\"item in items\" :key=\"item\" class=\"test\">{{item}}</div>\n\t\t\t\t\t\t\t\t</transition-group>\n\t\t\t\t\t\t\t</div>\n              <button id=\"toggleBtn\" @click=\"click\">button</button>\n            `,\n          setup: () => {\n            const items = ref(['a', 'b', 'c'])\n            const click = () => items.value.push('d', 'e')\n            return { click, items }\n          },\n        }).mount('#app')\n      })\n      expect(await html('#container')).toBe(\n        `<div class=\"test\">a</div>` +\n          `<div class=\"test\">b</div>` +\n          `<div class=\"test\">c</div>`,\n      )\n\n      expect(await htmlWhenTransitionStart()).toBe(\n        `<div class=\"test\">a</div>` +\n          `<div class=\"test\">b</div>` +\n          `<div class=\"test\">c</div>` +\n          `<div class=\"test test-enter-from test-enter-active\">d</div>` +\n          `<div class=\"test test-enter-from test-enter-active\">e</div>`,\n      )\n      await nextFrame()\n      expect(await html('#container')).toBe(\n        `<div class=\"test\">a</div>` +\n          `<div class=\"test\">b</div>` +\n          `<div class=\"test\">c</div>` +\n          `<div class=\"test test-enter-active test-enter-to\">d</div>` +\n          `<div class=\"test test-enter-active test-enter-to\">e</div>`,\n      )\n      await transitionFinish()\n      expect(await html('#container')).toBe(\n        `<div class=\"test\">a</div>` +\n          `<div class=\"test\">b</div>` +\n          `<div class=\"test\">c</div>` +\n          `<div class=\"test\">d</div>` +\n          `<div class=\"test\">e</div>`,\n      )\n    },\n    E2E_TIMEOUT,\n  )\n\n  test(\n    'leave',\n    async () => {\n      await page().evaluate(() => {\n        const { createApp, ref } = (window as any).Vue\n        createApp({\n          template: `\n              <div id=\"container\">\n\t\t\t\t\t\t\t\t<transition-group name=\"test\">\n\t\t\t\t\t\t\t\t\t<div v-for=\"item in items\" :key=\"item\" class=\"test\">{{item}}</div>\n\t\t\t\t\t\t\t\t</transition-group>\n\t\t\t\t\t\t\t</div>\n              <button id=\"toggleBtn\" @click=\"click\">button</button>\n            `,\n          setup: () => {\n            const items = ref(['a', 'b', 'c'])\n            const click = () => (items.value = ['b'])\n            return { click, items }\n          },\n        }).mount('#app')\n      })\n      expect(await html('#container')).toBe(\n        `<div class=\"test\">a</div>` +\n          `<div class=\"test\">b</div>` +\n          `<div class=\"test\">c</div>`,\n      )\n\n      expect(await htmlWhenTransitionStart()).toBe(\n        `<div class=\"test test-leave-from test-leave-active\">a</div>` +\n          `<div class=\"test\">b</div>` +\n          `<div class=\"test test-leave-from test-leave-active\">c</div>`,\n      )\n      await nextFrame()\n      expect(await html('#container')).toBe(\n        `<div class=\"test test-leave-active test-leave-to\">a</div>` +\n          `<div class=\"test\">b</div>` +\n          `<div class=\"test test-leave-active test-leave-to\">c</div>`,\n      )\n      await transitionFinish()\n      expect(await html('#container')).toBe(`<div class=\"test\">b</div>`)\n    },\n    E2E_TIMEOUT,\n  )\n\n  test(\n    'enter + leave',\n    async () => {\n      await page().evaluate(() => {\n        const { createApp, ref } = (window as any).Vue\n        createApp({\n          template: `\n              <div id=\"container\">\n\t\t\t\t\t\t\t\t<transition-group name=\"test\">\n\t\t\t\t\t\t\t\t\t<div v-for=\"item in items\" :key=\"item\" class=\"test\">{{item}}</div>\n\t\t\t\t\t\t\t\t</transition-group>\n\t\t\t\t\t\t\t</div>\n              <button id=\"toggleBtn\" @click=\"click\">button</button>\n            `,\n          setup: () => {\n            const items = ref(['a', 'b', 'c'])\n            const click = () => (items.value = ['b', 'c', 'd'])\n            return { click, items }\n          },\n        }).mount('#app')\n      })\n      expect(await html('#container')).toBe(\n        `<div class=\"test\">a</div>` +\n          `<div class=\"test\">b</div>` +\n          `<div class=\"test\">c</div>`,\n      )\n\n      expect(await htmlWhenTransitionStart()).toBe(\n        `<div class=\"test test-leave-from test-leave-active\">a</div>` +\n          `<div class=\"test\">b</div>` +\n          `<div class=\"test\">c</div>` +\n          `<div class=\"test test-enter-from test-enter-active\">d</div>`,\n      )\n      await nextFrame()\n      expect(await html('#container')).toBe(\n        `<div class=\"test test-leave-active test-leave-to\">a</div>` +\n          `<div class=\"test\">b</div>` +\n          `<div class=\"test\">c</div>` +\n          `<div class=\"test test-enter-active test-enter-to\">d</div>`,\n      )\n      await transitionFinish()\n      expect(await html('#container')).toBe(\n        `<div class=\"test\">b</div>` +\n          `<div class=\"test\">c</div>` +\n          `<div class=\"test\">d</div>`,\n      )\n    },\n    E2E_TIMEOUT,\n  )\n\n  test(\n    'appear',\n    async () => {\n      const appearHtml = await page().evaluate(() => {\n        const { createApp, ref } = (window as any).Vue\n        createApp({\n          template: `\n              <div id=\"container\">\n\t\t\t\t\t\t\t\t<transition-group appear\n\t\t\t\t\t\t\t\t\t\tappear-from-class=\"test-appear-from\"\n\t\t\t\t\t\t\t\t\t\tappear-to-class=\"test-appear-to\"\n\t\t\t\t\t\t\t\t\t\tappear-active-class=\"test-appear-active\"\n\t\t\t\t\t\t\t\t\t\tname=\"test\">\n\t\t\t\t\t\t\t\t\t<div v-for=\"item in items\" :key=\"item\" class=\"test\">{{item}}</div>\n\t\t\t\t\t\t\t\t</transition-group>\n\t\t\t\t\t\t\t</div>\n              <button id=\"toggleBtn\" @click=\"click\">button</button>\n            `,\n          setup: () => {\n            const items = ref(['a', 'b', 'c'])\n            const click = () => items.value.push('d', 'e')\n            return { click, items }\n          },\n        }).mount('#app')\n        return Promise.resolve().then(() => {\n          return document.querySelector('#container')!.innerHTML\n        })\n      })\n      // appear\n      expect(appearHtml).toBe(\n        `<div class=\"test test-appear-from test-appear-active\">a</div>` +\n          `<div class=\"test test-appear-from test-appear-active\">b</div>` +\n          `<div class=\"test test-appear-from test-appear-active\">c</div>`,\n      )\n      await nextFrame()\n      expect(await html('#container')).toBe(\n        `<div class=\"test test-appear-active test-appear-to\">a</div>` +\n          `<div class=\"test test-appear-active test-appear-to\">b</div>` +\n          `<div class=\"test test-appear-active test-appear-to\">c</div>`,\n      )\n      await transitionFinish()\n      expect(await html('#container')).toBe(\n        `<div class=\"test\">a</div>` +\n          `<div class=\"test\">b</div>` +\n          `<div class=\"test\">c</div>`,\n      )\n\n      // enter\n      expect(await htmlWhenTransitionStart()).toBe(\n        `<div class=\"test\">a</div>` +\n          `<div class=\"test\">b</div>` +\n          `<div class=\"test\">c</div>` +\n          `<div class=\"test test-enter-from test-enter-active\">d</div>` +\n          `<div class=\"test test-enter-from test-enter-active\">e</div>`,\n      )\n      await nextFrame()\n      expect(await html('#container')).toBe(\n        `<div class=\"test\">a</div>` +\n          `<div class=\"test\">b</div>` +\n          `<div class=\"test\">c</div>` +\n          `<div class=\"test test-enter-active test-enter-to\">d</div>` +\n          `<div class=\"test test-enter-active test-enter-to\">e</div>`,\n      )\n      await transitionFinish()\n      expect(await html('#container')).toBe(\n        `<div class=\"test\">a</div>` +\n          `<div class=\"test\">b</div>` +\n          `<div class=\"test\">c</div>` +\n          `<div class=\"test\">d</div>` +\n          `<div class=\"test\">e</div>`,\n      )\n    },\n    E2E_TIMEOUT,\n  )\n\n  test(\n    'move',\n    async () => {\n      await page().evaluate(() => {\n        const { createApp, ref } = (window as any).Vue\n        createApp({\n          template: `\n              <div id=\"container\">\n\t\t\t\t\t\t\t\t<transition-group name=\"group\">\n\t\t\t\t\t\t\t\t\t<div v-for=\"item in items\" :key=\"item\" class=\"test\">{{item}}</div>\n\t\t\t\t\t\t\t\t</transition-group>\n\t\t\t\t\t\t\t</div>\n              <button id=\"toggleBtn\" @click=\"click\">button</button>\n            `,\n          setup: () => {\n            const items = ref(['a', 'b', 'c'])\n            const click = () => (items.value = ['d', 'b', 'a'])\n            return { click, items }\n          },\n        }).mount('#app')\n      })\n      expect(await html('#container')).toBe(\n        `<div class=\"test\">a</div>` +\n          `<div class=\"test\">b</div>` +\n          `<div class=\"test\">c</div>`,\n      )\n\n      expect(await htmlWhenTransitionStart()).toBe(\n        `<div class=\"test group-enter-from group-enter-active\">d</div>` +\n          `<div class=\"test\">b</div>` +\n          `<div class=\"test group-move\" style=\"\">a</div>` +\n          `<div class=\"test group-leave-from group-leave-active group-move\" style=\"\">c</div>`,\n      )\n      await nextFrame()\n      expect(await html('#container')).toBe(\n        `<div class=\"test group-enter-active group-enter-to\">d</div>` +\n          `<div class=\"test\">b</div>` +\n          `<div class=\"test group-move\" style=\"\">a</div>` +\n          `<div class=\"test group-leave-active group-move group-leave-to\" style=\"\">c</div>`,\n      )\n      await transitionFinish(duration * 2)\n      expect(await html('#container')).toBe(\n        `<div class=\"test\">d</div>` +\n          `<div class=\"test\">b</div>` +\n          `<div class=\"test\" style=\"\">a</div>`,\n      )\n    },\n    E2E_TIMEOUT,\n  )\n\n  test(\n    'move while entering',\n    async () => {\n      await page().evaluate(duration => {\n        const { createApp, ref, onMounted } = (window as any).Vue\n        createApp({\n          template: `\n              <transition-group name=\"toasts\" tag=\"div\" id=\"toasts\">\n                <div class=\"toast\" v-for=\"toast in list\" :key=\"toast.id\">\n                  {{ toast.text }} #{{ toast.id }}\n                </div>\n              </transition-group>\n              <button id=\"addBtn\" @click=\"add\">button</button>\n            `,\n          setup: () => {\n            const list = ref([])\n            let id = 0\n            const add = () => {\n              if (list.value.length > 3) {\n                list.value.splice(0, 1)\n              }\n              list.value.push({\n                id,\n                type: 'error',\n                text: 'Test message',\n              })\n              id++\n            }\n\n            onMounted(() => {\n              const styleNode = document.createElement('style')\n              styleNode.innerHTML = `\n                #toasts {\n                  position: absolute;\n                  bottom: 0;\n                  left: 0;\n                }\n                #toasts > .toast {\n                  width: 150px;\n                  margin-bottom: 10px;\n                  height: 30px;\n                  color: white;\n                  background: black;\n                }\n                .toasts-leave-active {\n                  position: absolute;\n                }\n                .toasts-move { transition: transform ${duration}ms ease; }\n              `\n              document.body.appendChild(styleNode)\n            })\n\n            return { list, add }\n          },\n        }).mount('#app')\n      }, duration)\n\n      const overlapDelay = Math.max(10, Math.floor(duration / 2))\n      const { midTop, finalTop } = await page().evaluate(\n        ({ overlapDelay, duration, buffer }) => {\n          ;(document.querySelector('#addBtn') as any)!.click()\n          return new Promise<{ midTop: number; finalTop: number }>(resolve => {\n            setTimeout(() => {\n              ;(document.querySelector('#addBtn') as any)!.click()\n              Promise.resolve().then(() => {\n                const nodes = Array.from(\n                  document.querySelectorAll('#toasts .toast'),\n                ) as HTMLElement[]\n                const firstToast = nodes.find(node =>\n                  node.textContent?.includes('#0'),\n                )\n                const midTop = firstToast\n                  ? firstToast.getBoundingClientRect().top\n                  : NaN\n                setTimeout(() => {\n                  const finalTop = firstToast\n                    ? firstToast.getBoundingClientRect().top\n                    : NaN\n                  resolve({ midTop, finalTop })\n                }, duration + buffer)\n              })\n            }, overlapDelay)\n          })\n        },\n        { overlapDelay, duration, buffer },\n      )\n\n      expect(midTop).toBeGreaterThan(finalTop)\n    },\n    E2E_TIMEOUT,\n  )\n\n  test(\n    'dynamic name',\n    async () => {\n      await page().evaluate(() => {\n        const { createApp, ref } = (window as any).Vue\n        createApp({\n          template: `\n              <div id=\"container\">\n\t\t\t\t\t\t\t\t<transition-group :name=\"name\">\n\t\t\t\t\t\t\t\t\t<div v-for=\"item in items\" :key=\"item\" >{{item}}</div>\n\t\t\t\t\t\t\t\t</transition-group>\n\t\t\t\t\t\t\t</div>\n              <button id=\"toggleBtn\" @click=\"click\">button</button>\n              <button id=\"changeNameBtn\" @click=\"changeName\">button</button>\n\t\t\t\t\t`,\n          setup: () => {\n            const items = ref(['a', 'b', 'c'])\n            const name = ref('invalid')\n            const click = () => (items.value = ['b', 'c', 'a'])\n            const changeName = () => {\n              name.value = 'group'\n              items.value = ['a', 'b', 'c']\n            }\n            return { click, items, name, changeName }\n          },\n        }).mount('#app')\n      })\n      expect(await html('#container')).toBe(\n        `<div>a</div>` + `<div>b</div>` + `<div>c</div>`,\n      )\n\n      // invalid name\n      expect(await htmlWhenTransitionStart()).toBe(\n        `<div>b</div>` + `<div>c</div>` + `<div>a</div>`,\n      )\n      // change name\n      const moveHtml = await page().evaluate(() => {\n        ;(document.querySelector('#changeNameBtn') as any).click()\n        return Promise.resolve().then(() => {\n          return document.querySelector('#container')!.innerHTML\n        })\n      })\n      expect(moveHtml).toBe(\n        `<div class=\"group-move\" style=\"\">a</div>` +\n          `<div class=\"group-move\" style=\"\">b</div>` +\n          `<div class=\"group-move\" style=\"\">c</div>`,\n      )\n      // not sure why but we just have to wait really long for this to\n      // pass consistently :/\n      await transitionFinish(duration * 4 + buffer)\n      expect(await html('#container')).toBe(\n        `<div class=\"\" style=\"\">a</div>` +\n          `<div class=\"\" style=\"\">b</div>` +\n          `<div class=\"\" style=\"\">c</div>`,\n      )\n    },\n    E2E_TIMEOUT,\n  )\n\n  test(\n    'events',\n    async () => {\n      const onLeaveSpy = vi.fn()\n      const onEnterSpy = vi.fn()\n      const onAppearSpy = vi.fn()\n      const beforeLeaveSpy = vi.fn()\n      const beforeEnterSpy = vi.fn()\n      const beforeAppearSpy = vi.fn()\n      const afterLeaveSpy = vi.fn()\n      const afterEnterSpy = vi.fn()\n      const afterAppearSpy = vi.fn()\n\n      await page().exposeFunction('onLeaveSpy', onLeaveSpy)\n      await page().exposeFunction('onEnterSpy', onEnterSpy)\n      await page().exposeFunction('onAppearSpy', onAppearSpy)\n      await page().exposeFunction('beforeLeaveSpy', beforeLeaveSpy)\n      await page().exposeFunction('beforeEnterSpy', beforeEnterSpy)\n      await page().exposeFunction('beforeAppearSpy', beforeAppearSpy)\n      await page().exposeFunction('afterLeaveSpy', afterLeaveSpy)\n      await page().exposeFunction('afterEnterSpy', afterEnterSpy)\n      await page().exposeFunction('afterAppearSpy', afterAppearSpy)\n\n      const appearHtml = await page().evaluate(() => {\n        const {\n          beforeAppearSpy,\n          onAppearSpy,\n          afterAppearSpy,\n          beforeEnterSpy,\n          onEnterSpy,\n          afterEnterSpy,\n          beforeLeaveSpy,\n          onLeaveSpy,\n          afterLeaveSpy,\n        } = window as any\n        const { createApp, ref } = (window as any).Vue\n        createApp({\n          template: `\n                <div id=\"container\">\n                  <transition-group name=\"test\"\n                      appear\n                      appear-from-class=\"test-appear-from\"\n                      appear-to-class=\"test-appear-to\"\n                      appear-active-class=\"test-appear-active\"\n                      @before-enter=\"beforeEnterSpy()\"\n                      @enter=\"onEnterSpy()\"\n                      @after-enter=\"afterEnterSpy()\"\n                      @before-leave=\"beforeLeaveSpy()\"\n                      @leave=\"onLeaveSpy()\"\n                      @after-leave=\"afterLeaveSpy()\"\n                      @before-appear=\"beforeAppearSpy()\"\n                      @appear=\"onAppearSpy()\"\n                      @after-appear=\"afterAppearSpy()\">\n                    <div v-for=\"item in items\" :key=\"item\" class=\"test\">{{item}}</div>\n                  </transition-group>\n                </div>\n                <button id=\"toggleBtn\" @click=\"click\">button</button>\n              `,\n          setup: () => {\n            const items = ref(['a', 'b', 'c'])\n            const click = () => (items.value = ['b', 'c', 'd'])\n            return {\n              click,\n              items,\n              beforeAppearSpy,\n              onAppearSpy,\n              afterAppearSpy,\n              beforeEnterSpy,\n              onEnterSpy,\n              afterEnterSpy,\n              beforeLeaveSpy,\n              onLeaveSpy,\n              afterLeaveSpy,\n            }\n          },\n        }).mount('#app')\n        return Promise.resolve().then(() => {\n          return document.querySelector('#container')!.innerHTML\n        })\n      })\n      expect(beforeAppearSpy).toBeCalled()\n      expect(onAppearSpy).toBeCalled()\n      expect(afterAppearSpy).not.toBeCalled()\n      expect(appearHtml).toBe(\n        `<div class=\"test test-appear-from test-appear-active\">a</div>` +\n          `<div class=\"test test-appear-from test-appear-active\">b</div>` +\n          `<div class=\"test test-appear-from test-appear-active\">c</div>`,\n      )\n      await nextFrame()\n      expect(afterAppearSpy).not.toBeCalled()\n      expect(await html('#container')).toBe(\n        `<div class=\"test test-appear-active test-appear-to\">a</div>` +\n          `<div class=\"test test-appear-active test-appear-to\">b</div>` +\n          `<div class=\"test test-appear-active test-appear-to\">c</div>`,\n      )\n      await transitionFinish()\n      expect(afterAppearSpy).toBeCalled()\n      expect(await html('#container')).toBe(\n        `<div class=\"test\">a</div>` +\n          `<div class=\"test\">b</div>` +\n          `<div class=\"test\">c</div>`,\n      )\n\n      // enter + leave\n      expect(await htmlWhenTransitionStart()).toBe(\n        `<div class=\"test test-leave-from test-leave-active\">a</div>` +\n          `<div class=\"test\">b</div>` +\n          `<div class=\"test\">c</div>` +\n          `<div class=\"test test-enter-from test-enter-active\">d</div>`,\n      )\n      expect(beforeLeaveSpy).toBeCalled()\n      expect(onLeaveSpy).toBeCalled()\n      expect(afterLeaveSpy).not.toBeCalled()\n      expect(beforeEnterSpy).toBeCalled()\n      expect(onEnterSpy).toBeCalled()\n      expect(afterEnterSpy).not.toBeCalled()\n      await nextFrame()\n      expect(await html('#container')).toBe(\n        `<div class=\"test test-leave-active test-leave-to\">a</div>` +\n          `<div class=\"test\">b</div>` +\n          `<div class=\"test\">c</div>` +\n          `<div class=\"test test-enter-active test-enter-to\">d</div>`,\n      )\n      expect(afterLeaveSpy).not.toBeCalled()\n      expect(afterEnterSpy).not.toBeCalled()\n      await transitionFinish()\n      expect(await html('#container')).toBe(\n        `<div class=\"test\">b</div>` +\n          `<div class=\"test\">c</div>` +\n          `<div class=\"test\">d</div>`,\n      )\n      expect(afterLeaveSpy).toBeCalled()\n      expect(afterEnterSpy).toBeCalled()\n    },\n    E2E_TIMEOUT,\n  )\n\n  test('warn unkeyed children', () => {\n    createApp({\n      template: `\n        <transition-group name=\"test\">\n          <div v-for=\"item in items\" class=\"test\">{{item}}</div>\n        </transition-group>\n            `,\n      setup: () => {\n        const items = ref(['a', 'b', 'c'])\n        return { items }\n      },\n    }).mount(document.createElement('div'))\n\n    expect(`<TransitionGroup> children must be keyed`).toHaveBeenWarned()\n  })\n\n  test('not warn unkeyed text children w/ whitespace preserve', () => {\n    const app = createApp({\n      template: `\n        <transition-group name=\"test\">\n          <p key=\"1\">1</p>\n          <p key=\"2\" v-if=\"false\">2</p>\n        </transition-group>\n        `,\n    })\n\n    app.config.compilerOptions.whitespace = 'preserve'\n    app.mount(document.createElement('div'))\n    expect(`<TransitionGroup> children must be keyed`).not.toHaveBeenWarned()\n  })\n\n  // #5168, #7898, #9067\n  test(\n    'avoid set transition hooks for comment node',\n    async () => {\n      await page().evaluate(duration => {\n        const { createApp, ref, h, createCommentVNode } = (window as any).Vue\n\n        const show = ref(false)\n        createApp({\n          template: `\n            <div id=\"container\">\n              <transition-group name=\"test\">\n                <div v-for=\"item in items\" :key=\"item\" class=\"test\">{{item}}</div>\n                <Child key=\"child\"/>\n              </transition-group>\n            </div>\n            <button id=\"toggleBtn\" @click=\"click\">button</button>\n          `,\n          components: {\n            Child: {\n              setup() {\n                return () =>\n                  show.value\n                    ? h('div', { class: 'test' }, 'child')\n                    : createCommentVNode('v-if', true)\n              },\n            },\n          },\n          setup: () => {\n            const items = ref([])\n            const click = () => {\n              items.value = ['a', 'b', 'c']\n              setTimeout(() => {\n                show.value = true\n              }, duration)\n            }\n            return { click, items }\n          },\n        }).mount('#app')\n      }, duration)\n\n      expect(await html('#container')).toBe(`<!--v-if-->`)\n\n      expect(await htmlWhenTransitionStart()).toBe(\n        `<div class=\"test test-enter-from test-enter-active\">a</div>` +\n          `<div class=\"test test-enter-from test-enter-active\">b</div>` +\n          `<div class=\"test test-enter-from test-enter-active\">c</div>` +\n          `<!--v-if-->`,\n      )\n\n      await transitionFinish(duration)\n      await nextFrame()\n      expect(await html('#container')).toBe(\n        `<div class=\"test\">a</div>` +\n          `<div class=\"test\">b</div>` +\n          `<div class=\"test\">c</div>` +\n          `<div class=\"test test-enter-active test-enter-to\">child</div>`,\n      )\n\n      await transitionFinish(duration)\n      expect(await html('#container')).toBe(\n        `<div class=\"test\">a</div>` +\n          `<div class=\"test\">b</div>` +\n          `<div class=\"test\">c</div>` +\n          `<div class=\"test\">child</div>`,\n      )\n    },\n    E2E_TIMEOUT,\n  )\n\n  // #4621, #4622, #5153\n  test(\n    'avoid set transition hooks for text node',\n    async () => {\n      await page().evaluate(() => {\n        const { createApp, ref } = (window as any).Vue\n        const app = createApp({\n          template: `\n            <div id=\"container\">\n              <transition-group name=\"test\">\n                <div class=\"test\">foo</div>\n                <div class=\"test\" v-if=\"show\">bar</div>\n              </transition-group>\n            </div>\n            <button id=\"toggleBtn\" @click=\"click\">button</button>\n          `,\n          setup: () => {\n            const show = ref(false)\n            const click = () => {\n              show.value = true\n            }\n            return { show, click }\n          },\n        })\n\n        app.config.compilerOptions.whitespace = 'preserve'\n        app.mount('#app')\n      })\n\n      expect(await html('#container')).toBe(`<div class=\"test\">foo</div>` + ` `)\n\n      expect(await htmlWhenTransitionStart()).toBe(\n        `<div class=\"test\">foo</div>` +\n          ` ` +\n          `<div class=\"test test-enter-from test-enter-active\">bar</div>`,\n      )\n\n      await nextFrame()\n      expect(await html('#container')).toBe(\n        `<div class=\"test\">foo</div>` +\n          ` ` +\n          `<div class=\"test test-enter-active test-enter-to\">bar</div>`,\n      )\n\n      await transitionFinish(duration)\n      expect(await html('#container')).toBe(\n        `<div class=\"test\">foo</div>` + ` ` + `<div class=\"test\">bar</div>`,\n      )\n    },\n    E2E_TIMEOUT,\n  )\n\n  // #6105\n  test(\n    'with scale',\n    async () => {\n      await page().evaluate(() => {\n        const { createApp, ref, onMounted } = (window as any).Vue\n        createApp({\n          template: `\n            <div id=\"container\">\n              <div class=\"scale\" style=\"transform: scale(2) translateX(50%) translateY(50%)\">\n                <transition-group tag=\"ul\">\n                  <li v-for=\"item in items\" :key=\"item\">{{item}}</li>\n                </transition-group>\n                <button id=\"toggleBtn\" @click=\"click\">button</button>\n              </div>\n            </div>\n          `,\n          setup: () => {\n            const items = ref(['a', 'b', 'c'])\n            const click = () => {\n              items.value.reverse()\n            }\n\n            onMounted(() => {\n              const styleNode = document.createElement('style')\n              styleNode.innerHTML = `.v-move {\n                transition: transform 0.5s ease;\n              }`\n              document.body.appendChild(styleNode)\n            })\n\n            return { items, click }\n          },\n        }).mount('#app')\n      })\n\n      const original_top = await page().$eval('ul li:nth-child(1)', node => {\n        return node.getBoundingClientRect().top\n      })\n      const new_top = await page().evaluate(() => {\n        const el = document.querySelector('ul li:nth-child(1)')\n        const p = new Promise(resolve => {\n          el!.addEventListener('transitionstart', () => {\n            const new_top = el!.getBoundingClientRect().top\n            resolve(new_top)\n          })\n        })\n        ;(document.querySelector('#toggleBtn') as any)!.click()\n        return p\n      })\n\n      expect(original_top).toBeLessThan(new_top as number)\n    },\n    E2E_TIMEOUT,\n  )\n\n  test(\n    'not leaking after children unmounted',\n    async () => {\n      const client = await page().createCDPSession()\n      await page().evaluate(async () => {\n        const { createApp, ref, nextTick } = (window as any).Vue\n        const show = ref(true)\n\n        createApp({\n          components: {\n            Child: {\n              setup: () => {\n                // Big arrays kick GC earlier\n                const test = ref([...Array(3000)].map((_, i) => ({ i })))\n                // @ts-expect-error - Custom property and same lib as runtime is used\n                window.__REF__ = new WeakRef(test)\n\n                return { test }\n              },\n              template: `\n              <p>{{ test.length }}</p>\n            `,\n            },\n          },\n          template: `\n          <transition-group>\n            <Child v-if=\"show\" />\n          </transition-group>\n        `,\n          setup() {\n            return { show }\n          },\n        }).mount('#app')\n\n        show.value = false\n        await nextTick()\n      })\n\n      const isCollected = async () =>\n        // @ts-expect-error - Custom property\n        await page().evaluate(() => window.__REF__.deref() === undefined)\n\n      while ((await isCollected()) === false) {\n        await client.send('HeapProfiler.collectGarbage')\n      }\n\n      expect(await isCollected()).toBe(true)\n    },\n    E2E_TIMEOUT,\n  )\n})\n"
  },
  {
    "path": "packages/vue/__tests__/e2e/commits.mock.ts",
    "content": "export default {\n  main: [\n    {\n      sha: 'd1527fbee422c7170e56845e55b49c4fd6de72a7',\n      node_id:\n        'MDY6Q29tbWl0MTM3MDc4NDg3OmQxNTI3ZmJlZTQyMmM3MTcwZTU2ODQ1ZTU1YjQ5YzRmZDZkZTcyYTc=',\n      commit: {\n        author: {\n          name: 'Haoqun Jiang',\n          email: 'haoqunjiang@gmail.com',\n          date: '2019-12-09T19:52:20Z',\n        },\n        committer: {\n          name: 'Evan You',\n          email: 'yyx990803@gmail.com',\n          date: '2019-12-09T19:52:20Z',\n        },\n        message: 'test: add test for runtime-dom/modules/class (#75)',\n        tree: {\n          sha: 'f53f761827af281db86c31d113086c068c1d0789',\n          url: 'https://api.github.com/repos/vuejs/core/git/trees/f53f761827af281db86c31d113086c068c1d0789',\n        },\n        url: 'https://api.github.com/repos/vuejs/core/git/commits/d1527fbee422c7170e56845e55b49c4fd6de72a7',\n        comment_count: 0,\n        verification: {\n          verified: false,\n          reason: 'unsigned',\n          signature: null,\n          payload: null,\n        },\n      },\n      url: 'https://api.github.com/repos/vuejs/core/commits/d1527fbee422c7170e56845e55b49c4fd6de72a7',\n      html_url:\n        'https://github.com/vuejs/core/commit/d1527fbee422c7170e56845e55b49c4fd6de72a7',\n      comments_url:\n        'https://api.github.com/repos/vuejs/core/commits/d1527fbee422c7170e56845e55b49c4fd6de72a7/comments',\n      author: {\n        login: 'sodatea',\n        id: 3277634,\n        node_id: 'MDQ6VXNlcjMyNzc2MzQ=',\n        avatar_url: 'https://avatars3.githubusercontent.com/u/3277634?v=4',\n        gravatar_id: '',\n        url: 'https://api.github.com/users/sodatea',\n        html_url: 'https://github.com/sodatea',\n        followers_url: 'https://api.github.com/users/sodatea/followers',\n        following_url:\n          'https://api.github.com/users/sodatea/following{/other_user}',\n        gists_url: 'https://api.github.com/users/sodatea/gists{/gist_id}',\n        starred_url:\n          'https://api.github.com/users/sodatea/starred{/owner}{/repo}',\n        subscriptions_url: 'https://api.github.com/users/sodatea/subscriptions',\n        organizations_url: 'https://api.github.com/users/sodatea/orgs',\n        repos_url: 'https://api.github.com/users/sodatea/repos',\n        events_url: 'https://api.github.com/users/sodatea/events{/privacy}',\n        received_events_url:\n          'https://api.github.com/users/sodatea/received_events',\n        type: 'User',\n        site_admin: false,\n      },\n      committer: {\n        login: 'yyx990803',\n        id: 499550,\n        node_id: 'MDQ6VXNlcjQ5OTU1MA==',\n        avatar_url: 'https://avatars1.githubusercontent.com/u/499550?v=4',\n        gravatar_id: '',\n        url: 'https://api.github.com/users/yyx990803',\n        html_url: 'https://github.com/yyx990803',\n        followers_url: 'https://api.github.com/users/yyx990803/followers',\n        following_url:\n          'https://api.github.com/users/yyx990803/following{/other_user}',\n        gists_url: 'https://api.github.com/users/yyx990803/gists{/gist_id}',\n        starred_url:\n          'https://api.github.com/users/yyx990803/starred{/owner}{/repo}',\n        subscriptions_url:\n          'https://api.github.com/users/yyx990803/subscriptions',\n        organizations_url: 'https://api.github.com/users/yyx990803/orgs',\n        repos_url: 'https://api.github.com/users/yyx990803/repos',\n        events_url: 'https://api.github.com/users/yyx990803/events{/privacy}',\n        received_events_url:\n          'https://api.github.com/users/yyx990803/received_events',\n        type: 'User',\n        site_admin: false,\n      },\n      parents: [\n        {\n          sha: '2383b45e322272ddc102d6914c149b284a25d04f',\n          url: 'https://api.github.com/repos/vuejs/core/commits/2383b45e322272ddc102d6914c149b284a25d04f',\n          html_url:\n            'https://github.com/vuejs/core/commit/2383b45e322272ddc102d6914c149b284a25d04f',\n        },\n      ],\n    },\n    {\n      sha: '2383b45e322272ddc102d6914c149b284a25d04f',\n      node_id:\n        'MDY6Q29tbWl0MTM3MDc4NDg3OjIzODNiNDVlMzIyMjcyZGRjMTAyZDY5MTRjMTQ5YjI4NGEyNWQwNGY=',\n      commit: {\n        author: {\n          name: 'GCA',\n          email: 'gcaaa31928@gmail.com',\n          date: '2019-12-09T19:23:57Z',\n        },\n        committer: {\n          name: 'Evan You',\n          email: 'yyx990803@gmail.com',\n          date: '2019-12-09T19:23:57Z',\n        },\n        message: 'chore: fix typo (#530) [ci skip]',\n        tree: {\n          sha: '2a5872ff8dc8ccb8121abd7e890ac3c0c9f1209f',\n          url: 'https://api.github.com/repos/vuejs/core/git/trees/2a5872ff8dc8ccb8121abd7e890ac3c0c9f1209f',\n        },\n        url: 'https://api.github.com/repos/vuejs/core/git/commits/2383b45e322272ddc102d6914c149b284a25d04f',\n        comment_count: 0,\n        verification: {\n          verified: false,\n          reason: 'unsigned',\n          signature: null,\n          payload: null,\n        },\n      },\n      url: 'https://api.github.com/repos/vuejs/core/commits/2383b45e322272ddc102d6914c149b284a25d04f',\n      html_url:\n        'https://github.com/vuejs/core/commit/2383b45e322272ddc102d6914c149b284a25d04f',\n      comments_url:\n        'https://api.github.com/repos/vuejs/core/commits/2383b45e322272ddc102d6914c149b284a25d04f/comments',\n      author: {\n        login: 'gcaaa31928',\n        id: 6309392,\n        node_id: 'MDQ6VXNlcjYzMDkzOTI=',\n        avatar_url: 'https://avatars1.githubusercontent.com/u/6309392?v=4',\n        gravatar_id: '',\n        url: 'https://api.github.com/users/gcaaa31928',\n        html_url: 'https://github.com/gcaaa31928',\n        followers_url: 'https://api.github.com/users/gcaaa31928/followers',\n        following_url:\n          'https://api.github.com/users/gcaaa31928/following{/other_user}',\n        gists_url: 'https://api.github.com/users/gcaaa31928/gists{/gist_id}',\n        starred_url:\n          'https://api.github.com/users/gcaaa31928/starred{/owner}{/repo}',\n        subscriptions_url:\n          'https://api.github.com/users/gcaaa31928/subscriptions',\n        organizations_url: 'https://api.github.com/users/gcaaa31928/orgs',\n        repos_url: 'https://api.github.com/users/gcaaa31928/repos',\n        events_url: 'https://api.github.com/users/gcaaa31928/events{/privacy}',\n        received_events_url:\n          'https://api.github.com/users/gcaaa31928/received_events',\n        type: 'User',\n        site_admin: false,\n      },\n      committer: {\n        login: 'yyx990803',\n        id: 499550,\n        node_id: 'MDQ6VXNlcjQ5OTU1MA==',\n        avatar_url: 'https://avatars1.githubusercontent.com/u/499550?v=4',\n        gravatar_id: '',\n        url: 'https://api.github.com/users/yyx990803',\n        html_url: 'https://github.com/yyx990803',\n        followers_url: 'https://api.github.com/users/yyx990803/followers',\n        following_url:\n          'https://api.github.com/users/yyx990803/following{/other_user}',\n        gists_url: 'https://api.github.com/users/yyx990803/gists{/gist_id}',\n        starred_url:\n          'https://api.github.com/users/yyx990803/starred{/owner}{/repo}',\n        subscriptions_url:\n          'https://api.github.com/users/yyx990803/subscriptions',\n        organizations_url: 'https://api.github.com/users/yyx990803/orgs',\n        repos_url: 'https://api.github.com/users/yyx990803/repos',\n        events_url: 'https://api.github.com/users/yyx990803/events{/privacy}',\n        received_events_url:\n          'https://api.github.com/users/yyx990803/received_events',\n        type: 'User',\n        site_admin: false,\n      },\n      parents: [\n        {\n          sha: 'e7e1314cccd1a66fcf8b8526ec21350ec16cc3ad',\n          url: 'https://api.github.com/repos/vuejs/core/commits/e7e1314cccd1a66fcf8b8526ec21350ec16cc3ad',\n          html_url:\n            'https://github.com/vuejs/core/commit/e7e1314cccd1a66fcf8b8526ec21350ec16cc3ad',\n        },\n      ],\n    },\n    {\n      sha: 'e7e1314cccd1a66fcf8b8526ec21350ec16cc3ad',\n      node_id:\n        'MDY6Q29tbWl0MTM3MDc4NDg3OmU3ZTEzMTRjY2NkMWE2NmZjZjhiODUyNmVjMjEzNTBlYzE2Y2MzYWQ=',\n      commit: {\n        author: {\n          name: 'Evan You',\n          email: 'yyx990803@gmail.com',\n          date: '2019-12-09T19:23:01Z',\n        },\n        committer: {\n          name: 'Evan You',\n          email: 'yyx990803@gmail.com',\n          date: '2019-12-09T19:23:01Z',\n        },\n        message: 'test: fix warning',\n        tree: {\n          sha: 'd942b17681e2e2fbbcd2ee04092390c7f2cf534d',\n          url: 'https://api.github.com/repos/vuejs/core/git/trees/d942b17681e2e2fbbcd2ee04092390c7f2cf534d',\n        },\n        url: 'https://api.github.com/repos/vuejs/core/git/commits/e7e1314cccd1a66fcf8b8526ec21350ec16cc3ad',\n        comment_count: 0,\n        verification: {\n          verified: false,\n          reason: 'unsigned',\n          signature: null,\n          payload: null,\n        },\n      },\n      url: 'https://api.github.com/repos/vuejs/core/commits/e7e1314cccd1a66fcf8b8526ec21350ec16cc3ad',\n      html_url:\n        'https://github.com/vuejs/core/commit/e7e1314cccd1a66fcf8b8526ec21350ec16cc3ad',\n      comments_url:\n        'https://api.github.com/repos/vuejs/core/commits/e7e1314cccd1a66fcf8b8526ec21350ec16cc3ad/comments',\n      author: {\n        login: 'yyx990803',\n        id: 499550,\n        node_id: 'MDQ6VXNlcjQ5OTU1MA==',\n        avatar_url: 'https://avatars1.githubusercontent.com/u/499550?v=4',\n        gravatar_id: '',\n        url: 'https://api.github.com/users/yyx990803',\n        html_url: 'https://github.com/yyx990803',\n        followers_url: 'https://api.github.com/users/yyx990803/followers',\n        following_url:\n          'https://api.github.com/users/yyx990803/following{/other_user}',\n        gists_url: 'https://api.github.com/users/yyx990803/gists{/gist_id}',\n        starred_url:\n          'https://api.github.com/users/yyx990803/starred{/owner}{/repo}',\n        subscriptions_url:\n          'https://api.github.com/users/yyx990803/subscriptions',\n        organizations_url: 'https://api.github.com/users/yyx990803/orgs',\n        repos_url: 'https://api.github.com/users/yyx990803/repos',\n        events_url: 'https://api.github.com/users/yyx990803/events{/privacy}',\n        received_events_url:\n          'https://api.github.com/users/yyx990803/received_events',\n        type: 'User',\n        site_admin: false,\n      },\n      committer: {\n        login: 'yyx990803',\n        id: 499550,\n        node_id: 'MDQ6VXNlcjQ5OTU1MA==',\n        avatar_url: 'https://avatars1.githubusercontent.com/u/499550?v=4',\n        gravatar_id: '',\n        url: 'https://api.github.com/users/yyx990803',\n        html_url: 'https://github.com/yyx990803',\n        followers_url: 'https://api.github.com/users/yyx990803/followers',\n        following_url:\n          'https://api.github.com/users/yyx990803/following{/other_user}',\n        gists_url: 'https://api.github.com/users/yyx990803/gists{/gist_id}',\n        starred_url:\n          'https://api.github.com/users/yyx990803/starred{/owner}{/repo}',\n        subscriptions_url:\n          'https://api.github.com/users/yyx990803/subscriptions',\n        organizations_url: 'https://api.github.com/users/yyx990803/orgs',\n        repos_url: 'https://api.github.com/users/yyx990803/repos',\n        events_url: 'https://api.github.com/users/yyx990803/events{/privacy}',\n        received_events_url:\n          'https://api.github.com/users/yyx990803/received_events',\n        type: 'User',\n        site_admin: false,\n      },\n      parents: [\n        {\n          sha: '12ec62e6881f83dfa6c7f8a3c3650ec2567e6b1e',\n          url: 'https://api.github.com/repos/vuejs/core/commits/12ec62e6881f83dfa6c7f8a3c3650ec2567e6b1e',\n          html_url:\n            'https://github.com/vuejs/core/commit/12ec62e6881f83dfa6c7f8a3c3650ec2567e6b1e',\n        },\n      ],\n    },\n  ],\n  'v2-compat': [\n    {\n      sha: 'ecf4da822eea97f5db5fa769d39f994755384a4b',\n      node_id:\n        'MDY6Q29tbWl0MTM3MDc4NDg3OmVjZjRkYTgyMmVlYTk3ZjVkYjVmYTc2OWQzOWY5OTQ3NTUzODRhNGI=',\n      commit: {\n        author: {\n          name: 'Evan You',\n          email: 'yyx990803@gmail.com',\n          date: '2018-11-13T03:42:34Z',\n        },\n        committer: {\n          name: 'Evan You',\n          email: 'yyx990803@gmail.com',\n          date: '2018-11-13T03:54:01Z',\n        },\n        message: 'chore: fix tests',\n        tree: {\n          sha: '6ac7bd078a6eb0ad32b5102e0c5d2c29f2b20a48',\n          url: 'https://api.github.com/repos/vuejs/core/git/trees/6ac7bd078a6eb0ad32b5102e0c5d2c29f2b20a48',\n        },\n        url: 'https://api.github.com/repos/vuejs/core/git/commits/ecf4da822eea97f5db5fa769d39f994755384a4b',\n        comment_count: 0,\n        verification: {\n          verified: false,\n          reason: 'unsigned',\n          signature: null,\n          payload: null,\n        },\n      },\n      url: 'https://api.github.com/repos/vuejs/core/commits/ecf4da822eea97f5db5fa769d39f994755384a4b',\n      html_url:\n        'https://github.com/vuejs/core/commit/ecf4da822eea97f5db5fa769d39f994755384a4b',\n      comments_url:\n        'https://api.github.com/repos/vuejs/core/commits/ecf4da822eea97f5db5fa769d39f994755384a4b/comments',\n      author: {\n        login: 'yyx990803',\n        id: 499550,\n        node_id: 'MDQ6VXNlcjQ5OTU1MA==',\n        avatar_url: 'https://avatars1.githubusercontent.com/u/499550?v=4',\n        gravatar_id: '',\n        url: 'https://api.github.com/users/yyx990803',\n        html_url: 'https://github.com/yyx990803',\n        followers_url: 'https://api.github.com/users/yyx990803/followers',\n        following_url:\n          'https://api.github.com/users/yyx990803/following{/other_user}',\n        gists_url: 'https://api.github.com/users/yyx990803/gists{/gist_id}',\n        starred_url:\n          'https://api.github.com/users/yyx990803/starred{/owner}{/repo}',\n        subscriptions_url:\n          'https://api.github.com/users/yyx990803/subscriptions',\n        organizations_url: 'https://api.github.com/users/yyx990803/orgs',\n        repos_url: 'https://api.github.com/users/yyx990803/repos',\n        events_url: 'https://api.github.com/users/yyx990803/events{/privacy}',\n        received_events_url:\n          'https://api.github.com/users/yyx990803/received_events',\n        type: 'User',\n        site_admin: false,\n      },\n      committer: {\n        login: 'yyx990803',\n        id: 499550,\n        node_id: 'MDQ6VXNlcjQ5OTU1MA==',\n        avatar_url: 'https://avatars1.githubusercontent.com/u/499550?v=4',\n        gravatar_id: '',\n        url: 'https://api.github.com/users/yyx990803',\n        html_url: 'https://github.com/yyx990803',\n        followers_url: 'https://api.github.com/users/yyx990803/followers',\n        following_url:\n          'https://api.github.com/users/yyx990803/following{/other_user}',\n        gists_url: 'https://api.github.com/users/yyx990803/gists{/gist_id}',\n        starred_url:\n          'https://api.github.com/users/yyx990803/starred{/owner}{/repo}',\n        subscriptions_url:\n          'https://api.github.com/users/yyx990803/subscriptions',\n        organizations_url: 'https://api.github.com/users/yyx990803/orgs',\n        repos_url: 'https://api.github.com/users/yyx990803/repos',\n        events_url: 'https://api.github.com/users/yyx990803/events{/privacy}',\n        received_events_url:\n          'https://api.github.com/users/yyx990803/received_events',\n        type: 'User',\n        site_admin: false,\n      },\n      parents: [\n        {\n          sha: 'ca296812d54aff123472d7147b83fddfb634d9bc',\n          url: 'https://api.github.com/repos/vuejs/core/commits/ca296812d54aff123472d7147b83fddfb634d9bc',\n          html_url:\n            'https://github.com/vuejs/core/commit/ca296812d54aff123472d7147b83fddfb634d9bc',\n        },\n      ],\n    },\n    {\n      sha: 'ca296812d54aff123472d7147b83fddfb634d9bc',\n      node_id:\n        'MDY6Q29tbWl0MTM3MDc4NDg3OmNhMjk2ODEyZDU0YWZmMTIzNDcyZDcxNDdiODNmZGRmYjYzNGQ5YmM=',\n      commit: {\n        author: {\n          name: 'Evan You',\n          email: 'yyx990803@gmail.com',\n          date: '2018-11-13T03:21:56Z',\n        },\n        committer: {\n          name: 'Evan You',\n          email: 'yyx990803@gmail.com',\n          date: '2018-11-13T03:46:06Z',\n        },\n        message: 'refactor: bring back clone for reused nodes',\n        tree: {\n          sha: '2cec32c97686e0ee9af1b87f0abdbbbdc18b6de6',\n          url: 'https://api.github.com/repos/vuejs/core/git/trees/2cec32c97686e0ee9af1b87f0abdbbbdc18b6de6',\n        },\n        url: 'https://api.github.com/repos/vuejs/core/git/commits/ca296812d54aff123472d7147b83fddfb634d9bc',\n        comment_count: 0,\n        verification: {\n          verified: false,\n          reason: 'unsigned',\n          signature: null,\n          payload: null,\n        },\n      },\n      url: 'https://api.github.com/repos/vuejs/core/commits/ca296812d54aff123472d7147b83fddfb634d9bc',\n      html_url:\n        'https://github.com/vuejs/core/commit/ca296812d54aff123472d7147b83fddfb634d9bc',\n      comments_url:\n        'https://api.github.com/repos/vuejs/core/commits/ca296812d54aff123472d7147b83fddfb634d9bc/comments',\n      author: {\n        login: 'yyx990803',\n        id: 499550,\n        node_id: 'MDQ6VXNlcjQ5OTU1MA==',\n        avatar_url: 'https://avatars1.githubusercontent.com/u/499550?v=4',\n        gravatar_id: '',\n        url: 'https://api.github.com/users/yyx990803',\n        html_url: 'https://github.com/yyx990803',\n        followers_url: 'https://api.github.com/users/yyx990803/followers',\n        following_url:\n          'https://api.github.com/users/yyx990803/following{/other_user}',\n        gists_url: 'https://api.github.com/users/yyx990803/gists{/gist_id}',\n        starred_url:\n          'https://api.github.com/users/yyx990803/starred{/owner}{/repo}',\n        subscriptions_url:\n          'https://api.github.com/users/yyx990803/subscriptions',\n        organizations_url: 'https://api.github.com/users/yyx990803/orgs',\n        repos_url: 'https://api.github.com/users/yyx990803/repos',\n        events_url: 'https://api.github.com/users/yyx990803/events{/privacy}',\n        received_events_url:\n          'https://api.github.com/users/yyx990803/received_events',\n        type: 'User',\n        site_admin: false,\n      },\n      committer: {\n        login: 'yyx990803',\n        id: 499550,\n        node_id: 'MDQ6VXNlcjQ5OTU1MA==',\n        avatar_url: 'https://avatars1.githubusercontent.com/u/499550?v=4',\n        gravatar_id: '',\n        url: 'https://api.github.com/users/yyx990803',\n        html_url: 'https://github.com/yyx990803',\n        followers_url: 'https://api.github.com/users/yyx990803/followers',\n        following_url:\n          'https://api.github.com/users/yyx990803/following{/other_user}',\n        gists_url: 'https://api.github.com/users/yyx990803/gists{/gist_id}',\n        starred_url:\n          'https://api.github.com/users/yyx990803/starred{/owner}{/repo}',\n        subscriptions_url:\n          'https://api.github.com/users/yyx990803/subscriptions',\n        organizations_url: 'https://api.github.com/users/yyx990803/orgs',\n        repos_url: 'https://api.github.com/users/yyx990803/repos',\n        events_url: 'https://api.github.com/users/yyx990803/events{/privacy}',\n        received_events_url:\n          'https://api.github.com/users/yyx990803/received_events',\n        type: 'User',\n        site_admin: false,\n      },\n      parents: [\n        {\n          sha: 'e6be55a4989edb6f8750dbaa14eb693ec1f0d67b',\n          url: 'https://api.github.com/repos/vuejs/core/commits/e6be55a4989edb6f8750dbaa14eb693ec1f0d67b',\n          html_url:\n            'https://github.com/vuejs/core/commit/e6be55a4989edb6f8750dbaa14eb693ec1f0d67b',\n        },\n      ],\n    },\n    {\n      sha: 'e6be55a4989edb6f8750dbaa14eb693ec1f0d67b',\n      node_id:\n        'MDY6Q29tbWl0MTM3MDc4NDg3OmU2YmU1NWE0OTg5ZWRiNmY4NzUwZGJhYTE0ZWI2OTNlYzFmMGQ2N2I=',\n      commit: {\n        author: {\n          name: 'Evan You',\n          email: 'yyx990803@gmail.com',\n          date: '2018-11-02T20:59:45Z',\n        },\n        committer: {\n          name: 'Evan You',\n          email: 'yyx990803@gmail.com',\n          date: '2018-11-02T20:59:45Z',\n        },\n        message: 'chore: relax render type for tsx',\n        tree: {\n          sha: '7e2b3bb92ab91f755b2251e4a7903e6dd2042602',\n          url: 'https://api.github.com/repos/vuejs/core/git/trees/7e2b3bb92ab91f755b2251e4a7903e6dd2042602',\n        },\n        url: 'https://api.github.com/repos/vuejs/core/git/commits/e6be55a4989edb6f8750dbaa14eb693ec1f0d67b',\n        comment_count: 0,\n        verification: {\n          verified: false,\n          reason: 'unsigned',\n          signature: null,\n          payload: null,\n        },\n      },\n      url: 'https://api.github.com/repos/vuejs/core/commits/e6be55a4989edb6f8750dbaa14eb693ec1f0d67b',\n      html_url:\n        'https://github.com/vuejs/core/commit/e6be55a4989edb6f8750dbaa14eb693ec1f0d67b',\n      comments_url:\n        'https://api.github.com/repos/vuejs/core/commits/e6be55a4989edb6f8750dbaa14eb693ec1f0d67b/comments',\n      author: {\n        login: 'yyx990803',\n        id: 499550,\n        node_id: 'MDQ6VXNlcjQ5OTU1MA==',\n        avatar_url: 'https://avatars1.githubusercontent.com/u/499550?v=4',\n        gravatar_id: '',\n        url: 'https://api.github.com/users/yyx990803',\n        html_url: 'https://github.com/yyx990803',\n        followers_url: 'https://api.github.com/users/yyx990803/followers',\n        following_url:\n          'https://api.github.com/users/yyx990803/following{/other_user}',\n        gists_url: 'https://api.github.com/users/yyx990803/gists{/gist_id}',\n        starred_url:\n          'https://api.github.com/users/yyx990803/starred{/owner}{/repo}',\n        subscriptions_url:\n          'https://api.github.com/users/yyx990803/subscriptions',\n        organizations_url: 'https://api.github.com/users/yyx990803/orgs',\n        repos_url: 'https://api.github.com/users/yyx990803/repos',\n        events_url: 'https://api.github.com/users/yyx990803/events{/privacy}',\n        received_events_url:\n          'https://api.github.com/users/yyx990803/received_events',\n        type: 'User',\n        site_admin: false,\n      },\n      committer: {\n        login: 'yyx990803',\n        id: 499550,\n        node_id: 'MDQ6VXNlcjQ5OTU1MA==',\n        avatar_url: 'https://avatars1.githubusercontent.com/u/499550?v=4',\n        gravatar_id: '',\n        url: 'https://api.github.com/users/yyx990803',\n        html_url: 'https://github.com/yyx990803',\n        followers_url: 'https://api.github.com/users/yyx990803/followers',\n        following_url:\n          'https://api.github.com/users/yyx990803/following{/other_user}',\n        gists_url: 'https://api.github.com/users/yyx990803/gists{/gist_id}',\n        starred_url:\n          'https://api.github.com/users/yyx990803/starred{/owner}{/repo}',\n        subscriptions_url:\n          'https://api.github.com/users/yyx990803/subscriptions',\n        organizations_url: 'https://api.github.com/users/yyx990803/orgs',\n        repos_url: 'https://api.github.com/users/yyx990803/repos',\n        events_url: 'https://api.github.com/users/yyx990803/events{/privacy}',\n        received_events_url:\n          'https://api.github.com/users/yyx990803/received_events',\n        type: 'User',\n        site_admin: false,\n      },\n      parents: [\n        {\n          sha: 'ccc835caff0344baad3c92ce786ad4f804bf667b',\n          url: 'https://api.github.com/repos/vuejs/core/commits/ccc835caff0344baad3c92ce786ad4f804bf667b',\n          html_url:\n            'https://github.com/vuejs/core/commit/ccc835caff0344baad3c92ce786ad4f804bf667b',\n        },\n      ],\n    },\n  ],\n} as any\n"
  },
  {
    "path": "packages/vue/__tests__/e2e/commits.spec.ts",
    "content": "import path from 'node:path'\nimport { E2E_TIMEOUT, setupPuppeteer } from './e2eUtils'\nimport mocks from './commits.mock'\n\ndescribe('e2e: commits', () => {\n  const { page, click, count, text, isChecked } = setupPuppeteer()\n\n  async function testCommits(apiType: 'classic' | 'composition') {\n    const baseUrl = `file://${path.resolve(\n      __dirname,\n      `../../examples/${apiType}/commits.html`,\n    )}`\n\n    // intercept and mock the response to avoid hitting the actual API\n    await page().setRequestInterception(true)\n    page().on('request', req => {\n      const match = req.url().match(/&sha=(.*)$/)\n      if (!match) {\n        req.continue()\n      } else {\n        req.respond({\n          status: 200,\n          contentType: 'application/json',\n          headers: { 'Access-Control-Allow-Origin': '*' },\n          body: JSON.stringify(mocks[match[1] as 'main' | 'v2-compat']),\n        })\n      }\n    })\n\n    await page().goto(baseUrl)\n    await page().waitForSelector('li')\n    expect(await count('input')).toBe(2)\n    expect(await count('label')).toBe(2)\n    expect(await text('label[for=\"main\"]')).toBe('main')\n    expect(await text('label[for=\"v2-compat\"]')).toBe('v2-compat')\n    expect(await isChecked('#main')).toBe(true)\n    expect(await isChecked('#v2-compat')).toBe(false)\n    expect(await text('p')).toBe('vuejs/core@main')\n    expect(await count('li')).toBe(3)\n    expect(await count('li .commit')).toBe(3)\n    expect(await count('li .message')).toBe(3)\n    await click('#v2-compat')\n    expect(await text('p')).toBe('vuejs/core@v2-compat')\n    expect(await count('li')).toBe(3)\n    expect(await count('li .commit')).toBe(3)\n    expect(await count('li .message')).toBe(3)\n  }\n\n  test(\n    'classic',\n    async () => {\n      await testCommits('classic')\n    },\n    E2E_TIMEOUT,\n  )\n\n  test(\n    'composition',\n    async () => {\n      await testCommits('composition')\n    },\n    E2E_TIMEOUT,\n  )\n})\n"
  },
  {
    "path": "packages/vue/__tests__/e2e/e2eUtils.ts",
    "content": "import puppeteer, {\n  type Browser,\n  type ClickOptions,\n  type LaunchOptions,\n  type Page,\n} from 'puppeteer'\n\nexport const E2E_TIMEOUT: number = 30 * 1000\n\nconst puppeteerOptions: LaunchOptions = {\n  args: process.env.CI ? ['--no-sandbox', '--disable-setuid-sandbox'] : [],\n  headless: true,\n}\n\nconst maxTries = 30\nexport const timeout = (n: number): Promise<any> =>\n  new Promise(r => setTimeout(r, n))\n\nexport async function expectByPolling(\n  poll: () => Promise<any>,\n  expected: string,\n): Promise<void> {\n  for (let tries = 0; tries < maxTries; tries++) {\n    const actual = (await poll()) || ''\n    if (actual.indexOf(expected) > -1 || tries === maxTries - 1) {\n      expect(actual).toMatch(expected)\n      break\n    } else {\n      await timeout(50)\n    }\n  }\n}\n\ninterface PuppeteerUtils {\n  page: () => Page\n  click(selector: string, options?: ClickOptions): Promise<void>\n  count(selector: string): Promise<number>\n  text(selector: string): Promise<string | null>\n  value(selector: string): Promise<string>\n  html(selector: string): Promise<string>\n  classList(selector: string): Promise<string[]>\n  style(selector: string, property: keyof CSSStyleDeclaration): Promise<any>\n  children(selector: string): Promise<any[]>\n  isVisible(selector: string): Promise<boolean>\n  isChecked(selector: string): Promise<boolean>\n  isFocused(selector: string): Promise<boolean>\n  setValue(selector: string, value: string): Promise<any>\n  typeValue(selector: string, value: string): Promise<any>\n  enterValue(selector: string, value: string): Promise<any>\n  clearValue(selector: string): Promise<any>\n  timeout(time: number): Promise<any>\n  nextFrame(): Promise<any>\n}\n\nexport function setupPuppeteer(args?: string[]): PuppeteerUtils {\n  let browser: Browser\n  let page: Page\n\n  const resolvedOptions = args\n    ? {\n        ...puppeteerOptions,\n        args: [...puppeteerOptions.args!, ...args],\n      }\n    : puppeteerOptions\n\n  beforeAll(async () => {\n    browser = await puppeteer.launch(resolvedOptions)\n  }, 20000)\n\n  beforeEach(async () => {\n    page = await browser.newPage()\n\n    await page.evaluateOnNewDocument(() => {\n      localStorage.clear()\n    })\n\n    page.on('console', e => {\n      if (e.type() === 'error') {\n        const err = e.args()[0]\n        console.error(`Error from Puppeteer-loaded page:\\n`, err.remoteObject())\n      }\n    })\n  })\n\n  afterEach(async () => {\n    await page.close()\n  })\n\n  afterAll(async () => {\n    await browser.close()\n  })\n\n  async function click(\n    selector: string,\n    options?: ClickOptions,\n  ): Promise<void> {\n    await page.click(selector, options)\n  }\n\n  async function count(selector: string): Promise<number> {\n    return (await page.$$(selector)).length\n  }\n\n  async function text(selector: string): Promise<string | null> {\n    return page.$eval(selector, node => node.textContent)\n  }\n\n  async function value(selector: string): Promise<string> {\n    return page.$eval(selector, node => (node as HTMLInputElement).value)\n  }\n\n  async function html(selector: string): Promise<string> {\n    return page.$eval(selector, node => node.innerHTML)\n  }\n\n  async function classList(selector: string): Promise<string[]> {\n    return page.$eval(selector, (node: any) => [...node.classList])\n  }\n\n  async function children(selector: string): Promise<any[]> {\n    return page.$eval(selector, (node: any) => [...node.children])\n  }\n\n  async function style(\n    selector: string,\n    property: keyof CSSStyleDeclaration,\n  ): Promise<any> {\n    return await page.$eval(\n      selector,\n      (node, property) => {\n        return window.getComputedStyle(node)[property]\n      },\n      property,\n    )\n  }\n\n  async function isVisible(selector: string): Promise<boolean> {\n    const display = await page.$eval(selector, node => {\n      return window.getComputedStyle(node).display\n    })\n    return display !== 'none'\n  }\n\n  async function isChecked(selector: string) {\n    return await page.$eval(\n      selector,\n      node => (node as HTMLInputElement).checked,\n    )\n  }\n\n  async function isFocused(selector: string) {\n    return await page.$eval(selector, node => node === document.activeElement)\n  }\n\n  async function setValue(selector: string, value: string) {\n    await page.$eval(\n      selector,\n      (node, value) => {\n        ;(node as HTMLInputElement).value = value as string\n        node.dispatchEvent(new Event('input'))\n      },\n      value,\n    )\n  }\n\n  async function typeValue(selector: string, value: string) {\n    const el = (await page.$(selector))!\n    await el.evaluate(node => ((node as HTMLInputElement).value = ''))\n    await el.type(value)\n  }\n\n  async function enterValue(selector: string, value: string) {\n    const el = (await page.$(selector))!\n    await el.evaluate(node => ((node as HTMLInputElement).value = ''))\n    await el.type(value)\n    await el.press('Enter')\n  }\n\n  async function clearValue(selector: string) {\n    return await page.$eval(\n      selector,\n      node => ((node as HTMLInputElement).value = ''),\n    )\n  }\n\n  function timeout(time: number) {\n    return page.evaluate(time => {\n      return new Promise(r => {\n        setTimeout(r, time)\n      })\n    }, time)\n  }\n\n  function nextFrame() {\n    return page.evaluate(() => {\n      return new Promise(resolve => {\n        requestAnimationFrame(() => {\n          requestAnimationFrame(resolve)\n        })\n      })\n    })\n  }\n\n  return {\n    page: () => page,\n    click,\n    count,\n    text,\n    value,\n    html,\n    classList,\n    style,\n    children,\n    isVisible,\n    isChecked,\n    isFocused,\n    setValue,\n    typeValue,\n    enterValue,\n    clearValue,\n    timeout,\n    nextFrame,\n  }\n}\n"
  },
  {
    "path": "packages/vue/__tests__/e2e/grid.spec.ts",
    "content": "import path from 'node:path'\nimport { E2E_TIMEOUT, setupPuppeteer } from './e2eUtils'\n\ninterface TableData {\n  name: string\n  power: number\n}\n\ndescribe('e2e: grid', () => {\n  const { page, click, text, count, typeValue, clearValue } = setupPuppeteer()\n  const columns = ['name', 'power'] as const\n\n  async function assertTable(data: TableData[]) {\n    expect(await count('td')).toBe(data.length * columns.length)\n    for (let i = 0; i < data.length; i++) {\n      for (let j = 0; j < columns.length; j++) {\n        expect(\n          await text(`tr:nth-child(${i + 1}) td:nth-child(${j + 1})`),\n        ).toContain(`${data[i][columns[j]]}`)\n      }\n    }\n  }\n\n  async function testGrid(apiType: 'classic' | 'composition') {\n    const baseUrl = `file://${path.resolve(\n      __dirname,\n      `../../examples/${apiType}/grid.html`,\n    )}`\n\n    await page().goto(baseUrl)\n    await page().waitForSelector('table')\n    expect(await count('th')).toBe(2)\n    expect(await count('th.active')).toBe(0)\n    expect(await text('th:nth-child(1)')).toContain('Name')\n    expect(await text('th:nth-child(2)')).toContain('Power')\n    await assertTable([\n      { name: 'Chuck Norris', power: Infinity },\n      { name: 'Bruce Lee', power: 9000 },\n      { name: 'Jackie Chan', power: 7000 },\n      { name: 'Jet Li', power: 8000 },\n    ])\n\n    await click('th:nth-child(1)')\n    expect(await count('th.active:nth-child(1)')).toBe(1)\n    expect(await count('th.active:nth-child(2)')).toBe(0)\n    expect(await count('th:nth-child(1) .arrow.dsc')).toBe(1)\n    expect(await count('th:nth-child(2) .arrow.dsc')).toBe(0)\n    await assertTable([\n      { name: 'Jet Li', power: 8000 },\n      { name: 'Jackie Chan', power: 7000 },\n      { name: 'Chuck Norris', power: Infinity },\n      { name: 'Bruce Lee', power: 9000 },\n    ])\n\n    await click('th:nth-child(2)')\n    expect(await count('th.active:nth-child(1)')).toBe(0)\n    expect(await count('th.active:nth-child(2)')).toBe(1)\n    expect(await count('th:nth-child(1) .arrow.dsc')).toBe(1)\n    expect(await count('th:nth-child(2) .arrow.dsc')).toBe(1)\n    await assertTable([\n      { name: 'Chuck Norris', power: Infinity },\n      { name: 'Bruce Lee', power: 9000 },\n      { name: 'Jet Li', power: 8000 },\n      { name: 'Jackie Chan', power: 7000 },\n    ])\n\n    await click('th:nth-child(2)')\n    expect(await count('th.active:nth-child(1)')).toBe(0)\n    expect(await count('th.active:nth-child(2)')).toBe(1)\n    expect(await count('th:nth-child(1) .arrow.dsc')).toBe(1)\n    expect(await count('th:nth-child(2) .arrow.asc')).toBe(1)\n    await assertTable([\n      { name: 'Jackie Chan', power: 7000 },\n      { name: 'Jet Li', power: 8000 },\n      { name: 'Bruce Lee', power: 9000 },\n      { name: 'Chuck Norris', power: Infinity },\n    ])\n\n    await click('th:nth-child(1)')\n    expect(await count('th.active:nth-child(1)')).toBe(1)\n    expect(await count('th.active:nth-child(2)')).toBe(0)\n    expect(await count('th:nth-child(1) .arrow.asc')).toBe(1)\n    expect(await count('th:nth-child(2) .arrow.asc')).toBe(1)\n    await assertTable([\n      { name: 'Bruce Lee', power: 9000 },\n      { name: 'Chuck Norris', power: Infinity },\n      { name: 'Jackie Chan', power: 7000 },\n      { name: 'Jet Li', power: 8000 },\n    ])\n\n    await typeValue('input[name=\"query\"]', 'j')\n    await assertTable([\n      { name: 'Jackie Chan', power: 7000 },\n      { name: 'Jet Li', power: 8000 },\n    ])\n\n    await typeValue('input[name=\"query\"]', 'infinity')\n    await assertTable([{ name: 'Chuck Norris', power: Infinity }])\n\n    await clearValue('input[name=\"query\"]')\n    expect(await count('p')).toBe(0)\n    await typeValue('input[name=\"query\"]', 'stringthatdoesnotexistanywhere')\n    expect(await count('p')).toBe(1)\n  }\n\n  test(\n    'classic',\n    async () => {\n      await testGrid('classic')\n    },\n    E2E_TIMEOUT,\n  )\n\n  test(\n    'composition',\n    async () => {\n      await testGrid('composition')\n    },\n    E2E_TIMEOUT,\n  )\n})\n"
  },
  {
    "path": "packages/vue/__tests__/e2e/hydration-strat-custom.html",
    "content": "<script src=\"../../dist/vue.global.js\"></script>\n\n<div><span id=\"custom-trigger\">click here to hydrate</span></div>\n<div id=\"app\"><button>0</button></div>\n\n<script>\n  window.isHydrated = false\n  const { createSSRApp, defineAsyncComponent, h, ref, onMounted } = Vue\n\n  const Comp = {\n    setup() {\n      const count = ref(0)\n      onMounted(() => {\n        console.log('hydrated')\n        window.isHydrated = true\n      })\n      return () => {\n        return h('button', { onClick: () => count.value++ }, count.value)\n      }\n    },\n  }\n\n  const AsyncComp = defineAsyncComponent({\n    loader: () => Promise.resolve(Comp),\n    hydrate: (hydrate, el) => {\n      const triggerEl = document.getElementById('custom-trigger')\n      triggerEl.addEventListener('click', hydrate, { once: true })\n      return () => {\n        window.teardownCalled = true\n        triggerEl.removeEventListener('click', hydrate)\n      }\n    },\n  })\n\n  const show = (window.show = ref(true))\n  createSSRApp({\n    setup() {\n      onMounted(() => {\n        window.isRootMounted = true\n      })\n      return () => (show.value ? h(AsyncComp) : 'off')\n    },\n  }).mount('#app')\n</script>\n"
  },
  {
    "path": "packages/vue/__tests__/e2e/hydration-strat-idle.html",
    "content": "<script src=\"../../dist/vue.global.js\"></script>\n\n<div id=\"app\"><button>0</button></div>\n\n<script>\n  window.isHydrated = false\n  const {\n    createSSRApp,\n    defineAsyncComponent,\n    h,\n    ref,\n    onMounted,\n    hydrateOnIdle,\n  } = Vue\n\n  const Comp = {\n    setup() {\n      const count = ref(0)\n      onMounted(() => {\n        console.log('hydrated')\n        window.isHydrated = true\n      })\n      return () => h('button', { onClick: () => count.value++ }, count.value)\n    },\n  }\n\n  const AsyncComp = defineAsyncComponent({\n    loader: () =>\n      new Promise(resolve => {\n        setTimeout(() => {\n          console.log('resolve')\n          resolve(Comp)\n          requestIdleCallback(() => {\n            console.log('busy')\n          })\n        }, 10)\n      }),\n    hydrate: hydrateOnIdle(),\n  })\n\n  createSSRApp({\n    render: () => h(AsyncComp),\n  }).mount('#app')\n</script>\n"
  },
  {
    "path": "packages/vue/__tests__/e2e/hydration-strat-interaction.html",
    "content": "<script src=\"../../dist/vue.global.js\"></script>\n\n<div>click to hydrate</div>\n<div id=\"app\"><button>0</button></div>\n<style>\n  body {\n    margin: 0;\n  }\n</style>\n\n<script>\n  const isFragment = location.search.includes('?fragment')\n  if (isFragment) {\n    document.getElementById('app').innerHTML =\n      `<!--[--><!--[--><span>one</span><!--]--><button>0</button><span>two</span><!--]-->`\n  }\n\n  window.isHydrated = false\n  const {\n    createSSRApp,\n    defineAsyncComponent,\n    h,\n    ref,\n    onMounted,\n    hydrateOnInteraction,\n  } = Vue\n\n  const Comp = {\n    setup() {\n      const count = ref(0)\n      onMounted(() => {\n        console.log('hydrated')\n        window.isHydrated = true\n      })\n      return () => {\n        const button = h(\n          'button',\n          { onClick: () => count.value++ },\n          count.value,\n        )\n        if (isFragment) {\n          return [[h('span', 'one')], button, h('span', 'two')]\n        } else {\n          return button\n        }\n      }\n    },\n  }\n\n  const AsyncComp = defineAsyncComponent({\n    loader: () => Promise.resolve(Comp),\n    hydrate: hydrateOnInteraction(['click', 'wheel']),\n  })\n\n  createSSRApp({\n    setup() {\n      onMounted(() => {\n        window.isRootMounted = true\n      })\n      return () => h(AsyncComp)\n    },\n  }).mount('#app')\n</script>\n"
  },
  {
    "path": "packages/vue/__tests__/e2e/hydration-strat-media.html",
    "content": "<script src=\"../../dist/vue.global.js\"></script>\n\n<div>resize the window width to < 500px to hydrate</div>\n<div id=\"app\"><button>0</button></div>\n\n<script>\n  window.isHydrated = false\n  const {\n    createSSRApp,\n    defineAsyncComponent,\n    h,\n    ref,\n    onMounted,\n    hydrateOnMediaQuery,\n  } = Vue\n\n  const Comp = {\n    props: {\n      value: Boolean,\n    },\n    setup(props) {\n      const count = ref(0)\n      onMounted(() => {\n        console.log('hydrated')\n        window.isHydrated = true\n      })\n      return () => {\n        props.value\n        return h('button', { onClick: () => count.value++ }, count.value)\n      }\n    },\n  }\n\n  const AsyncComp = defineAsyncComponent({\n    loader: () => Promise.resolve(Comp),\n    hydrate: hydrateOnMediaQuery('(max-width:500px)'),\n  })\n\n  createSSRApp({\n    setup() {\n      onMounted(() => {\n        window.isRootMounted = true\n      })\n\n      const show = (window.show = ref(true))\n      return () => h(AsyncComp, { value: show.value })\n    },\n  }).mount('#app')\n</script>\n"
  },
  {
    "path": "packages/vue/__tests__/e2e/hydration-strat-visible.html",
    "content": "<script src=\"../../dist/vue.global.js\"></script>\n\n<div style=\"height: 1000px\">scroll to the bottom to hydrate</div>\n<div id=\"app\"><button>0</button></div>\n<style>\n  body {\n    margin: 0;\n  }\n</style>\n\n<script>\n  const rootMargin = location.search.match(/rootMargin=(\\d+)/)?.[1] ?? 0\n  const isFragment = location.search.includes('?fragment')\n  const isVIf = location.search.includes('?v-if')\n  if (isFragment) {\n    document.getElementById('app').innerHTML =\n      `<!--[--><!--[--><span>one</span><!--]--><button>0</button><span>two</span><!--]-->`\n  } else if (isVIf) {\n    document.getElementById('app').innerHTML = `<!---->`\n  }\n\n  window.isHydrated = false\n  const {\n    createSSRApp,\n    defineAsyncComponent,\n    h,\n    ref,\n    onMounted,\n    hydrateOnVisible,\n    createCommentVNode,\n  } = Vue\n\n  const Comp = {\n    setup() {\n      const count = ref(0)\n      onMounted(() => {\n        console.log('hydrated')\n        window.isHydrated = true\n      })\n      return () => {\n        const button = h(\n          'button',\n          { onClick: () => count.value++ },\n          count.value,\n        )\n        if (isVIf) {\n          return createCommentVNode('v-if', true)\n        } else if (isFragment) {\n          return [[h('span', 'one')], button, h('span', 'two')]\n        } else {\n          return button\n        }\n      }\n    },\n  }\n\n  const AsyncComp = defineAsyncComponent({\n    loader: () => Promise.resolve(Comp),\n    hydrate: hydrateOnVisible({ rootMargin: rootMargin + 'px' }),\n  })\n\n  createSSRApp({\n    setup() {\n      onMounted(() => {\n        window.isRootMounted = true\n      })\n      return () => h(AsyncComp)\n    },\n  }).mount('#app')\n</script>\n"
  },
  {
    "path": "packages/vue/__tests__/e2e/hydrationStrategies.spec.ts",
    "content": "import path from 'node:path'\nimport { setupPuppeteer } from './e2eUtils'\nimport type { Ref } from '../../src/runtime'\n\ndeclare const window: Window & {\n  isHydrated: boolean\n  isRootMounted: boolean\n  teardownCalled?: boolean\n  show: Ref<boolean>\n}\n\ndescribe('async component hydration strategies', () => {\n  const { page, click, text, count } = setupPuppeteer(['--window-size=800,600'])\n\n  async function goToCase(name: string, query = '') {\n    const file = `file://${path.resolve(__dirname, `./hydration-strat-${name}.html${query}`)}`\n    await page().goto(file)\n  }\n\n  async function assertHydrationSuccess(n = '1') {\n    await click('button')\n    expect(await text('button')).toBe(n)\n  }\n\n  test('idle', async () => {\n    const messages: string[] = []\n    page().on('console', e => messages.push(e.text()))\n\n    await goToCase('idle')\n    // not hydrated yet\n    expect(await page().evaluate(() => window.isHydrated)).toBe(false)\n    // wait for hydration\n    await page().waitForFunction(() => window.isHydrated)\n    // assert message order: hyration should happen after already queued main thread work\n    expect(messages.slice(1)).toMatchObject(['resolve', 'busy', 'hydrated'])\n    await assertHydrationSuccess()\n  })\n\n  test('visible', async () => {\n    await goToCase('visible')\n    await page().waitForFunction(() => window.isRootMounted)\n    expect(await page().evaluate(() => window.isHydrated)).toBe(false)\n    // scroll down\n    await page().evaluate(() => window.scrollTo({ top: 1000 }))\n    await page().waitForFunction(() => window.isHydrated)\n    await assertHydrationSuccess()\n  })\n\n  test('visible (with rootMargin)', async () => {\n    await goToCase('visible', '?rootMargin=1000')\n    await page().waitForFunction(() => window.isRootMounted)\n    // should hydrate without needing to scroll\n    await page().waitForFunction(() => window.isHydrated)\n    await assertHydrationSuccess()\n  })\n\n  test('visible (fragment)', async () => {\n    await goToCase('visible', '?fragment')\n    await page().waitForFunction(() => window.isRootMounted)\n    expect(await page().evaluate(() => window.isHydrated)).toBe(false)\n    expect(await count('span')).toBe(2)\n    // scroll down\n    await page().evaluate(() => window.scrollTo({ top: 1000 }))\n    await page().waitForFunction(() => window.isHydrated)\n    await assertHydrationSuccess()\n  })\n\n  test('visible (root v-if) should not throw error', async () => {\n    const spy = vi.fn()\n    const currentPage = page()\n    currentPage.on('pageerror', spy)\n    await goToCase('visible', '?v-if')\n    await page().waitForFunction(() => window.isRootMounted)\n    expect(await page().evaluate(() => window.isHydrated)).toBe(false)\n    expect(spy).toBeCalledTimes(0)\n    currentPage.off('pageerror', spy)\n  })\n\n  test('media query', async () => {\n    await goToCase('media')\n    await page().waitForFunction(() => window.isRootMounted)\n    expect(await page().evaluate(() => window.isHydrated)).toBe(false)\n    // resize\n    await page().setViewport({ width: 400, height: 600 })\n    await page().waitForFunction(() => window.isHydrated)\n    await assertHydrationSuccess()\n  })\n\n  // #13255\n  test('media query (patched before hydration)', async () => {\n    const spy = vi.fn()\n    const currentPage = page()\n    currentPage.on('pageerror', spy)\n\n    const warn: any[] = []\n    currentPage.on('console', e => warn.push(e.text()))\n\n    await goToCase('media')\n    await page().waitForFunction(() => window.isRootMounted)\n    expect(await page().evaluate(() => window.isHydrated)).toBe(false)\n\n    // patch\n    await page().evaluate(() => (window.show.value = false))\n    await click('button')\n    expect(await text('button')).toBe('1')\n\n    // resize\n    await page().setViewport({ width: 400, height: 600 })\n    await page().waitForFunction(() => window.isHydrated)\n    await assertHydrationSuccess('2')\n\n    expect(spy).toBeCalledTimes(0)\n    currentPage.off('pageerror', spy)\n    expect(\n      warn.some(w => w.includes('Skipping lazy hydration for component')),\n    ).toBe(true)\n  })\n\n  test('interaction', async () => {\n    await goToCase('interaction')\n    await page().waitForFunction(() => window.isRootMounted)\n    expect(await page().evaluate(() => window.isHydrated)).toBe(false)\n    await click('button')\n    await page().waitForFunction(() => window.isHydrated)\n    // should replay event\n    expect(await text('button')).toBe('1')\n    await assertHydrationSuccess('2')\n  })\n\n  test('interaction (fragment)', async () => {\n    await goToCase('interaction', '?fragment')\n    await page().waitForFunction(() => window.isRootMounted)\n    expect(await page().evaluate(() => window.isHydrated)).toBe(false)\n    await click('button')\n    await page().waitForFunction(() => window.isHydrated)\n    // should replay event\n    expect(await text('button')).toBe('1')\n    await assertHydrationSuccess('2')\n  })\n\n  test('custom', async () => {\n    await goToCase('custom')\n    await page().waitForFunction(() => window.isRootMounted)\n    expect(await page().evaluate(() => window.isHydrated)).toBe(false)\n    await click('#custom-trigger')\n    await page().waitForFunction(() => window.isHydrated)\n    await assertHydrationSuccess()\n  })\n\n  test('custom teardown', async () => {\n    await goToCase('custom')\n    await page().waitForFunction(() => window.isRootMounted)\n    expect(await page().evaluate(() => window.isHydrated)).toBe(false)\n    await page().evaluate(() => (window.show.value = false))\n    expect(await text('#app')).toBe('off')\n    expect(await page().evaluate(() => window.isHydrated)).toBe(false)\n    expect(await page().evaluate(() => window.teardownCalled)).toBe(true)\n  })\n})\n"
  },
  {
    "path": "packages/vue/__tests__/e2e/markdown.spec.ts",
    "content": "import path from 'node:path'\nimport { E2E_TIMEOUT, expectByPolling, setupPuppeteer } from './e2eUtils'\n\ndescribe('e2e: markdown', () => {\n  const { page, isVisible, value, html } = setupPuppeteer()\n\n  async function testMarkdown(apiType: 'classic' | 'composition') {\n    const baseUrl = `file://${path.resolve(\n      __dirname,\n      `../../examples/${apiType}/markdown.html#test`,\n    )}`\n\n    await page().goto(baseUrl)\n    expect(await isVisible('#editor')).toBe(true)\n    expect(await value('textarea')).toBe('# hello')\n    expect(await html('#editor div')).toBe('<h1>hello</h1>\\n')\n\n    await page().type('textarea', '\\n## foo\\n\\n- bar\\n- baz')\n\n    // assert the output is not updated yet because of debounce\n    // debounce has become unstable on CI so this assertion is disabled\n    // expect(await html('#editor div')).toBe('<h1 id=\"hello\">hello</h1>\\n')\n\n    await expectByPolling(\n      () => html('#editor div'),\n      '<h1>hello</h1>\\n' +\n        '<h2>foo</h2>\\n' +\n        '<ul>\\n<li>bar</li>\\n<li>baz</li>\\n</ul>\\n',\n    )\n  }\n\n  test(\n    'classic',\n    async () => {\n      await testMarkdown('classic')\n    },\n    E2E_TIMEOUT,\n  )\n\n  test(\n    'composition',\n    async () => {\n      await testMarkdown('composition')\n    },\n    E2E_TIMEOUT,\n  )\n})\n"
  },
  {
    "path": "packages/vue/__tests__/e2e/memory-leak.spec.ts",
    "content": "import { E2E_TIMEOUT, setupPuppeteer } from './e2eUtils'\nimport path from 'node:path'\n\nconst { page, html, click } = setupPuppeteer()\n\nbeforeEach(async () => {\n  await page().setContent(`<div id=\"app\"></div>`)\n  await page().addScriptTag({\n    path: path.resolve(__dirname, '../../dist/vue.global.js'),\n  })\n})\n\ndescribe('not leaking', async () => {\n  // #13661\n  test(\n    'cached text vnodes should not retaining detached DOM nodes',\n    async () => {\n      const client = await page().createCDPSession()\n      await page().evaluate(async () => {\n        const { createApp, ref } = (window as any).Vue\n        createApp({\n          components: {\n            Comp1: {\n              template: `\n                <h1><slot></slot></h1>\n                <div>{{ test.length }}</div>\n            `,\n              setup() {\n                const test = ref([...Array(3000)].map((_, i) => ({ i })))\n                // @ts-expect-error\n                window.__REF__ = new WeakRef(test)\n\n                return { test }\n              },\n            },\n            Comp2: {\n              template: `<h2>comp2</h2>`,\n            },\n          },\n          template: `\n          <button id=\"toggleBtn\" @click=\"click\">button</button>\n          <Comp1 v-if=\"toggle\">\n            <div>\n              <Comp2/>\n              text node\n            </div>\n          </Comp1>\n        `,\n          setup() {\n            const toggle = ref(true)\n            const click = () => (toggle.value = !toggle.value)\n            return { toggle, click }\n          },\n        }).mount('#app')\n      })\n\n      expect(await html('#app')).toBe(\n        `<button id=\"toggleBtn\">button</button>` +\n          `<h1>` +\n          `<div>` +\n          `<h2>comp2</h2>` +\n          ` text node ` +\n          `</div>` +\n          `</h1>` +\n          `<div>3000</div>`,\n      )\n\n      await click('#toggleBtn')\n      expect(await html('#app')).toBe(\n        `<button id=\"toggleBtn\">button</button><!--v-if-->`,\n      )\n\n      const isCollected = async () =>\n        // @ts-expect-error\n        await page().evaluate(() => window.__REF__.deref() === undefined)\n\n      while ((await isCollected()) === false) {\n        await client.send('HeapProfiler.collectGarbage')\n      }\n\n      expect(await isCollected()).toBe(true)\n    },\n    E2E_TIMEOUT,\n  )\n\n  // #13211\n  test(\n    'cached array vnodes should not retaining detached DOM nodes',\n    async () => {\n      const client = await page().createCDPSession()\n      await page().evaluate(async () => {\n        const { createApp, ref } = (window as any).Vue\n        createApp({\n          components: {\n            Comp1: {\n              template: `\n                <h1><slot></slot></h1>\n                <div>{{ test.length }}</div>\n            `,\n              setup() {\n                const test = ref([...Array(3000)].map((_, i) => ({ i })))\n                // @ts-expect-error\n                window.__REF__ = new WeakRef(test)\n\n                return { test }\n              },\n            },\n          },\n          template: `\n          <button id=\"toggleBtn\" @click=\"click\">button</button>\n          <Comp1 v-if=\"toggle\">slot content</Comp1>\n        `,\n          setup() {\n            const toggle = ref(true)\n            const click = () => (toggle.value = !toggle.value)\n            return { toggle, click }\n          },\n        }).mount('#app')\n      })\n\n      expect(await html('#app')).toBe(\n        `<button id=\"toggleBtn\">button</button>` +\n          `<h1>` +\n          `slot content` +\n          `</h1>` +\n          `<div>3000</div>`,\n      )\n\n      await click('#toggleBtn')\n      expect(await html('#app')).toBe(\n        `<button id=\"toggleBtn\">button</button><!--v-if-->`,\n      )\n\n      const isCollected = async () =>\n        // @ts-expect-error\n        await page().evaluate(() => window.__REF__.deref() === undefined)\n\n      while ((await isCollected()) === false) {\n        await client.send('HeapProfiler.collectGarbage')\n      }\n\n      expect(await isCollected()).toBe(true)\n    },\n    E2E_TIMEOUT,\n  )\n\n  // https://github.com/element-plus/element-plus/issues/21408\n  test(\n    'cached text nodes in Fragment should not retaining detached DOM nodes',\n    async () => {\n      const client = await page().createCDPSession()\n      await page().evaluate(async () => {\n        const { createApp, ref } = (window as any).Vue\n        createApp({\n          components: {\n            Comp: {\n              template: `<div>{{ test.length }}</div>`,\n              setup() {\n                const test = ref([...Array(3000)].map((_, i) => ({ i })))\n                // @ts-expect-error\n                window.__REF__ = new WeakRef(test)\n\n                return { test }\n              },\n            },\n          },\n          template: `\n          <button id=\"addBtn\" @click=\"add\">add</button>\n          <button id=\"toggleBtn\" @click=\"click\">button</button>\n          <div v-if=\"toggle\">\n            <template v-for=\"item in items\" :key=\"item\">\n              text\n              <div>{{ item }}</div>\n            </template>\n            <Comp/>\n          </div>\n        `,\n          setup() {\n            const toggle = ref(true)\n            const items = ref([1])\n            const click = () => (toggle.value = !toggle.value)\n            const add = () => items.value.push(2)\n            return { toggle, click, items, add }\n          },\n        }).mount('#app')\n      })\n\n      expect(await html('#app')).toBe(\n        `<button id=\"addBtn\">add</button>` +\n          `<button id=\"toggleBtn\">button</button>` +\n          `<div>` +\n          ` text ` +\n          `<div>1</div>` +\n          `<div>3000</div></div>`,\n      )\n\n      await click('#addBtn')\n      expect(await html('#app')).toBe(\n        `<button id=\"addBtn\">add</button>` +\n          `<button id=\"toggleBtn\">button</button>` +\n          `<div>` +\n          ` text ` +\n          `<div>1</div>` +\n          ` text ` +\n          `<div>2</div>` +\n          `<div>3000</div></div>`,\n      )\n\n      await click('#toggleBtn')\n      expect(await html('#app')).toBe(\n        `<button id=\"addBtn\">add</button>` +\n          `<button id=\"toggleBtn\">button</button><!--v-if-->`,\n      )\n\n      const isCollected = async () =>\n        // @ts-expect-error\n        await page().evaluate(() => window.__REF__.deref() === undefined)\n\n      while ((await isCollected()) === false) {\n        await client.send('HeapProfiler.collectGarbage')\n      }\n\n      expect(await isCollected()).toBe(true)\n    },\n    E2E_TIMEOUT,\n  )\n})\n"
  },
  {
    "path": "packages/vue/__tests__/e2e/ssr-custom-element.spec.ts",
    "content": "import path from 'node:path'\nimport { setupPuppeteer } from './e2eUtils'\n\nconst { page, click, text } = setupPuppeteer()\n\nbeforeEach(async () => {\n  await page().addScriptTag({\n    path: path.resolve(__dirname, '../../dist/vue.global.js'),\n  })\n})\n\nasync function setContent(html: string) {\n  await page().setContent(`<div id=\"app\">${html}</div>`)\n}\n\n// this must be tested in actual Chrome because jsdom does not support\n// declarative shadow DOM\ntest('ssr custom element hydration', async () => {\n  await setContent(\n    `<my-element><template shadowrootmode=\"open\"><button>1</button></template></my-element><my-element-async><template shadowrootmode=\"open\"><button>1</button></template></my-element-async>`,\n  )\n\n  await page().evaluate(() => {\n    const {\n      h,\n      ref,\n      defineSSRCustomElement,\n      defineAsyncComponent,\n      onMounted,\n      useHost,\n    } = (window as any).Vue\n\n    const def = {\n      setup() {\n        const count = ref(1)\n        const el = useHost()\n        onMounted(() => (el.style.border = '1px solid red'))\n\n        return () => h('button', { onClick: () => count.value++ }, count.value)\n      },\n    }\n\n    customElements.define('my-element', defineSSRCustomElement(def))\n    customElements.define(\n      'my-element-async',\n      defineSSRCustomElement(\n        defineAsyncComponent(\n          () =>\n            new Promise(r => {\n              ;(window as any).resolve = () => r(def)\n            }),\n        ),\n      ),\n    )\n  })\n\n  function getColor() {\n    return page().evaluate(() => {\n      return [\n        (document.querySelector('my-element') as any).style.border,\n        (document.querySelector('my-element-async') as any).style.border,\n      ]\n    })\n  }\n\n  expect(await getColor()).toMatchObject(['1px solid red', ''])\n  await page().evaluate(() => (window as any).resolve()) // exposed by test\n  expect(await getColor()).toMatchObject(['1px solid red', '1px solid red'])\n\n  async function assertInteraction(el: string) {\n    const selector = `${el} >>> button`\n    expect(await text(selector)).toBe('1')\n    await click(selector)\n    expect(await text(selector)).toBe('2')\n  }\n\n  await assertInteraction('my-element')\n  await assertInteraction('my-element-async')\n})\n\ntest('work with Teleport (shadowRoot: false)', async () => {\n  await setContent(\n    `<div id='test'></div><my-p><my-y><span>default</span></my-y></my-p>`,\n  )\n\n  await page().evaluate(() => {\n    const { h, defineSSRCustomElement, Teleport, renderSlot } = (window as any)\n      .Vue\n    const Y = defineSSRCustomElement(\n      {\n        render() {\n          return h(\n            Teleport,\n            { to: '#test' },\n            {\n              default: () => [renderSlot(this.$slots, 'default')],\n            },\n          )\n        },\n      },\n      { shadowRoot: false },\n    )\n    customElements.define('my-y', Y)\n    const P = defineSSRCustomElement(\n      {\n        render() {\n          return renderSlot(this.$slots, 'default')\n        },\n      },\n      { shadowRoot: false },\n    )\n    customElements.define('my-p', P)\n  })\n\n  function getInnerHTML() {\n    return page().evaluate(() => {\n      return (document.querySelector('#test') as any).innerHTML\n    })\n  }\n\n  expect(await getInnerHTML()).toBe('<span>default</span>')\n})\n\n// #11641\ntest('pass key to custom element', async () => {\n  const messages: string[] = []\n  page().on('console', e => messages.push(e.text()))\n\n  await setContent(\n    `<!--[--><my-element str=\"1\"><template shadowrootmode=\"open\"><div>1</div></template></my-element><!--]-->`,\n  )\n  await page().evaluate(() => {\n    const {\n      h,\n      ref,\n      defineSSRCustomElement,\n      onBeforeUnmount,\n      onMounted,\n      createSSRApp,\n      renderList,\n    } = (window as any).Vue\n\n    const MyElement = defineSSRCustomElement({\n      props: {\n        str: String,\n      },\n      setup(props: any) {\n        onMounted(() => {\n          console.log('child mounted')\n        })\n        onBeforeUnmount(() => {\n          console.log('child unmount')\n        })\n        return () => h('div', props.str)\n      },\n    })\n    customElements.define('my-element', MyElement)\n\n    createSSRApp({\n      setup() {\n        const arr = ref(['1'])\n        // pass key to custom element\n        return () =>\n          renderList(arr.value, (i: string) =>\n            h('my-element', { key: i, str: i }, null),\n          )\n      },\n    }).mount('#app')\n  })\n\n  expect(messages.includes('child mounted')).toBe(true)\n  expect(messages.includes('child unmount')).toBe(false)\n  expect(await text('my-element >>> div')).toBe('1')\n})\n"
  },
  {
    "path": "packages/vue/__tests__/e2e/svg.spec.ts",
    "content": "import path from 'node:path'\nimport { E2E_TIMEOUT, setupPuppeteer } from './e2eUtils'\n\ndeclare const globalStats: {\n  label: string\n  value: number\n}[]\n\ndeclare function valueToPoint(\n  value: number,\n  index: number,\n  total: number,\n): {\n  x: number\n  y: number\n}\n\ndescribe('e2e: svg', () => {\n  const { page, click, count, setValue, typeValue } = setupPuppeteer()\n\n  // assert the shape of the polygon is correct\n  async function assertPolygon(total: number) {\n    expect(\n      await page().evaluate(\n        ([total]) => {\n          const points = globalStats\n            .map((stat, i) => {\n              const point = valueToPoint(stat.value, i, total)\n              return point.x + ',' + point.y\n            })\n            .join(' ')\n          return (\n            document.querySelector('polygon')!.attributes[0].value === points\n          )\n        },\n        [total],\n      ),\n    ).toBe(true)\n  }\n\n  // assert the position of each label is correct\n  async function assertLabels(total: number) {\n    const positions = await page().evaluate(\n      ([total]) => {\n        return globalStats.map((stat, i) => {\n          const point = valueToPoint(+stat.value + 10, i, total)\n          return [point.x, point.y]\n        })\n      },\n      [total],\n    )\n    for (let i = 0; i < total; i++) {\n      const textPosition = await page().$eval(\n        `text:nth-child(${i + 3})`,\n        node => [+node.attributes[0].value, +node.attributes[1].value],\n      )\n      expect(textPosition).toEqual(positions[i])\n    }\n  }\n\n  // assert each value of stats is correct\n  async function assertStats(expected: number[]) {\n    const statsValue = await page().evaluate(() => {\n      return globalStats.map(stat => +stat.value)\n    })\n    expect(statsValue).toEqual(expected)\n  }\n\n  function nthRange(n: number) {\n    return `#demo div:nth-child(${n + 1}) input[type=\"range\"]`\n  }\n\n  async function testSvg(apiType: 'classic' | 'composition') {\n    const baseUrl = `file://${path.resolve(\n      __dirname,\n      `../../examples/${apiType}/svg.html`,\n    )}`\n\n    await page().goto(baseUrl)\n    await page().waitForSelector('svg')\n    expect(await count('g')).toBe(1)\n    expect(await count('polygon')).toBe(1)\n    expect(await count('circle')).toBe(1)\n    expect(await count('text')).toBe(6)\n    expect(await count('label')).toBe(6)\n    expect(await count('button')).toBe(7)\n    expect(await count('input[type=\"range\"]')).toBe(6)\n    await assertPolygon(6)\n    await assertLabels(6)\n    await assertStats([100, 100, 100, 100, 100, 100])\n\n    await setValue(nthRange(1), '10')\n    await assertPolygon(6)\n    await assertLabels(6)\n    await assertStats([10, 100, 100, 100, 100, 100])\n\n    await click('button.remove')\n    expect(await count('text')).toBe(5)\n    expect(await count('label')).toBe(5)\n    expect(await count('button')).toBe(6)\n    expect(await count('input[type=\"range\"]')).toBe(5)\n    await assertPolygon(5)\n    await assertLabels(5)\n    await assertStats([100, 100, 100, 100, 100])\n\n    await typeValue('input[name=\"newlabel\"]', 'foo')\n    await click('#add > button')\n    expect(await count('text')).toBe(6)\n    expect(await count('label')).toBe(6)\n    expect(await count('button')).toBe(7)\n    expect(await count('input[type=\"range\"]')).toBe(6)\n    await assertPolygon(6)\n    await assertLabels(6)\n    await assertStats([100, 100, 100, 100, 100, 100])\n\n    await setValue(nthRange(1), '10')\n    await assertPolygon(6)\n    await assertLabels(6)\n    await assertStats([10, 100, 100, 100, 100, 100])\n\n    await setValue(nthRange(2), '20')\n    await assertPolygon(6)\n    await assertLabels(6)\n    await assertStats([10, 20, 100, 100, 100, 100])\n\n    await setValue(nthRange(6), '60')\n    await assertPolygon(6)\n    await assertLabels(6)\n    await assertStats([10, 20, 100, 100, 100, 60])\n\n    await click('button.remove')\n    await assertPolygon(5)\n    await assertLabels(5)\n    await assertStats([20, 100, 100, 100, 60])\n\n    await setValue(nthRange(1), '10')\n    await assertPolygon(5)\n    await assertLabels(5)\n    await assertStats([10, 100, 100, 100, 60])\n  }\n\n  test(\n    'classic',\n    async () => {\n      await testSvg('classic')\n    },\n    E2E_TIMEOUT,\n  )\n\n  test(\n    'composition',\n    async () => {\n      await testSvg('composition')\n    },\n    E2E_TIMEOUT,\n  )\n})\n"
  },
  {
    "path": "packages/vue/__tests__/e2e/todomvc.spec.ts",
    "content": "import path from 'node:path'\nimport { E2E_TIMEOUT, setupPuppeteer } from './e2eUtils'\n\ndescribe('e2e: todomvc', () => {\n  const {\n    page,\n    click,\n    isVisible,\n    count,\n    text,\n    value,\n    isChecked,\n    isFocused,\n    classList,\n    enterValue,\n    clearValue,\n    timeout,\n  } = setupPuppeteer()\n\n  async function removeItemAt(n: number) {\n    const item = (await page().$('.todo:nth-child(' + n + ')'))!\n    const itemBBox = (await item.boundingBox())!\n    await page().mouse.move(itemBBox.x + 10, itemBBox.y + 10)\n    await click('.todo:nth-child(' + n + ') .destroy')\n  }\n\n  async function testTodomvc(apiType: 'classic' | 'composition') {\n    const baseUrl = `file://${path.resolve(\n      __dirname,\n      `../../examples/${apiType}/todomvc.html`,\n    )}`\n\n    await page().goto(baseUrl)\n    expect(await isVisible('.main')).toBe(false)\n    expect(await isVisible('.footer')).toBe(false)\n    expect(await count('.filters .selected')).toBe(1)\n    expect(await text('.filters .selected')).toBe('All')\n    expect(await count('.todo')).toBe(0)\n\n    await enterValue('.new-todo', 'test')\n    expect(await count('.todo')).toBe(1)\n    expect(await isVisible('.todo .edit')).toBe(false)\n    expect(await text('.todo label')).toBe('test')\n    expect(await text('.todo-count strong')).toBe('1')\n    expect(await isChecked('.todo .toggle')).toBe(false)\n    expect(await isVisible('.main')).toBe(true)\n    expect(await isVisible('.footer')).toBe(true)\n    expect(await isVisible('.clear-completed')).toBe(false)\n    expect(await value('.new-todo')).toBe('')\n\n    await enterValue('.new-todo', 'test2')\n    expect(await count('.todo')).toBe(2)\n    expect(await text('.todo:nth-child(2) label')).toBe('test2')\n    expect(await text('.todo-count strong')).toBe('2')\n\n    // toggle\n    await click('.todo .toggle')\n    expect(await count('.todo.completed')).toBe(1)\n    expect(await classList('.todo:nth-child(1)')).toContain('completed')\n    expect(await text('.todo-count strong')).toBe('1')\n    expect(await isVisible('.clear-completed')).toBe(true)\n\n    await enterValue('.new-todo', 'test3')\n    expect(await count('.todo')).toBe(3)\n    expect(await text('.todo:nth-child(3) label')).toBe('test3')\n    expect(await text('.todo-count strong')).toBe('2')\n\n    await enterValue('.new-todo', 'test4')\n    await enterValue('.new-todo', 'test5')\n    expect(await count('.todo')).toBe(5)\n    expect(await text('.todo-count strong')).toBe('4')\n\n    // toggle more\n    await click('.todo:nth-child(4) .toggle')\n    await click('.todo:nth-child(5) .toggle')\n    expect(await count('.todo.completed')).toBe(3)\n    expect(await text('.todo-count strong')).toBe('2')\n\n    // remove\n    await removeItemAt(1)\n    expect(await count('.todo')).toBe(4)\n    expect(await count('.todo.completed')).toBe(2)\n    expect(await text('.todo-count strong')).toBe('2')\n    await removeItemAt(2)\n    expect(await count('.todo')).toBe(3)\n    expect(await count('.todo.completed')).toBe(2)\n    expect(await text('.todo-count strong')).toBe('1')\n\n    // remove all\n    await click('.clear-completed')\n    expect(await count('.todo')).toBe(1)\n    expect(await text('.todo label')).toBe('test2')\n    expect(await count('.todo.completed')).toBe(0)\n    expect(await text('.todo-count strong')).toBe('1')\n    expect(await isVisible('.clear-completed')).toBe(false)\n\n    // prepare to test filters\n    await enterValue('.new-todo', 'test')\n    await enterValue('.new-todo', 'test')\n    await click('.todo:nth-child(2) .toggle')\n    await click('.todo:nth-child(3) .toggle')\n\n    // active filter\n    await click('.filters li:nth-child(2) a')\n    await timeout(1)\n    expect(await count('.todo')).toBe(1)\n    expect(await count('.todo.completed')).toBe(0)\n    // add item with filter active\n    await enterValue('.new-todo', 'test')\n    expect(await count('.todo')).toBe(2)\n\n    // completed filter\n    await click('.filters li:nth-child(3) a')\n    await timeout(1)\n    expect(await count('.todo')).toBe(2)\n    expect(await count('.todo.completed')).toBe(2)\n\n    // filter on page load\n    await page().goto(`${baseUrl}#active`)\n    expect(await count('.todo')).toBe(2)\n    expect(await count('.todo.completed')).toBe(0)\n    expect(await text('.todo-count strong')).toBe('2')\n\n    // completed on page load\n    await page().goto(`${baseUrl}#completed`)\n    expect(await count('.todo')).toBe(2)\n    expect(await count('.todo.completed')).toBe(2)\n    expect(await text('.todo-count strong')).toBe('2')\n\n    // toggling with filter active\n    await click('.todo .toggle')\n    expect(await count('.todo')).toBe(1)\n    await click('.filters li:nth-child(2) a')\n    await timeout(1)\n    expect(await count('.todo')).toBe(3)\n    await click('.todo .toggle')\n    expect(await count('.todo')).toBe(2)\n\n    // editing triggered by blur\n    await click('.filters li:nth-child(1) a')\n    await timeout(1)\n    await click('.todo:nth-child(1) label', { count: 2 })\n    expect(await count('.todo.editing')).toBe(1)\n    expect(await isFocused('.todo:nth-child(1) .edit')).toBe(true)\n    await clearValue('.todo:nth-child(1) .edit')\n    await page().type('.todo:nth-child(1) .edit', 'edited!')\n    await click('.new-todo') // blur\n    expect(await count('.todo.editing')).toBe(0)\n    expect(await text('.todo:nth-child(1) label')).toBe('edited!')\n\n    // editing triggered by enter\n    await click('.todo label', { count: 2 })\n    await enterValue('.todo:nth-child(1) .edit', 'edited again!')\n    expect(await count('.todo.editing')).toBe(0)\n    expect(await text('.todo:nth-child(1) label')).toBe('edited again!')\n\n    // cancel\n    await click('.todo label', { count: 2 })\n    await clearValue('.todo:nth-child(1) .edit')\n    await page().type('.todo:nth-child(1) .edit', 'edited!')\n    await page().keyboard.press('Escape')\n    expect(await count('.todo.editing')).toBe(0)\n    expect(await text('.todo:nth-child(1) label')).toBe('edited again!')\n\n    // empty value should remove\n    await click('.todo label', { count: 2 })\n    await enterValue('.todo:nth-child(1) .edit', ' ')\n    expect(await count('.todo')).toBe(3)\n\n    // toggle all\n    await click('.toggle-all+label')\n    expect(await count('.todo.completed')).toBe(3)\n    await click('.toggle-all+label')\n    expect(await count('.todo:not(.completed)')).toBe(3)\n  }\n\n  test(\n    'classic',\n    async () => {\n      await testTodomvc('classic')\n    },\n    E2E_TIMEOUT,\n  )\n\n  test(\n    'composition',\n    async () => {\n      await testTodomvc('composition')\n    },\n    E2E_TIMEOUT,\n  )\n})\n"
  },
  {
    "path": "packages/vue/__tests__/e2e/transition.html",
    "content": "<script src=\"../../dist/vue.global.js\"></script>\n\n<div id=\"app\"></div>\n<style>\n  .test {\n    -webkit-transition: opacity 50ms ease;\n    transition: opacity 50ms ease;\n  }\n  .group-move {\n    -webkit-transition: -webkit-transform 50ms ease;\n    transition: transform 50ms ease;\n  }\n  .v-appear,\n  .v-enter,\n  .v-leave-active,\n  .test-appear,\n  .test-enter,\n  .test-leave-active,\n  .test-reflow-enter,\n  .test-reflow-leave-to,\n  .hello,\n  .bye.active,\n  .changed-enter {\n    opacity: 0;\n  }\n  .test-reflow-leave-active,\n  .test-reflow-enter-active {\n    -webkit-transition: opacity 50ms ease;\n    transition: opacity 50ms ease;\n  }\n  .test-reflow-leave-from {\n    opacity: 0.9;\n  }\n  .test-anim-enter-active {\n    animation: test-enter 50ms;\n    -webkit-animation: test-enter 50ms;\n  }\n  .test-anim-leave-active {\n    animation: test-leave 50ms;\n    -webkit-animation: test-leave 50ms;\n  }\n  .test-anim-long-enter-active {\n    animation: test-enter 100ms;\n    -webkit-animation: test-enter 100ms;\n  }\n  .test-anim-long-leave-active {\n    animation: test-leave 100ms;\n    -webkit-animation: test-leave 100ms;\n  }\n  @keyframes test-enter {\n    from {\n      opacity: 0;\n    }\n    to {\n      opacity: 1;\n    }\n  }\n  @-webkit-keyframes test-enter {\n    from {\n      opacity: 0;\n    }\n    to {\n      opacity: 1;\n    }\n  }\n  @keyframes test-leave {\n    from {\n      opacity: 1;\n    }\n    to {\n      opacity: 0;\n    }\n  }\n  @-webkit-keyframes test-leave {\n    from {\n      opacity: 1;\n    }\n    to {\n      opacity: 0;\n    }\n  }\n</style>\n"
  },
  {
    "path": "packages/vue/__tests__/e2e/tree.spec.ts",
    "content": "import path from 'node:path'\nimport { E2E_TIMEOUT, setupPuppeteer } from './e2eUtils'\n\ndescribe('e2e: tree', () => {\n  const { page, click, count, text, children, isVisible } = setupPuppeteer()\n\n  async function testTree(apiType: 'classic' | 'composition') {\n    const baseUrl = `file://${path.resolve(\n      __dirname,\n      `../../examples/${apiType}/tree.html`,\n    )}`\n\n    await page().goto(baseUrl)\n    expect(await count('.item')).toBe(12)\n    expect(await count('.add')).toBe(4)\n    expect(await count('.item > ul')).toBe(4)\n    expect(await isVisible('#demo li ul')).toBe(false)\n    expect(await text('#demo li div span')).toBe('[+]')\n\n    // expand root\n    await click('.bold')\n    expect(await isVisible('#demo ul')).toBe(true)\n    expect((await children('#demo li ul')).length).toBe(4)\n    expect(await text('#demo li div span')).toContain('[-]')\n    expect(await text('#demo > .item > ul > .item:nth-child(1)')).toContain(\n      'hello',\n    )\n    expect(await text('#demo > .item > ul > .item:nth-child(2)')).toContain(\n      'wat',\n    )\n    expect(await text('#demo > .item > ul > .item:nth-child(3)')).toContain(\n      'child folder',\n    )\n    expect(await text('#demo > .item > ul > .item:nth-child(3)')).toContain(\n      '[+]',\n    )\n\n    // add items to root\n    await click('#demo > .item > ul > .add')\n    expect((await children('#demo li ul')).length).toBe(5)\n    expect(await text('#demo > .item > ul > .item:nth-child(1)')).toContain(\n      'hello',\n    )\n    expect(await text('#demo > .item > ul > .item:nth-child(2)')).toContain(\n      'wat',\n    )\n    expect(await text('#demo > .item > ul > .item:nth-child(3)')).toContain(\n      'child folder',\n    )\n    expect(await text('#demo > .item > ul > .item:nth-child(3)')).toContain(\n      '[+]',\n    )\n    expect(await text('#demo > .item > ul > .item:nth-child(4)')).toContain(\n      'new stuff',\n    )\n\n    // add another item\n    await click('#demo > .item > ul > .add')\n    expect((await children('#demo li ul')).length).toBe(6)\n    expect(await text('#demo > .item > ul > .item:nth-child(1)')).toContain(\n      'hello',\n    )\n    expect(await text('#demo > .item > ul > .item:nth-child(2)')).toContain(\n      'wat',\n    )\n    expect(await text('#demo > .item > ul > .item:nth-child(3)')).toContain(\n      'child folder',\n    )\n    expect(await text('#demo > .item > ul > .item:nth-child(3)')).toContain(\n      '[+]',\n    )\n    expect(await text('#demo > .item > ul > .item:nth-child(4)')).toContain(\n      'new stuff',\n    )\n    expect(await text('#demo > .item > ul > .item:nth-child(5)')).toContain(\n      'new stuff',\n    )\n\n    await click('#demo ul .bold')\n    expect(await isVisible('#demo ul ul')).toBe(true)\n    expect(await text('#demo ul > .item:nth-child(3)')).toContain('[-]')\n    expect((await children('#demo ul ul')).length).toBe(5)\n\n    await click('.bold')\n    expect(await isVisible('#demo ul')).toBe(false)\n    expect(await text('#demo li div span')).toContain('[+]')\n    await click('.bold')\n    expect(await isVisible('#demo ul')).toBe(true)\n    expect(await text('#demo li div span')).toContain('[-]')\n\n    await click('#demo ul > .item div', { count: 2 })\n    expect(await count('.item')).toBe(15)\n    expect(await count('.item > ul')).toBe(5)\n    expect(await text('#demo ul > .item:nth-child(1)')).toContain('[-]')\n    expect((await children('#demo ul > .item:nth-child(1) > ul')).length).toBe(\n      2,\n    )\n  }\n\n  test(\n    'classic',\n    async () => {\n      await testTree('classic')\n    },\n    E2E_TIMEOUT,\n  )\n\n  test(\n    'composition',\n    async () => {\n      await testTree('composition')\n    },\n    E2E_TIMEOUT,\n  )\n})\n"
  },
  {
    "path": "packages/vue/__tests__/e2e/trusted-types.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <link rel=\"icon\" href=\"data:;base64,iVBORw0KGgo=\" />\n    <meta\n      http-equiv=\"content-security-policy\"\n      content=\"require-trusted-types-for 'script'\"\n    />\n    <title>Vue App</title>\n    <script src=\"../../dist/vue.global.js\"></script>\n  </head>\n\n  <body>\n    <div id=\"app\"></div>\n  </body>\n</html>\n"
  },
  {
    "path": "packages/vue/__tests__/e2e/trusted-types.spec.ts",
    "content": "import { once } from 'node:events'\nimport { createServer } from 'node:http'\nimport path from 'node:path'\nimport { beforeAll } from 'vitest'\nimport serveHandler from 'serve-handler'\n\nimport { E2E_TIMEOUT, setupPuppeteer } from './e2eUtils'\n\n// use the `vue` package root as the public directory\n// because we need to serve the Vue runtime for the tests\nconst serverRoot = path.resolve(import.meta.dirname, '../../')\nconst testPort = 9090\nconst basePath = path.relative(\n  serverRoot,\n  path.resolve(import.meta.dirname, './trusted-types.html'),\n)\nconst baseUrl = `http://localhost:${testPort}/${basePath}`\n\nconst { page, html } = setupPuppeteer()\n\nlet server: ReturnType<typeof createServer>\nbeforeAll(async () => {\n  // sets up the static server\n  server = createServer((req, res) => {\n    return serveHandler(req, res, {\n      public: serverRoot,\n      cleanUrls: false,\n    })\n  })\n\n  server.listen(testPort)\n  await once(server, 'listening')\n})\n\nafterAll(async () => {\n  server.close()\n  await once(server, 'close')\n})\n\ndescribe('e2e: trusted types', () => {\n  beforeEach(async () => {\n    await page().goto(baseUrl)\n    await page().waitForSelector('#app')\n  })\n\n  test(\n    'should render the hello world app',\n    async () => {\n      await page().evaluate(() => {\n        const { createApp, ref, h } = (window as any).Vue\n        createApp({\n          setup() {\n            const msg = ref('✅success: hello world')\n            return function render() {\n              return h('div', msg.value)\n            }\n          },\n        }).mount('#app')\n      })\n      expect(await html('#app')).toContain('<div>✅success: hello world</div>')\n    },\n    E2E_TIMEOUT,\n  )\n\n  test(\n    'should render static vnode without error',\n    async () => {\n      await page().evaluate(() => {\n        const { createApp, createStaticVNode } = (window as any).Vue\n        createApp({\n          render() {\n            return createStaticVNode('<div>✅success: static vnode</div>')\n          },\n        }).mount('#app')\n      })\n      expect(await html('#app')).toContain('<div>✅success: static vnode</div>')\n    },\n    E2E_TIMEOUT,\n  )\n\n  test(\n    'should accept v-html with custom policy',\n    async () => {\n      await page().evaluate(() => {\n        const testPolicy = (window as any).trustedTypes.createPolicy('test', {\n          createHTML: (input: string): string => input,\n        })\n\n        const { createApp, ref, h } = (window as any).Vue\n        createApp({\n          setup() {\n            const msg = ref('✅success: v-html')\n            return function render() {\n              return h('div', { innerHTML: testPolicy.createHTML(msg.value) })\n            }\n          },\n        }).mount('#app')\n      })\n      expect(await html('#app')).toContain('<div>✅success: v-html</div>')\n    },\n    E2E_TIMEOUT,\n  )\n})\n"
  },
  {
    "path": "packages/vue/__tests__/e2e/vModel.spec.ts",
    "content": "import path from 'node:path'\nimport { setupPuppeteer } from './e2eUtils'\n\nconst { page, click, isChecked } = setupPuppeteer()\nimport { nextTick } from 'vue'\n\nbeforeEach(async () => {\n  await page().addScriptTag({\n    path: path.resolve(__dirname, '../../dist/vue.global.js'),\n  })\n  await page().setContent(`<div id=\"app\"></div>`)\n})\n\n// #12144\ntest('checkbox click with v-model', async () => {\n  await page().evaluate(() => {\n    const { createApp } = (window as any).Vue\n    createApp({\n      template: `\n      <label>\n        <input \n          id=\"first\"\n          type=\"checkbox\"\n          v-model=\"first\"/>\n        First\n      </label>\n      <br>  \n      <label>\n        <input\n          id=\"second\"\n          type=\"checkbox\"\n          v-model=\"second\"      \n          @click=\"secondClick\"/>    \n          Second\n      </label> \n        `,\n      data() {\n        return {\n          first: true,\n          second: false,\n        }\n      },\n      methods: {\n        secondClick(this: any) {\n          this.first = false\n        },\n      },\n    }).mount('#app')\n  })\n\n  expect(await isChecked('#first')).toBe(true)\n  expect(await isChecked('#second')).toBe(false)\n  await click('#second')\n  await nextTick()\n  expect(await isChecked('#first')).toBe(false)\n  expect(await isChecked('#second')).toBe(true)\n})\n"
  },
  {
    "path": "packages/vue/__tests__/index.spec.ts",
    "content": "import { EMPTY_ARR } from '@vue/shared'\nimport { createApp, nextTick, reactive, ref } from '../src'\n\ndescribe('compiler + runtime integration', () => {\n  it('should support runtime template compilation', () => {\n    const container = document.createElement('div')\n    const App = {\n      template: `{{ count }}`,\n      data() {\n        return {\n          count: 0,\n        }\n      },\n    }\n    createApp(App).mount(container)\n    expect(container.innerHTML).toBe(`0`)\n  })\n\n  it('keep-alive with compiler + runtime integration', async () => {\n    const container = document.createElement('div')\n    const one = {\n      name: 'one',\n      template: 'one',\n      created: vi.fn(),\n      mounted: vi.fn(),\n      activated: vi.fn(),\n      deactivated: vi.fn(),\n      unmounted: vi.fn(),\n    }\n\n    const toggle = ref(true)\n\n    const App = {\n      template: `\n        <keep-alive>\n          <one v-if=\"toggle\"></one>\n        </keep-alive>\n      `,\n      data() {\n        return {\n          toggle,\n        }\n      },\n      components: {\n        One: one,\n      },\n    }\n    createApp(App).mount(container)\n    expect(container.innerHTML).toBe(`one`)\n    expect(one.created).toHaveBeenCalledTimes(1)\n    expect(one.mounted).toHaveBeenCalledTimes(1)\n    expect(one.activated).toHaveBeenCalledTimes(1)\n    expect(one.deactivated).toHaveBeenCalledTimes(0)\n    expect(one.unmounted).toHaveBeenCalledTimes(0)\n\n    toggle.value = false\n    await nextTick()\n    expect(container.innerHTML).toBe(`<!--v-if-->`)\n    expect(one.created).toHaveBeenCalledTimes(1)\n    expect(one.mounted).toHaveBeenCalledTimes(1)\n    expect(one.activated).toHaveBeenCalledTimes(1)\n    expect(one.deactivated).toHaveBeenCalledTimes(1)\n    expect(one.unmounted).toHaveBeenCalledTimes(0)\n\n    toggle.value = true\n    await nextTick()\n    expect(container.innerHTML).toBe(`one`)\n    expect(one.created).toHaveBeenCalledTimes(1)\n    expect(one.mounted).toHaveBeenCalledTimes(1)\n    expect(one.activated).toHaveBeenCalledTimes(2)\n    expect(one.deactivated).toHaveBeenCalledTimes(1)\n    expect(one.unmounted).toHaveBeenCalledTimes(0)\n  })\n\n  it('should support runtime template via CSS ID selector', () => {\n    const container = document.createElement('div')\n    const template = document.createElement('div')\n    template.id = 'template'\n    template.innerHTML = '{{ count }}'\n    document.body.appendChild(template)\n\n    const App = {\n      template: `#template`,\n      data() {\n        return {\n          count: 0,\n        }\n      },\n    }\n    createApp(App).mount(container)\n    expect(container.innerHTML).toBe(`0`)\n  })\n\n  it('should support runtime template via direct DOM node', () => {\n    const container = document.createElement('div')\n    const template = document.createElement('div')\n    template.id = 'template'\n    template.innerHTML = '{{ count }}'\n\n    const App = {\n      template,\n      data() {\n        return {\n          count: 0,\n        }\n      },\n    }\n    createApp(App).mount(container)\n    expect(container.innerHTML).toBe(`0`)\n  })\n\n  it('should warn template compilation errors with codeframe', () => {\n    const container = document.createElement('div')\n    const App = {\n      template: `<div v-if>`,\n    }\n    createApp(App).mount(container)\n    expect(\n      `Template compilation error: Element is missing end tag`,\n    ).toHaveBeenWarned()\n    expect(\n      `\n1  |  <div v-if>\n   |  ^`.trim(),\n    ).toHaveBeenWarned()\n    expect(`v-if/v-else-if is missing expression`).toHaveBeenWarned()\n    expect(\n      `\n1  |  <div v-if>\n   |       ^^^^`.trim(),\n    ).toHaveBeenWarned()\n  })\n\n  it('should support custom element via config.isCustomElement (deprecated)', () => {\n    const app = createApp({\n      template: '<custom></custom>',\n    })\n    const container = document.createElement('div')\n    app.config.isCustomElement = tag => tag === 'custom'\n    app.mount(container)\n    expect(container.innerHTML).toBe('<custom></custom>')\n  })\n\n  it('should support custom element via config.compilerOptions.isCustomElement', () => {\n    const app = createApp({\n      template: '<custom></custom>',\n    })\n    const container = document.createElement('div')\n    app.config.compilerOptions.isCustomElement = tag => tag === 'custom'\n    app.mount(container)\n    expect(container.innerHTML).toBe('<custom></custom>')\n  })\n\n  it('should support using element innerHTML as template', () => {\n    const app = createApp({\n      data: () => ({\n        msg: 'hello',\n      }),\n    })\n    const container = document.createElement('div')\n    container.innerHTML = '{{msg}}'\n    app.mount(container)\n    expect(container.innerHTML).toBe('hello')\n  })\n\n  it('should support selector of rootContainer', () => {\n    const container = document.createElement('div')\n    const origin = document.querySelector\n    document.querySelector = vi.fn().mockReturnValue(container)\n\n    const App = {\n      template: `{{ count }}`,\n      data() {\n        return {\n          count: 0,\n        }\n      },\n    }\n    createApp(App).mount('#app')\n    expect(container.innerHTML).toBe(`0`)\n    document.querySelector = origin\n  })\n\n  it('should warn when template is not available', () => {\n    const app = createApp({\n      template: {},\n    })\n    const container = document.createElement('div')\n    app.mount(container)\n    expect('[Vue warn]: invalid template option:').toHaveBeenWarned()\n  })\n\n  it('should warn when template is is not found', () => {\n    const app = createApp({\n      template: '#not-exist-id',\n    })\n    const container = document.createElement('div')\n    app.mount(container)\n    expect(\n      '[Vue warn]: Template element not found or is empty: #not-exist-id',\n    ).toHaveBeenWarned()\n  })\n\n  it('should warn when container is not found', () => {\n    const origin = document.querySelector\n    document.querySelector = vi.fn().mockReturnValue(null)\n    const App = {\n      template: `{{ count }}`,\n      data() {\n        return {\n          count: 0,\n        }\n      },\n    }\n    createApp(App).mount('#not-exist-id')\n\n    expect(\n      '[Vue warn]: Failed to mount app: mount target selector \"#not-exist-id\" returned null.',\n    ).toHaveBeenWarned()\n    document.querySelector = origin\n  })\n\n  // #1813\n  it('should not report an error when \"0\" as patchFlag value', async () => {\n    const container = document.createElement('div')\n    const target = document.createElement('div')\n    const count = ref(0)\n    const origin = document.querySelector\n    document.querySelector = vi.fn().mockReturnValue(target)\n\n    const App = {\n      template: `\n      <teleport v-if=\"count < 2\" to=\"#target\">\n        <div>\n          <div>{{ count }}</div>\n        </div>\n      </teleport>\n      `,\n      data() {\n        return {\n          count,\n        }\n      },\n    }\n    createApp(App).mount(container)\n    expect(container.innerHTML).toBe(`<!--teleport start--><!--teleport end-->`)\n    expect(target.innerHTML).toBe(`<div><div>0</div></div>`)\n\n    count.value++\n    await nextTick()\n    expect(container.innerHTML).toBe(`<!--teleport start--><!--teleport end-->`)\n    expect(target.innerHTML).toBe(`<div><div>1</div></div>`)\n\n    count.value++\n    await nextTick()\n    expect(container.innerHTML).toBe(`<!--v-if-->`)\n    expect(target.innerHTML).toBe(``)\n\n    document.querySelector = origin\n  })\n\n  test('v-if + v-once', async () => {\n    const ok = ref(true)\n    const App = {\n      setup() {\n        return { ok }\n      },\n      template: `<div>{{ ok }}<div v-if=\"ok\" v-once>{{ ok }}</div></div>`,\n    }\n    const container = document.createElement('div')\n    createApp(App).mount(container)\n\n    expect(container.innerHTML).toBe(`<div>true<div>true</div></div>`)\n    ok.value = false\n    await nextTick()\n    expect(container.innerHTML).toBe(`<div>false<div>true</div></div>`)\n  })\n\n  test('v-for + v-once', async () => {\n    const list = reactive([1])\n    const App = {\n      setup() {\n        return { list }\n      },\n      template: `<div>{{ list.length }}<div v-for=\"i in list\" v-once>{{ i }}</div></div>`,\n    }\n    const container = document.createElement('div')\n    createApp(App).mount(container)\n\n    expect(container.innerHTML).toBe(`<div>1<div>1</div></div>`)\n    list.push(2)\n    await nextTick()\n    expect(container.innerHTML).toBe(`<div>2<div>1</div></div>`)\n  })\n\n  // #2413\n  it('EMPTY_ARR should not change', () => {\n    const App = {\n      template: `<div v-for=\"v of ['a']\">{{ v }}</div>`,\n    }\n    const container = document.createElement('div')\n    createApp(App).mount(container)\n    expect(EMPTY_ARR.length).toBe(0)\n  })\n\n  test('BigInt support', () => {\n    const app = createApp({\n      template: `<div>{{ BigInt(BigInt(100000111)) + BigInt(2000000000n) * 30000000n }}</div>`,\n    })\n    const root = document.createElement('div')\n    app.mount(root)\n    expect(root.innerHTML).toBe('<div>60000000100000111</div>')\n  })\n})\n"
  },
  {
    "path": "packages/vue/__tests__/mathmlNamespace.spec.ts",
    "content": "// MathML logic is technically dom-specific, but the logic is placed in core\n// because splitting it out of core would lead to unnecessary complexity in both\n// the renderer and compiler implementations.\n// Related files:\n// - runtime-core/src/renderer.ts\n// - compiler-core/src/transforms/transformElement.ts\n\nimport { vtcKey } from '../../runtime-dom/src/components/Transition'\nimport { h, nextTick, ref, render } from '../src'\n\ndescribe('MathML support', () => {\n  afterEach(() => {\n    document.body.innerHTML = ''\n  })\n\n  test('should mount elements with correct html namespace', () => {\n    const root = document.createElement('div')\n    document.body.appendChild(root)\n    const App = {\n      template: `\n      <math display=\"block\" id=\"e0\">\n        <semantics id=\"e1\">\n          <mrow id=\"e2\">\n            <msup>\n              <mi>x</mi>\n              <mn>2</mn>\n            </msup>\n            <mo>+</mo>\n            <mi>y</mi>\n          </mrow>\n\n          <annotation-xml encoding=\"text/html\" id=\"e3\">\n            <div id=\"e4\" />\n            <svg id=\"e5\" />\n          </annotation-xml>\n        </semantics>\n      </math>\n      `,\n    }\n    render(h(App), root)\n    const e0 = document.getElementById('e0')!\n    expect(e0.namespaceURI).toMatch('Math')\n    expect(e0.querySelector('#e1')!.namespaceURI).toMatch('Math')\n    expect(e0.querySelector('#e2')!.namespaceURI).toMatch('Math')\n    expect(e0.querySelector('#e3')!.namespaceURI).toMatch('Math')\n    expect(e0.querySelector('#e4')!.namespaceURI).toMatch('xhtml')\n    expect(e0.querySelector('#e5')!.namespaceURI).toMatch('svg')\n  })\n\n  test('should patch elements with correct namespaces', async () => {\n    const root = document.createElement('div')\n    document.body.appendChild(root)\n    const cls = ref('foo')\n    const App = {\n      setup: () => ({ cls }),\n      template: `\n        <div>\n          <math id=\"f1\" :class=\"cls\">\n            <annotation encoding=\"text/html\">\n              <div id=\"f2\" :class=\"cls\"/>\n            </annotation>\n          </math>\n        </div>\n      `,\n    }\n    render(h(App), root)\n    const f1 = document.querySelector('#f1')!\n    const f2 = document.querySelector('#f2')!\n    expect(f1.getAttribute('class')).toBe('foo')\n    expect(f2.className).toBe('foo')\n\n    // set a transition class on the <div> - which is only respected on non-svg\n    // patches\n    ;(f2 as any)[vtcKey] = ['baz']\n    cls.value = 'bar'\n    await nextTick()\n    expect(f1.getAttribute('class')).toBe('bar')\n    expect(f2.className).toBe('bar baz')\n  })\n})\n"
  },
  {
    "path": "packages/vue/__tests__/runtimeCompilerOptions.spec.ts",
    "content": "import { createApp } from 'vue'\n\ndescribe('config.compilerOptions', () => {\n  test('isCustomElement', () => {\n    const app = createApp({\n      template: `<foo/>`,\n    })\n    app.config.compilerOptions.isCustomElement = (tag: string) => tag === 'foo'\n    const root = document.createElement('div')\n    app.mount(root)\n    expect(root.innerHTML).toBe('<foo></foo>')\n  })\n\n  test('comments', () => {\n    const app = createApp({\n      template: `<div/><!--test--><div/>`,\n    })\n    app.config.compilerOptions.comments = true\n    // the comments option is only relevant in production mode\n    __DEV__ = false\n    const root = document.createElement('div')\n    app.mount(root)\n    expect(root.innerHTML).toBe('<div></div><!--test--><div></div>')\n    __DEV__ = true\n  })\n\n  test('whitespace', () => {\n    const app = createApp({\n      template: `<div><span/>\\n  <span/></div>`,\n    })\n    app.config.compilerOptions.whitespace = 'preserve'\n    const root = document.createElement('div')\n    app.mount(root)\n    expect(root.firstChild!.childNodes.length).toBe(3)\n    expect(root.firstChild!.childNodes[1].nodeType).toBe(Node.TEXT_NODE)\n  })\n\n  test('delimiters', () => {\n    const app = createApp({\n      data: () => ({ foo: 'hi' }),\n      template: `[[ foo ]]`,\n    })\n    app.config.compilerOptions.delimiters = [`[[`, `]]`]\n    const root = document.createElement('div')\n    app.mount(root)\n    expect(root.textContent).toBe('hi')\n  })\n})\n\ndescribe('per-component compilerOptions', () => {\n  test('isCustomElement', () => {\n    const app = createApp({\n      template: `<foo/>`,\n      compilerOptions: {\n        isCustomElement: (tag: string) => tag === 'foo',\n      },\n    })\n    const root = document.createElement('div')\n    app.mount(root)\n    expect(root.innerHTML).toBe('<foo></foo>')\n  })\n\n  test('comments', () => {\n    const app = createApp({\n      template: `<div/><!--test--><div/>`,\n      compilerOptions: {\n        comments: true,\n      },\n    })\n    app.config.compilerOptions.comments = false\n    // the comments option is only relevant in production mode\n    __DEV__ = false\n    const root = document.createElement('div')\n    app.mount(root)\n    expect(root.innerHTML).toBe('<div></div><!--test--><div></div>')\n    __DEV__ = true\n  })\n\n  test('whitespace', () => {\n    const app = createApp({\n      template: `<div><span/>\\n  <span/></div>`,\n      compilerOptions: {\n        whitespace: 'preserve',\n      },\n    })\n    const root = document.createElement('div')\n    app.mount(root)\n    expect(root.firstChild!.childNodes.length).toBe(3)\n    expect(root.firstChild!.childNodes[1].nodeType).toBe(Node.TEXT_NODE)\n  })\n\n  test('delimiters', () => {\n    const app = createApp({\n      data: () => ({ foo: 'hi' }),\n      template: `[[ foo ]]`,\n      compilerOptions: {\n        delimiters: [`[[`, `]]`],\n      },\n    })\n    const root = document.createElement('div')\n    app.mount(root)\n    expect(root.textContent).toBe('hi')\n  })\n})\n"
  },
  {
    "path": "packages/vue/__tests__/svgNamespace.spec.ts",
    "content": "// SVG logic is technically dom-specific, but the logic is placed in core\n// because splitting it out of core would lead to unnecessary complexity in both\n// the renderer and compiler implementations.\n// Related files:\n// - runtime-core/src/renderer.ts\n// - compiler-core/src/transforms/transformElement.ts\n\nimport { vtcKey } from '../../runtime-dom/src/components/Transition'\nimport { h, nextTick, ref, render } from '../src'\n\ndescribe('SVG support', () => {\n  afterEach(() => {\n    document.body.innerHTML = ''\n  })\n\n  test('should mount elements with correct html namespace', () => {\n    const root = document.createElement('div')\n    document.body.appendChild(root)\n    const App = {\n      template: `\n        <div id=\"e0\">\n          <svg id=\"e1\">\n            <foreignObject id=\"e2\">\n              <div id=\"e3\"/>\n              <svg id=\"e4\"/>\n              <math id=\"e5\"/>\n            </foreignObject>\n          </svg>\n        </div>\n      `,\n    }\n    render(h(App), root)\n    const e0 = document.getElementById('e0')!\n    expect(e0.namespaceURI).toMatch('xhtml')\n    expect(e0.querySelector('#e1')!.namespaceURI).toMatch('svg')\n    expect(e0.querySelector('#e2')!.namespaceURI).toMatch('svg')\n    expect(e0.querySelector('#e3')!.namespaceURI).toMatch('xhtml')\n    expect(e0.querySelector('#e4')!.namespaceURI).toMatch('svg')\n    expect(e0.querySelector('#e5')!.namespaceURI).toMatch('Math')\n  })\n\n  test('should patch elements with correct namespaces', async () => {\n    const root = document.createElement('div')\n    document.body.appendChild(root)\n    const cls = ref('foo')\n    const App = {\n      setup: () => ({ cls }),\n      template: `\n        <div>\n          <svg id=\"f1\" :class=\"cls\">\n            <foreignObject>\n              <div id=\"f2\" :class=\"cls\"/>\n            </foreignObject>\n          </svg>\n        </div>\n      `,\n    }\n    render(h(App), root)\n    const f1 = document.querySelector('#f1')!\n    const f2 = document.querySelector('#f2')!\n    expect(f1.getAttribute('class')).toBe('foo')\n    expect(f2.className).toBe('foo')\n\n    // set a transition class on the <div> - which is only respected on non-svg\n    // patches\n    ;(f2 as any)[vtcKey] = ['baz']\n    cls.value = 'bar'\n    await nextTick()\n    expect(f1.getAttribute('class')).toBe('bar')\n    expect(f2.className).toBe('bar baz')\n  })\n})\n"
  },
  {
    "path": "packages/vue/compiler-sfc/index.browser.js",
    "content": "module.exports = require('@vue/compiler-sfc')\n"
  },
  {
    "path": "packages/vue/compiler-sfc/index.browser.mjs",
    "content": "export * from '@vue/compiler-sfc'\n"
  },
  {
    "path": "packages/vue/compiler-sfc/index.d.mts",
    "content": "export * from '@vue/compiler-sfc'\n"
  },
  {
    "path": "packages/vue/compiler-sfc/index.d.ts",
    "content": "export * from '@vue/compiler-sfc'\n"
  },
  {
    "path": "packages/vue/compiler-sfc/index.js",
    "content": "module.exports = require('@vue/compiler-sfc')\n\nrequire('./register-ts.js')\n"
  },
  {
    "path": "packages/vue/compiler-sfc/index.mjs",
    "content": "export * from '@vue/compiler-sfc'\n\nimport './register-ts.js'\n"
  },
  {
    "path": "packages/vue/compiler-sfc/package.json",
    "content": "{\n  \"main\": \"index.js\",\n  \"module\": \"index.mjs\"\n}\n"
  },
  {
    "path": "packages/vue/compiler-sfc/register-ts.js",
    "content": "if (typeof require !== 'undefined') {\n  require('@vue/compiler-sfc').registerTS(() => require('typescript'))\n}\n"
  },
  {
    "path": "packages/vue/examples/classic/commits.html",
    "content": "<script src=\"../../dist/vue.global.js\"></script>\n\n<div id=\"demo\">\n  <h1>Latest Vue.js Commits</h1>\n  <template v-for=\"branch in branches\">\n    <input\n      type=\"radio\"\n      :id=\"branch\"\n      :value=\"branch\"\n      name=\"branch\"\n      v-model=\"currentBranch\"\n    />\n    <label :for=\"branch\">{{ branch }}</label>\n  </template>\n  <p>vuejs/core@{{ currentBranch }}</p>\n  <ul>\n    <li v-for=\"{ html_url, sha, author, commit } in commits\">\n      <a :href=\"html_url\" target=\"_blank\" class=\"commit\"\n        >{{ sha.slice(0, 7) }}</a\n      >\n      - <span class=\"message\">{{ truncate(commit.message) }}</span><br />\n      by\n      <span class=\"author\"\n        ><a :href=\"author.html_url\" target=\"_blank\"\n          >{{ commit.author.name }}</a\n        ></span\n      >\n      at <span class=\"date\">{{ formatDate(commit.author.date) }}</span>\n    </li>\n  </ul>\n</div>\n\n<script>\n  const API_URL = `https://api.github.com/repos/vuejs/core/commits?per_page=3&sha=`\n\n  Vue.createApp({\n    data: () => ({\n      branches: ['main', 'v2-compat'],\n      currentBranch: 'main',\n      commits: null,\n    }),\n\n    created() {\n      this.fetchData()\n    },\n\n    watch: {\n      currentBranch: 'fetchData',\n    },\n\n    methods: {\n      fetchData() {\n        fetch(`${API_URL}${this.currentBranch}`)\n          .then(res => res.json())\n          .then(data => {\n            this.commits = data\n          })\n      },\n      truncate(v) {\n        const newline = v.indexOf('\\n')\n        return newline > 0 ? v.slice(0, newline) : v\n      },\n      formatDate(v) {\n        return v.replace(/T|Z/g, ' ')\n      },\n    },\n  }).mount('#demo')\n</script>\n\n<style>\n  #demo {\n    font-family: 'Helvetica', Arial, sans-serif;\n  }\n  a {\n    text-decoration: none;\n    color: #f66;\n  }\n  li {\n    line-height: 1.5em;\n    margin-bottom: 20px;\n  }\n  .author,\n  .date {\n    font-weight: bold;\n  }\n</style>\n"
  },
  {
    "path": "packages/vue/examples/classic/grid.html",
    "content": "<script src=\"../../dist/vue.global.js\"></script>\n\n<!-- DemoGrid component template -->\n<script type=\"text/x-template\" id=\"grid-template\">\n  <table v-if=\"filteredData.length\">\n    <thead>\n      <tr>\n        <th v-for=\"key in columns\"\n          @click=\"sortBy(key)\"\n          :class=\"{ active: sortKey == key }\">\n          {{ capitalize(key) }}\n          <span class=\"arrow\" :class=\"sortOrders[key] > 0 ? 'asc' : 'dsc'\">\n          </span>\n        </th>\n      </tr>\n    </thead>\n    <tbody>\n      <tr v-for=\"entry in filteredData\">\n        <td v-for=\"key in columns\">\n          {{entry[key]}}\n        </td>\n      </tr>\n    </tbody>\n  </table>\n  <p v-else>No matches found.</p>\n</script>\n<!-- DemoGrid component script -->\n<script>\n  const DemoGrid = {\n    template: '#grid-template',\n    props: {\n      data: Array,\n      columns: Array,\n      filterKey: String,\n    },\n    data() {\n      return {\n        sortKey: '',\n        sortOrders: this.columns.reduce((o, key) => ((o[key] = 1), o), {}),\n      }\n    },\n    computed: {\n      filteredData() {\n        const sortKey = this.sortKey\n        const filterKey = this.filterKey && this.filterKey.toLowerCase()\n        const order = this.sortOrders[sortKey] || 1\n        let data = this.data\n        if (filterKey) {\n          data = data.filter(row => {\n            return Object.keys(row).some(key => {\n              return String(row[key]).toLowerCase().indexOf(filterKey) > -1\n            })\n          })\n        }\n        if (sortKey) {\n          data = data.slice().sort((a, b) => {\n            a = a[sortKey]\n            b = b[sortKey]\n            return (a === b ? 0 : a > b ? 1 : -1) * order\n          })\n        }\n        return data\n      },\n    },\n    methods: {\n      sortBy(key) {\n        this.sortKey = key\n        this.sortOrders[key] = this.sortOrders[key] * -1\n      },\n      capitalize(str) {\n        return str.charAt(0).toUpperCase() + str.slice(1)\n      },\n    },\n  }\n</script>\n\n<!-- App template (in DOM) -->\n<div id=\"demo\">\n  <form id=\"search\">Search <input name=\"query\" v-model=\"searchQuery\" /></form>\n  <demo-grid :data=\"gridData\" :columns=\"gridColumns\" :filter-key=\"searchQuery\">\n  </demo-grid>\n</div>\n<!-- App script -->\n<script>\n  Vue.createApp({\n    components: {\n      DemoGrid,\n    },\n    data: () => ({\n      searchQuery: '',\n      gridColumns: ['name', 'power'],\n      gridData: [\n        { name: 'Chuck Norris', power: Infinity },\n        { name: 'Bruce Lee', power: 9000 },\n        { name: 'Jackie Chan', power: 7000 },\n        { name: 'Jet Li', power: 8000 },\n      ],\n    }),\n  }).mount('#demo')\n</script>\n\n<style>\n  body {\n    font-family:\n      Helvetica Neue,\n      Arial,\n      sans-serif;\n    font-size: 14px;\n    color: #444;\n  }\n\n  table {\n    border: 2px solid #42b983;\n    border-radius: 3px;\n    background-color: #fff;\n  }\n\n  th {\n    background-color: #42b983;\n    color: rgba(255, 255, 255, 0.66);\n    cursor: pointer;\n    -webkit-user-select: none;\n    -moz-user-select: none;\n    -ms-user-select: none;\n    user-select: none;\n  }\n\n  td {\n    background-color: #f9f9f9;\n  }\n\n  th,\n  td {\n    min-width: 120px;\n    padding: 10px 20px;\n  }\n\n  th.active {\n    color: #fff;\n  }\n\n  th.active .arrow {\n    opacity: 1;\n  }\n\n  .arrow {\n    display: inline-block;\n    vertical-align: middle;\n    width: 0;\n    height: 0;\n    margin-left: 5px;\n    opacity: 0.66;\n  }\n\n  .arrow.asc {\n    border-left: 4px solid transparent;\n    border-right: 4px solid transparent;\n    border-bottom: 4px solid #fff;\n  }\n\n  .arrow.dsc {\n    border-left: 4px solid transparent;\n    border-right: 4px solid transparent;\n    border-top: 4px solid #fff;\n  }\n</style>\n"
  },
  {
    "path": "packages/vue/examples/classic/markdown.html",
    "content": "<script src=\"../../../../node_modules/marked/marked.min.js\"></script>\n<script src=\"../../../../node_modules/lodash/lodash.min.js\"></script>\n<script src=\"../../dist/vue.global.js\"></script>\n\n<div id=\"editor\">\n  <textarea :value=\"input\" @input=\"update\"></textarea>\n  <div v-html=\"compiledMarkdown\"></div>\n</div>\n\n<script>\n  Vue.createApp({\n    data: () => ({\n      input: '# hello',\n    }),\n    computed: {\n      compiledMarkdown() {\n        return marked.marked(this.input, { sanitize: true })\n      },\n    },\n    methods: {\n      update: _.debounce(function (e) {\n        this.input = e.target.value\n      }, 50),\n    },\n  }).mount('#editor')\n</script>\n\n<style>\n  html,\n  body,\n  #editor {\n    margin: 0;\n    height: 100%;\n    font-family: 'Helvetica Neue', Arial, sans-serif;\n    color: #333;\n  }\n\n  textarea,\n  #editor div {\n    display: inline-block;\n    overflow: auto;\n    width: 50%;\n    height: 100%;\n    vertical-align: top;\n    -webkit-box-sizing: border-box;\n    -moz-box-sizing: border-box;\n    box-sizing: border-box;\n    padding: 0 20px;\n  }\n\n  textarea {\n    border: none;\n    border-right: 1px solid #ccc;\n    resize: none;\n    outline: none;\n    background-color: #f6f6f6;\n    font-size: 14px;\n    font-family: 'Monaco', courier, monospace;\n    padding: 20px;\n  }\n\n  code {\n    color: #f66;\n  }\n</style>\n"
  },
  {
    "path": "packages/vue/examples/classic/svg.html",
    "content": "<script src=\"../../dist/vue.global.js\"></script>\n<script>\n  // math helper...\n  function valueToPoint(value, index, total) {\n    var x = 0\n    var y = -value * 0.8\n    var angle = ((Math.PI * 2) / total) * index\n    var cos = Math.cos(angle)\n    var sin = Math.sin(angle)\n    var tx = x * cos - y * sin + 100\n    var ty = x * sin + y * cos + 100\n    return {\n      x: tx,\n      y: ty,\n    }\n  }\n\n  const AxisLabel = {\n    template: '<text :x=\"point.x\" :y=\"point.y\">{{stat.label}}</text>',\n    props: {\n      stat: Object,\n      index: Number,\n      total: Number,\n    },\n    computed: {\n      point: function () {\n        return valueToPoint(+this.stat.value + 10, this.index, this.total)\n      },\n    },\n  }\n</script>\n\n<!-- template for the polygraph component. -->\n<script type=\"text/x-template\" id=\"polygraph-template\">\n  <g>\n    <polygon :points=\"points\"></polygon>\n    <circle cx=\"100\" cy=\"100\" r=\"80\"></circle>\n    <axis-label\n      v-for=\"(stat, index) in stats\"\n      :stat=\"stat\"\n      :index=\"index\"\n      :total=\"stats.length\">\n    </axis-label>\n  </g>\n</script>\n\n<script>\n  const Polygraph = {\n    props: ['stats'],\n    template: '#polygraph-template',\n    computed: {\n      // a computed property for the polygon's points\n      points() {\n        const total = this.stats.length\n        return this.stats\n          .map((stat, i) => {\n            const point = valueToPoint(stat.value, i, total)\n            return point.x + ',' + point.y\n          })\n          .join(' ')\n      },\n    },\n    components: {\n      AxisLabel,\n    },\n  }\n</script>\n\n<!-- demo root element -->\n<div id=\"demo\">\n  <!-- Use the polygraph component -->\n  <svg width=\"200\" height=\"200\">\n    <polygraph :stats=\"stats\"></polygraph>\n  </svg>\n  <!-- controls -->\n  <div v-for=\"stat in stats\">\n    <label>{{stat.label}}</label>\n    <input type=\"range\" v-model=\"stat.value\" min=\"0\" max=\"100\" />\n    <span>{{stat.value}}</span>\n    <button @click=\"remove(stat)\" class=\"remove\">X</button>\n  </div>\n  <form id=\"add\">\n    <input name=\"newlabel\" v-model=\"newLabel\" />\n    <button @click=\"add\">Add a Stat</button>\n  </form>\n  <pre id=\"raw\">{{ stats }}</pre>\n</div>\n\n<script>\n  const globalStats = [\n    { label: 'A', value: 100 },\n    { label: 'B', value: 100 },\n    { label: 'C', value: 100 },\n    { label: 'D', value: 100 },\n    { label: 'E', value: 100 },\n    { label: 'F', value: 100 },\n  ]\n\n  Vue.createApp({\n    components: {\n      Polygraph,\n    },\n    data: () => ({\n      newLabel: '',\n      stats: globalStats,\n    }),\n    methods: {\n      add(e) {\n        e.preventDefault()\n        if (!this.newLabel) return\n        this.stats.push({\n          label: this.newLabel,\n          value: 100,\n        })\n        this.newLabel = ''\n      },\n      remove(stat) {\n        if (this.stats.length > 3) {\n          this.stats.splice(this.stats.indexOf(stat), 1)\n        } else {\n          alert(\"Can't delete more!\")\n        }\n      },\n    },\n  }).mount('#demo')\n</script>\n\n<style>\n  body {\n    font-family:\n      Helvetica Neue,\n      Arial,\n      sans-serif;\n  }\n\n  polygon {\n    fill: #42b983;\n    opacity: 0.75;\n  }\n\n  circle {\n    fill: transparent;\n    stroke: #999;\n  }\n\n  text {\n    font-family:\n      Helvetica Neue,\n      Arial,\n      sans-serif;\n    font-size: 10px;\n    fill: #666;\n  }\n\n  label {\n    display: inline-block;\n    margin-left: 10px;\n    width: 20px;\n  }\n\n  #raw {\n    position: absolute;\n    top: 0;\n    left: 300px;\n  }\n</style>\n"
  },
  {
    "path": "packages/vue/examples/classic/todomvc.html",
    "content": "<script src=\"../../dist/vue.global.js\"></script>\n<link\n  rel=\"stylesheet\"\n  href=\"../../../../node_modules/todomvc-app-css/index.css\"\n/>\n\n<div id=\"app\">\n  <section class=\"todoapp\">\n    <header class=\"header\">\n      <h1>todos</h1>\n      <input\n        class=\"new-todo\"\n        autofocus\n        autocomplete=\"off\"\n        placeholder=\"What needs to be done?\"\n        v-model=\"newTodo\"\n        @keyup.enter=\"addTodo\"\n      />\n    </header>\n    <section class=\"main\" v-show=\"todos.length\">\n      <input\n        id=\"toggle-all\"\n        class=\"toggle-all\"\n        type=\"checkbox\"\n        v-model=\"allDone\"\n      />\n      <label for=\"toggle-all\">Mark all as complete</label>\n      <ul class=\"todo-list\">\n        <li\n          v-for=\"todo in filteredTodos\"\n          class=\"todo\"\n          :key=\"todo.id\"\n          :class=\"{ completed: todo.completed, editing: todo === editedTodo }\"\n        >\n          <div class=\"view\">\n            <input class=\"toggle\" type=\"checkbox\" v-model=\"todo.completed\" />\n            <label @dblclick=\"editTodo(todo)\">{{ todo.title }}</label>\n            <button class=\"destroy\" @click=\"removeTodo(todo)\"></button>\n          </div>\n          <input\n            class=\"edit\"\n            type=\"text\"\n            v-model=\"todo.title\"\n            v-todo-focus=\"todo === editedTodo\"\n            @blur=\"doneEdit(todo)\"\n            @keyup.enter=\"doneEdit(todo)\"\n            @keyup.escape=\"cancelEdit(todo)\"\n          />\n        </li>\n      </ul>\n    </section>\n    <footer class=\"footer\" v-show=\"todos.length\">\n      <span class=\"todo-count\">\n        <strong>{{ remaining }}</strong>\n        <span>{{ pluralize(remaining) }} left</span>\n      </span>\n      <ul class=\"filters\">\n        <li>\n          <a href=\"#/all\" :class=\"{ selected: visibility === 'all' }\">All</a>\n        </li>\n        <li>\n          <a href=\"#/active\" :class=\"{ selected: visibility === 'active' }\"\n            >Active</a\n          >\n        </li>\n        <li>\n          <a\n            href=\"#/completed\"\n            :class=\"{ selected: visibility === 'completed' }\"\n            >Completed</a\n          >\n        </li>\n      </ul>\n      <button\n        class=\"clear-completed\"\n        @click=\"removeCompleted\"\n        v-show=\"todos.length > remaining\"\n      >\n        Clear completed\n      </button>\n    </footer>\n  </section>\n</div>\n\n<script>\n  const STORAGE_KEY = 'todos-vuejs-3.x'\n  const todoStorage = {\n    fetch() {\n      const todos = JSON.parse(localStorage.getItem(STORAGE_KEY) || '[]')\n      todos.forEach((todo, index) => {\n        todo.id = index\n      })\n      todoStorage.uid = todos.length\n      return todos\n    },\n    save(todos) {\n      localStorage.setItem(STORAGE_KEY, JSON.stringify(todos))\n    },\n  }\n\n  const filters = {\n    all(todos) {\n      return todos\n    },\n    active(todos) {\n      return todos.filter(todo => {\n        return !todo.completed\n      })\n    },\n    completed(todos) {\n      return todos.filter(function (todo) {\n        return todo.completed\n      })\n    },\n  }\n\n  Vue.createApp({\n    // app initial state\n    data: () => ({\n      todos: todoStorage.fetch(),\n      newTodo: '',\n      editedTodo: null,\n      visibility: 'all',\n    }),\n\n    // watch todos change for localStorage persistence\n    watch: {\n      todos: {\n        handler(todos) {\n          todoStorage.save(todos)\n        },\n        deep: true,\n      },\n    },\n\n    mounted() {\n      window.addEventListener('hashchange', this.onHashChange)\n      this.onHashChange()\n    },\n\n    computed: {\n      filteredTodos() {\n        return filters[this.visibility](this.todos)\n      },\n      remaining() {\n        return filters.active(this.todos).length\n      },\n      allDone: {\n        get() {\n          return this.remaining === 0\n        },\n        set(value) {\n          this.todos.forEach(function (todo) {\n            todo.completed = value\n          })\n        },\n      },\n    },\n\n    // methods that implement data logic.\n    // note there's no DOM manipulation here at all.\n    methods: {\n      addTodo() {\n        var value = this.newTodo && this.newTodo.trim()\n        if (!value) {\n          return\n        }\n        this.todos.push({\n          id: todoStorage.uid++,\n          title: value,\n          completed: false,\n        })\n        this.newTodo = ''\n      },\n\n      removeTodo(todo) {\n        this.todos.splice(this.todos.indexOf(todo), 1)\n      },\n\n      editTodo(todo) {\n        this.beforeEditCache = todo.title\n        this.editedTodo = todo\n      },\n\n      doneEdit(todo) {\n        if (!this.editedTodo) {\n          return\n        }\n        this.editedTodo = null\n        todo.title = todo.title.trim()\n        if (!todo.title) {\n          this.removeTodo(todo)\n        }\n      },\n\n      cancelEdit(todo) {\n        this.editedTodo = null\n        todo.title = this.beforeEditCache\n      },\n\n      removeCompleted() {\n        this.todos = filters.active(this.todos)\n      },\n\n      onHashChange() {\n        var visibility = window.location.hash.replace(/#\\/?/, '')\n        if (filters[visibility]) {\n          this.visibility = visibility\n        } else {\n          window.location.hash = ''\n          this.visibility = 'all'\n        }\n      },\n\n      pluralize(n) {\n        return n === 1 ? 'item' : 'items'\n      },\n    },\n\n    directives: {\n      'todo-focus'(el, binding) {\n        if (binding.value) {\n          el.focus()\n        }\n      },\n    },\n  }).mount('#app')\n</script>\n"
  },
  {
    "path": "packages/vue/examples/classic/tree.html",
    "content": "<script src=\"../../dist/vue.global.js\"></script>\n\n<!-- item template -->\n<script type=\"text/x-template\" id=\"item-template\">\n  <li>\n    <div\n      :class=\"{bold: isFolder}\"\n      @click=\"toggle\"\n      @dblclick=\"changeType\">\n      {{model.name}}\n      <span v-if=\"isFolder\">[{{open ? '-' : '+'}}]</span>\n    </div>\n    <ul v-show=\"open\" v-if=\"isFolder\">\n      <tree-item\n        class=\"item\"\n        v-for=\"model in model.children\"\n        :model=\"model\">\n      </tree-item>\n      <li class=\"add\" @click=\"addChild\">+</li>\n    </ul>\n  </li>\n</script>\n<!-- item script -->\n<script>\n  const TreeItem = {\n    name: 'TreeItem', // necessary for self-reference\n    template: '#item-template',\n    props: {\n      model: Object,\n    },\n    data() {\n      return {\n        open: false,\n      }\n    },\n    computed: {\n      isFolder() {\n        return this.model.children && this.model.children.length\n      },\n    },\n    methods: {\n      toggle() {\n        if (this.isFolder) {\n          this.open = !this.open\n        }\n      },\n      changeType() {\n        if (!this.isFolder) {\n          this.model.children = []\n          this.addChild()\n          this.open = true\n        }\n      },\n      addChild() {\n        this.model.children.push({\n          name: 'new stuff',\n        })\n      },\n    },\n  }\n</script>\n\n<p>(You can double click on an item to turn it into a folder.)</p>\n\n<!-- the app root element -->\n<ul id=\"demo\">\n  <tree-item class=\"item\" :model=\"treeData\"></tree-item>\n</ul>\n\n<script>\n  const treeData = {\n    name: 'My Tree',\n    children: [\n      { name: 'hello' },\n      { name: 'wat' },\n      {\n        name: 'child folder',\n        children: [\n          {\n            name: 'child folder',\n            children: [{ name: 'hello' }, { name: 'wat' }],\n          },\n          { name: 'hello' },\n          { name: 'wat' },\n          {\n            name: 'child folder',\n            children: [{ name: 'hello' }, { name: 'wat' }],\n          },\n        ],\n      },\n    ],\n  }\n\n  Vue.createApp({\n    components: {\n      TreeItem,\n    },\n    data: () => ({\n      treeData,\n    }),\n  }).mount('#demo')\n</script>\n\n<style>\n  body {\n    font-family: Menlo, Consolas, monospace;\n    color: #444;\n  }\n  .item {\n    cursor: pointer;\n  }\n  .bold {\n    font-weight: bold;\n  }\n  ul {\n    padding-left: 1em;\n    line-height: 1.5em;\n    list-style-type: dot;\n  }\n</style>\n"
  },
  {
    "path": "packages/vue/examples/composition/commits.html",
    "content": "<script src=\"../../dist/vue.global.js\"></script>\n\n<div id=\"demo\">\n  <h1>Latest Vue.js Commits</h1>\n  <template v-for=\"branch in branches\">\n    <input\n      type=\"radio\"\n      :id=\"branch\"\n      :value=\"branch\"\n      name=\"branch\"\n      v-model=\"currentBranch\"\n    />\n    <label :for=\"branch\">{{ branch }}</label>\n  </template>\n  <p>vuejs/core@{{ currentBranch }}</p>\n  <ul>\n    <li v-for=\"{ html_url, sha, author, commit } in commits\">\n      <a :href=\"html_url\" target=\"_blank\" class=\"commit\"\n        >{{ sha.slice(0, 7) }}</a\n      >\n      - <span class=\"message\">{{ truncate(commit.message) }}</span><br />\n      by\n      <span class=\"author\"\n        ><a :href=\"author.html_url\" target=\"_blank\"\n          >{{ commit.author.name }}</a\n        ></span\n      >\n      at <span class=\"date\">{{ formatDate(commit.author.date) }}</span>\n    </li>\n  </ul>\n</div>\n\n<script>\n  const { createApp, ref, watchEffect } = Vue\n  const API_URL = `https://api.github.com/repos/vuejs/core/commits?per_page=3&sha=`\n\n  const truncate = v => {\n    const newline = v.indexOf('\\n')\n    return newline > 0 ? v.slice(0, newline) : v\n  }\n\n  const formatDate = v => v.replace(/T|Z/g, ' ')\n\n  createApp({\n    setup() {\n      const currentBranch = ref('main')\n      const commits = ref(null)\n\n      watchEffect(() => {\n        fetch(`${API_URL}${currentBranch.value}`)\n          .then(res => res.json())\n          .then(data => {\n            console.log(data)\n            commits.value = data\n          })\n      })\n\n      return {\n        branches: ['main', 'v2-compat'],\n        currentBranch,\n        commits,\n        truncate,\n        formatDate,\n      }\n    },\n  }).mount('#demo')\n</script>\n\n<style>\n  #demo {\n    font-family: 'Helvetica', Arial, sans-serif;\n  }\n  a {\n    text-decoration: none;\n    color: #f66;\n  }\n  li {\n    line-height: 1.5em;\n    margin-bottom: 20px;\n  }\n  .author,\n  .date {\n    font-weight: bold;\n  }\n</style>\n"
  },
  {
    "path": "packages/vue/examples/composition/grid.html",
    "content": "<script src=\"../../dist/vue.global.js\"></script>\n\n<!-- DemoGrid component template -->\n<script type=\"text/x-template\" id=\"grid-template\">\n  <table v-if=\"filteredData.length\">\n    <thead>\n      <tr>\n        <th v-for=\"key in columns\"\n          @click=\"sortBy(key)\"\n          :class=\"{ active: state.sortKey == key }\">\n          {{ capitalize(key) }}\n          <span class=\"arrow\" :class=\"state.sortOrders[key] > 0 ? 'asc' : 'dsc'\">\n          </span>\n        </th>\n      </tr>\n    </thead>\n    <tbody>\n      <tr v-for=\"entry in filteredData\">\n        <td v-for=\"key in columns\">\n          {{entry[key]}}\n        </td>\n      </tr>\n    </tbody>\n  </table>\n  <p v-else>No matches found.</p>\n</script>\n<!-- DemoGrid component script -->\n<script>\n  const { reactive, computed } = Vue\n\n  const capitalize = str => str.charAt(0).toUpperCase() + str.slice(1)\n\n  const DemoGrid = {\n    template: '#grid-template',\n    props: {\n      data: Array,\n      columns: Array,\n      filterKey: String,\n    },\n    setup(props) {\n      const state = reactive({\n        sortKey: '',\n        sortOrders: props.columns.reduce((o, key) => ((o[key] = 1), o), {}),\n      })\n\n      const filteredData = computed(() => {\n        let { data, filterKey } = props\n        if (filterKey) {\n          filterKey = filterKey.toLowerCase()\n          data = data.filter(row => {\n            return Object.keys(row).some(key => {\n              return String(row[key]).toLowerCase().indexOf(filterKey) > -1\n            })\n          })\n        }\n        const { sortKey } = state\n        if (sortKey) {\n          const order = state.sortOrders[sortKey]\n          data = data.slice().sort((a, b) => {\n            a = a[sortKey]\n            b = b[sortKey]\n            return (a === b ? 0 : a > b ? 1 : -1) * order\n          })\n        }\n        return data\n      })\n\n      function sortBy(key) {\n        state.sortKey = key\n        state.sortOrders[key] *= -1\n      }\n\n      return {\n        state,\n        filteredData,\n        sortBy,\n        capitalize,\n      }\n    },\n  }\n</script>\n\n<!-- App template (in DOM) -->\n<div id=\"demo\">\n  <form id=\"search\">Search <input name=\"query\" v-model=\"searchQuery\" /></form>\n  <demo-grid :data=\"gridData\" :columns=\"gridColumns\" :filter-key=\"searchQuery\">\n  </demo-grid>\n</div>\n<!-- App script -->\n<script>\n  Vue.createApp({\n    components: {\n      DemoGrid,\n    },\n    data: () => ({\n      searchQuery: '',\n      gridColumns: ['name', 'power'],\n      gridData: [\n        { name: 'Chuck Norris', power: Infinity },\n        { name: 'Bruce Lee', power: 9000 },\n        { name: 'Jackie Chan', power: 7000 },\n        { name: 'Jet Li', power: 8000 },\n      ],\n    }),\n  }).mount('#demo')\n</script>\n\n<style>\n  body {\n    font-family:\n      Helvetica Neue,\n      Arial,\n      sans-serif;\n    font-size: 14px;\n    color: #444;\n  }\n\n  table {\n    border: 2px solid #42b983;\n    border-radius: 3px;\n    background-color: #fff;\n  }\n\n  th {\n    background-color: #42b983;\n    color: rgba(255, 255, 255, 0.66);\n    cursor: pointer;\n    -webkit-user-select: none;\n    -moz-user-select: none;\n    -ms-user-select: none;\n    user-select: none;\n  }\n\n  td {\n    background-color: #f9f9f9;\n  }\n\n  th,\n  td {\n    min-width: 120px;\n    padding: 10px 20px;\n  }\n\n  th.active {\n    color: #fff;\n  }\n\n  th.active .arrow {\n    opacity: 1;\n  }\n\n  .arrow {\n    display: inline-block;\n    vertical-align: middle;\n    width: 0;\n    height: 0;\n    margin-left: 5px;\n    opacity: 0.66;\n  }\n\n  .arrow.asc {\n    border-left: 4px solid transparent;\n    border-right: 4px solid transparent;\n    border-bottom: 4px solid #fff;\n  }\n\n  .arrow.dsc {\n    border-left: 4px solid transparent;\n    border-right: 4px solid transparent;\n    border-top: 4px solid #fff;\n  }\n</style>\n"
  },
  {
    "path": "packages/vue/examples/composition/markdown.html",
    "content": "<script src=\"../../../../node_modules/marked/marked.min.js\"></script>\n<script src=\"../../../../node_modules/lodash/lodash.min.js\"></script>\n<script src=\"../../dist/vue.global.js\"></script>\n\n<div id=\"editor\">\n  <textarea :value=\"input\" @input=\"update\"></textarea>\n  <div v-html=\"output\"></div>\n</div>\n\n<script>\n  const { ref, computed } = Vue\n\n  Vue.createApp({\n    setup() {\n      const input = ref('# hello')\n      const output = computed(() =>\n        marked.marked(input.value, { sanitize: true }),\n      )\n      const update = _.debounce(e => {\n        input.value = e.target.value\n      }, 50)\n\n      return {\n        input,\n        output,\n        update,\n      }\n    },\n  }).mount('#editor')\n</script>\n\n<style>\n  html,\n  body,\n  #editor {\n    margin: 0;\n    height: 100%;\n    font-family: 'Helvetica Neue', Arial, sans-serif;\n    color: #333;\n  }\n\n  textarea,\n  #editor div {\n    display: inline-block;\n    overflow: auto;\n    width: 50%;\n    height: 100%;\n    vertical-align: top;\n    -webkit-box-sizing: border-box;\n    -moz-box-sizing: border-box;\n    box-sizing: border-box;\n    padding: 0 20px;\n  }\n\n  textarea {\n    border: none;\n    border-right: 1px solid #ccc;\n    resize: none;\n    outline: none;\n    background-color: #f6f6f6;\n    font-size: 14px;\n    font-family: 'Monaco', courier, monospace;\n    padding: 20px;\n  }\n\n  code {\n    color: #f66;\n  }\n</style>\n"
  },
  {
    "path": "packages/vue/examples/composition/svg.html",
    "content": "<script src=\"../../dist/vue.global.js\"></script>\n<script>\n  const { ref, reactive, computed, createApp } = Vue\n\n  // math helper...\n  function valueToPoint(value, index, total) {\n    var x = 0\n    var y = -value * 0.8\n    var angle = ((Math.PI * 2) / total) * index\n    var cos = Math.cos(angle)\n    var sin = Math.sin(angle)\n    var tx = x * cos - y * sin + 100\n    var ty = x * sin + y * cos + 100\n    return {\n      x: tx,\n      y: ty,\n    }\n  }\n\n  const AxisLabel = {\n    template: '<text :x=\"point.x\" :y=\"point.y\">{{stat.label}}</text>',\n    props: {\n      stat: Object,\n      index: Number,\n      total: Number,\n    },\n    setup(props) {\n      return {\n        point: computed(() =>\n          valueToPoint(+props.stat.value + 10, props.index, props.total),\n        ),\n      }\n    },\n  }\n</script>\n\n<!-- template for the polygraph component. -->\n<script type=\"text/x-template\" id=\"polygraph-template\">\n  <g>\n    <polygon :points=\"points\"></polygon>\n    <circle cx=\"100\" cy=\"100\" r=\"80\"></circle>\n    <axis-label\n      v-for=\"(stat, index) in stats\"\n      :stat=\"stat\"\n      :index=\"index\"\n      :total=\"stats.length\">\n    </axis-label>\n  </g>\n</script>\n\n<script>\n  const Polygraph = {\n    props: ['stats'],\n    template: '#polygraph-template',\n    setup(props) {\n      return {\n        points: computed(() => {\n          const total = props.stats.length\n          return props.stats\n            .map((stat, i) => {\n              const point = valueToPoint(stat.value, i, total)\n              return point.x + ',' + point.y\n            })\n            .join(' ')\n        }),\n      }\n    },\n    components: {\n      AxisLabel,\n    },\n  }\n</script>\n\n<!-- demo root element -->\n<div id=\"demo\">\n  <!-- Use the polygraph component -->\n  <svg width=\"200\" height=\"200\">\n    <polygraph :stats=\"stats\"></polygraph>\n  </svg>\n  <!-- controls -->\n  <div v-for=\"stat in stats\">\n    <label>{{stat.label}}</label>\n    <input type=\"range\" v-model=\"stat.value\" min=\"0\" max=\"100\" />\n    <span>{{stat.value}}</span>\n    <button @click=\"remove(stat)\" class=\"remove\">X</button>\n  </div>\n  <form id=\"add\">\n    <input name=\"newlabel\" v-model=\"newLabel\" />\n    <button @click=\"add\">Add a Stat</button>\n  </form>\n  <pre id=\"raw\">{{ stats }}</pre>\n</div>\n\n<script>\n  const globalStats = [\n    { label: 'A', value: 100 },\n    { label: 'B', value: 100 },\n    { label: 'C', value: 100 },\n    { label: 'D', value: 100 },\n    { label: 'E', value: 100 },\n    { label: 'F', value: 100 },\n  ]\n\n  createApp({\n    components: {\n      Polygraph,\n    },\n    setup() {\n      const newLabel = ref('')\n      const stats = reactive(globalStats)\n\n      function add(e) {\n        e.preventDefault()\n        if (!newLabel.value) return\n        stats.push({\n          label: newLabel.value,\n          value: 100,\n        })\n        newLabel.value = ''\n      }\n\n      function remove(stat) {\n        if (stats.length > 3) {\n          stats.splice(stats.indexOf(stat), 1)\n        } else {\n          alert(\"Can't delete more!\")\n        }\n      }\n\n      return {\n        newLabel,\n        stats,\n        add,\n        remove,\n      }\n    },\n  }).mount('#demo')\n</script>\n\n<style>\n  body {\n    font-family:\n      Helvetica Neue,\n      Arial,\n      sans-serif;\n  }\n\n  polygon {\n    fill: #42b983;\n    opacity: 0.75;\n  }\n\n  circle {\n    fill: transparent;\n    stroke: #999;\n  }\n\n  text {\n    font-family:\n      Helvetica Neue,\n      Arial,\n      sans-serif;\n    font-size: 10px;\n    fill: #666;\n  }\n\n  label {\n    display: inline-block;\n    margin-left: 10px;\n    width: 20px;\n  }\n\n  #raw {\n    position: absolute;\n    top: 0;\n    left: 300px;\n  }\n</style>\n"
  },
  {
    "path": "packages/vue/examples/composition/todomvc.html",
    "content": "<script src=\"../../dist/vue.global.js\"></script>\n<link\n  rel=\"stylesheet\"\n  href=\"../../../../node_modules/todomvc-app-css/index.css\"\n/>\n\n<div id=\"app\">\n  <section class=\"todoapp\">\n    <header class=\"header\">\n      <h1>todos</h1>\n      <input\n        class=\"new-todo\"\n        autofocus\n        autocomplete=\"off\"\n        placeholder=\"What needs to be done?\"\n        v-model=\"state.newTodo\"\n        @keyup.enter=\"addTodo\"\n      />\n    </header>\n    <section class=\"main\" v-show=\"state.todos.length\">\n      <input\n        id=\"toggle-all\"\n        class=\"toggle-all\"\n        type=\"checkbox\"\n        v-model=\"state.allDone\"\n      />\n      <label for=\"toggle-all\">Mark all as complete</label>\n      <ul class=\"todo-list\">\n        <li\n          v-for=\"todo in state.filteredTodos\"\n          class=\"todo\"\n          :key=\"todo.id\"\n          :class=\"{ completed: todo.completed, editing: todo === state.editedTodo }\"\n        >\n          <div class=\"view\">\n            <input class=\"toggle\" type=\"checkbox\" v-model=\"todo.completed\" />\n            <label @dblclick=\"editTodo(todo)\">{{ todo.title }}</label>\n            <button class=\"destroy\" @click=\"removeTodo(todo)\"></button>\n          </div>\n          <input\n            class=\"edit\"\n            type=\"text\"\n            v-model=\"todo.title\"\n            v-todo-focus=\"todo === state.editedTodo\"\n            @blur=\"doneEdit(todo)\"\n            @keyup.enter=\"doneEdit(todo)\"\n            @keyup.escape=\"cancelEdit(todo)\"\n          />\n        </li>\n      </ul>\n    </section>\n    <footer class=\"footer\" v-show=\"state.todos.length\">\n      <span class=\"todo-count\">\n        <strong>{{ state.remaining }}</strong>\n        <span>{{ state.remainingText }}</span>\n      </span>\n      <ul class=\"filters\">\n        <li>\n          <a href=\"#/all\" :class=\"{ selected: state.visibility === 'all' }\"\n            >All</a\n          >\n        </li>\n        <li>\n          <a\n            href=\"#/active\"\n            :class=\"{ selected: state.visibility === 'active' }\"\n            >Active</a\n          >\n        </li>\n        <li>\n          <a\n            href=\"#/completed\"\n            :class=\"{ selected: state.visibility === 'completed' }\"\n            >Completed</a\n          >\n        </li>\n      </ul>\n\n      <button\n        class=\"clear-completed\"\n        @click=\"removeCompleted\"\n        v-show=\"state.todos.length > state.remaining\"\n      >\n        Clear completed\n      </button>\n    </footer>\n  </section>\n</div>\n\n<script>\n  const { createApp, reactive, computed, watchEffect, onMounted, onUnmounted } =\n    Vue\n\n  const STORAGE_KEY = 'todos-vuejs-3.x'\n  const todoStorage = {\n    fetch() {\n      const todos = JSON.parse(localStorage.getItem(STORAGE_KEY) || '[]')\n      todos.forEach((todo, index) => {\n        todo.id = index\n      })\n      todoStorage.uid = todos.length\n      return todos\n    },\n    save(todos) {\n      localStorage.setItem(STORAGE_KEY, JSON.stringify(todos))\n    },\n  }\n\n  const filters = {\n    all(todos) {\n      return todos\n    },\n    active(todos) {\n      return todos.filter(todo => {\n        return !todo.completed\n      })\n    },\n    completed(todos) {\n      return todos.filter(function (todo) {\n        return todo.completed\n      })\n    },\n  }\n\n  function pluralize(n) {\n    return n === 1 ? 'item' : 'items'\n  }\n\n  createApp({\n    setup() {\n      const state = reactive({\n        todos: todoStorage.fetch(),\n        editedTodo: null,\n        newTodo: '',\n        beforeEditCache: '',\n        visibility: 'all',\n        remaining: computed(() => {\n          return filters.active(state.todos).length\n        }),\n        remainingText: computed(() => {\n          return ` ${pluralize(state.remaining)} left`\n        }),\n        filteredTodos: computed(() => {\n          return filters[state.visibility](state.todos)\n        }),\n        allDone: computed({\n          get: function () {\n            return state.remaining === 0\n          },\n          set: function (value) {\n            state.todos.forEach(todo => {\n              todo.completed = value\n            })\n          },\n        }),\n      })\n\n      watchEffect(() => {\n        todoStorage.save(state.todos)\n      })\n\n      onMounted(() => {\n        window.addEventListener('hashchange', onHashChange)\n        onHashChange()\n      })\n\n      onUnmounted(() => {\n        window.removeEventListener('hashchange', onHashChange)\n      })\n\n      function onHashChange() {\n        const visibility = window.location.hash.replace(/#\\/?/, '')\n        if (filters[visibility]) {\n          state.visibility = visibility\n        } else {\n          window.location.hash = ''\n          state.visibility = 'all'\n        }\n      }\n\n      function addTodo() {\n        const value = state.newTodo && state.newTodo.trim()\n        if (!value) {\n          return\n        }\n        state.todos.push({\n          id: todoStorage.uid++,\n          title: value,\n          completed: false,\n        })\n        state.newTodo = ''\n      }\n\n      function removeTodo(todo) {\n        state.todos.splice(state.todos.indexOf(todo), 1)\n      }\n\n      function editTodo(todo) {\n        state.beforeEditCache = todo.title\n        state.editedTodo = todo\n      }\n\n      function doneEdit(todo) {\n        if (!state.editedTodo) {\n          return\n        }\n        state.editedTodo = null\n        todo.title = todo.title.trim()\n        if (!todo.title) {\n          removeTodo(todo)\n        }\n      }\n\n      function cancelEdit(todo) {\n        state.editedTodo = null\n        todo.title = state.beforeEditCache\n      }\n\n      function removeCompleted() {\n        state.todos = filters.active(state.todos)\n      }\n\n      return {\n        state,\n        addTodo,\n        removeTodo,\n        editTodo,\n        doneEdit,\n        cancelEdit,\n        removeCompleted,\n      }\n    },\n\n    directives: {\n      'todo-focus': (el, { value }) => {\n        if (value) {\n          el.focus()\n        }\n      },\n    },\n  }).mount('#app')\n</script>\n"
  },
  {
    "path": "packages/vue/examples/composition/tree.html",
    "content": "<script src=\"../../dist/vue.global.js\"></script>\n\n<!-- item template -->\n<script type=\"text/x-template\" id=\"item-template\">\n  <li>\n    <div\n      :class=\"{bold: isFolder}\"\n      @click=\"toggle\"\n      @dblclick=\"changeType\">\n      {{model.name}}\n      <span v-if=\"isFolder\">[{{open ? '-' : '+'}}]</span>\n    </div>\n    <ul v-if=\"isFolder\" v-show=\"open\">\n      <tree-item\n        class=\"item\"\n        v-for=\"model in model.children\"\n        :model=\"model\">\n      </tree-item>\n      <li class=\"add\" @click=\"addChild\">+</li>\n    </ul>\n  </li>\n</script>\n<!-- item script -->\n<script>\n  const { reactive, computed, toRefs } = Vue\n\n  const TreeItem = {\n    name: 'TreeItem', // necessary for self-reference\n    template: '#item-template',\n    props: {\n      model: Object,\n    },\n    setup(props) {\n      const state = reactive({\n        open: false,\n        isFolder: computed(() => {\n          return props.model.children && props.model.children.length\n        }),\n      })\n\n      function toggle() {\n        state.open = !state.open\n      }\n\n      function changeType() {\n        if (!state.isFolder) {\n          props.model.children = []\n          addChild()\n          state.open = true\n        }\n      }\n\n      function addChild() {\n        props.model.children.push({ name: 'new stuff' })\n      }\n\n      return {\n        ...toRefs(state),\n        toggle,\n        changeType,\n        addChild,\n      }\n    },\n  }\n</script>\n\n<p>(You can double click on an item to turn it into a folder.)</p>\n\n<!-- the app root element -->\n<ul id=\"demo\">\n  <tree-item class=\"item\" :model=\"treeData\"></tree-item>\n</ul>\n\n<script>\n  const treeData = {\n    name: 'My Tree',\n    children: [\n      { name: 'hello' },\n      { name: 'wat' },\n      {\n        name: 'child folder',\n        children: [\n          {\n            name: 'child folder',\n            children: [{ name: 'hello' }, { name: 'wat' }],\n          },\n          { name: 'hello' },\n          { name: 'wat' },\n          {\n            name: 'child folder',\n            children: [{ name: 'hello' }, { name: 'wat' }],\n          },\n        ],\n      },\n    ],\n  }\n\n  Vue.createApp({\n    components: {\n      TreeItem,\n    },\n    data: () => ({\n      treeData,\n    }),\n  }).mount('#demo')\n</script>\n\n<style>\n  body {\n    font-family: Menlo, Consolas, monospace;\n    color: #444;\n  }\n  .item {\n    cursor: pointer;\n  }\n  .bold {\n    font-weight: bold;\n  }\n  ul {\n    padding-left: 1em;\n    line-height: 1.5em;\n    list-style-type: dot;\n  }\n</style>\n"
  },
  {
    "path": "packages/vue/examples/transition/list.html",
    "content": "<script src=\"../../../../node_modules/lodash/lodash.min.js\"></script>\n<script src=\"../../dist/vue.global.js\"></script>\n\n<div id=\"app\">\n  <button @click=\"insert\">insert at random index</button>\n  <button @click=\"reset\">reset</button>\n  <button @click=\"shuffle\">shuffle</button>\n  <transition-group tag=\"ul\" name=\"fade\" class=\"container\">\n    <item\n      v-for=\"item in items\"\n      class=\"item\"\n      :msg=\"item\"\n      :key=\"item\"\n      @rm=\"remove(item)\"\n    >\n    </item>\n  </transition-group>\n</div>\n\n<script>\n  const getInitialItems = () => [1, 2, 3, 4, 5]\n  let id = getInitialItems().length + 1\n\n  const Item = {\n    props: ['msg'],\n    template: `<div>{{ msg }} <button @click=\"$emit('rm')\">x</button></div>`,\n  }\n\n  Vue.createApp({\n    components: {\n      Item,\n    },\n    data() {\n      return {\n        items: getInitialItems(),\n      }\n    },\n    methods: {\n      insert() {\n        const i = Math.round(Math.random() * this.items.length)\n        this.items.splice(i, 0, id++)\n      },\n      reset() {\n        this.items = getInitialItems()\n      },\n      shuffle() {\n        this.items = _.shuffle(this.items)\n      },\n      remove(item) {\n        const i = this.items.indexOf(item)\n        if (i > -1) {\n          this.items.splice(i, 1)\n        }\n      },\n    },\n  }).mount('#app')\n</script>\n\n<style>\n  .container {\n    position: relative;\n    padding: 0;\n  }\n  .item {\n    width: 100%;\n    height: 30px;\n    background-color: #f3f3f3;\n    border: 1px solid #666;\n    box-sizing: border-box;\n  }\n  /* 1. declare transition */\n  .fade-move,\n  .fade-enter-active,\n  .fade-leave-active {\n    transition: all 0.5s cubic-bezier(0.55, 0, 0.1, 1);\n  }\n  /* 2. declare enter from and leave to state */\n  .fade-enter-from,\n  .fade-leave-to {\n    opacity: 0;\n    transform: scaleY(0.01) translate(30px, 0);\n  }\n  /* 3. ensure leaving items are taken out of layout flow so that moving\n      animations can be calculated correctly. */\n  .fade-leave-active {\n    position: absolute;\n  }\n</style>\n"
  },
  {
    "path": "packages/vue/examples/transition/modal.html",
    "content": "<script src=\"../../dist/vue.global.js\"></script>\n\n<!-- template for the modal component -->\n<script type=\"text/x-template\" id=\"modal-template\">\n  <transition name=\"modal\">\n    <div v-if=\"show\" class=\"modal-mask\">\n      <div class=\"modal-wrapper\">\n        <div class=\"modal-container\">\n\n          <div class=\"modal-header\">\n            <slot name=\"header\">\n              default header\n            </slot>\n          </div>\n\n          <div class=\"modal-body\">\n            <slot name=\"body\">\n              default body\n            </slot>\n          </div>\n\n          <div class=\"modal-footer\">\n            <slot name=\"footer\">\n              default footer\n              <button class=\"modal-default-button\" @click=\"$emit('close')\">\n                OK\n              </button>\n            </slot>\n          </div>\n        </div>\n      </div>\n    </div>\n  </transition>\n</script>\n<script>\n  const Modal = {\n    template: '#modal-template',\n    props: ['show'],\n  }\n</script>\n\n<!-- modal container that lives outside of app root -->\n<div id=\"modal-container\"></div>\n\n<!-- app -->\n<div id=\"app\">\n  <button id=\"show-modal\" @click=\"showModal = true\">Show Modal</button>\n  <teleport to=\"#modal-container\">\n    <!-- use the modal component, pass in the prop -->\n    <modal :show=\"showModal\" @close=\"showModal = false\">\n      <template #header>\n        <h3>custom header</h3>\n      </template>\n    </modal>\n  </teleport>\n</div>\n\n<script>\n  Vue.createApp({\n    components: { Modal },\n    data: () => ({\n      showModal: false,\n    }),\n  }).mount('#app')\n</script>\n\n<style>\n  .modal-mask {\n    position: fixed;\n    z-index: 9998;\n    top: 0;\n    left: 0;\n    width: 100%;\n    height: 100%;\n    background-color: rgba(0, 0, 0, 0.5);\n    display: table;\n    transition: opacity 0.3s ease;\n  }\n\n  .modal-wrapper {\n    display: table-cell;\n    vertical-align: middle;\n  }\n\n  .modal-container {\n    width: 300px;\n    margin: 0px auto;\n    padding: 20px 30px;\n    background-color: #fff;\n    border-radius: 2px;\n    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.33);\n    transition: all 0.3s ease;\n    font-family: Helvetica, Arial, sans-serif;\n  }\n\n  .modal-header h3 {\n    margin-top: 0;\n    color: #42b983;\n  }\n\n  .modal-body {\n    margin: 20px 0;\n  }\n\n  .modal-default-button {\n    float: right;\n  }\n\n  /*\n * The following styles are auto-applied to elements with\n * transition=\"modal\" when their visibility is toggled\n * by Vue.js.\n *\n * You can easily play with the modal transition by editing\n * these styles.\n */\n\n  .modal-enter-from {\n    opacity: 0;\n  }\n\n  .modal-leave-to {\n    opacity: 0;\n  }\n\n  .modal-enter-from .modal-container,\n  .modal-leave-to .modal-container {\n    -webkit-transform: scale(1.1);\n    transform: scale(1.1);\n  }\n</style>\n"
  },
  {
    "path": "packages/vue/index.js",
    "content": "'use strict'\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./dist/vue.cjs.prod.js')\n} else {\n  module.exports = require('./dist/vue.cjs.js')\n}\n"
  },
  {
    "path": "packages/vue/index.mjs",
    "content": "export * from './index.js'\n"
  },
  {
    "path": "packages/vue/jsx-runtime/index.d.ts",
    "content": "/* eslint-disable @typescript-eslint/ban-ts-comment */\nimport type { NativeElements, ReservedProps, VNode } from '@vue/runtime-dom'\n\n/**\n * JSX namespace for usage with @jsxImportsSource directive\n * when ts compilerOptions.jsx is 'react-jsx' or 'react-jsxdev'\n * https://www.typescriptlang.org/tsconfig#jsxImportSource\n */\nexport { h as jsx, h as jsxDEV, Fragment, h as jsxs } from '@vue/runtime-dom'\n\nexport namespace JSX {\n  export interface Element extends VNode {}\n  export interface ElementClass {\n    $props: {}\n  }\n  export interface ElementAttributesProperty {\n    $props: {}\n  }\n  export interface IntrinsicElements extends NativeElements {\n    // allow arbitrary elements\n    // @ts-ignore suppress ts:2374 = Duplicate string index signature.\n    [name: string]: any\n  }\n  export interface IntrinsicAttributes extends ReservedProps {}\n}\n"
  },
  {
    "path": "packages/vue/jsx-runtime/index.js",
    "content": "const { h, Fragment } = require('vue')\n\nfunction jsx(type, props, key) {\n  const { children } = props\n  delete props.children\n  if (arguments.length > 2) {\n    props.key = key\n  }\n  return h(type, props, children)\n}\n\nexports.jsx = jsx\nexports.jsxs = jsx\nexports.jsxDEV = jsx\nexports.Fragment = Fragment\n"
  },
  {
    "path": "packages/vue/jsx-runtime/index.mjs",
    "content": "import { h, Fragment } from 'vue'\n\nfunction jsx(type, props, key) {\n  const { children } = props\n  delete props.children\n  if (arguments.length > 2) {\n    props.key = key\n  }\n  return h(type, props, children)\n}\n\nexport { Fragment, jsx, jsx as jsxs, jsx as jsxDEV }\n"
  },
  {
    "path": "packages/vue/jsx-runtime/package.json",
    "content": "{\n  \"main\": \"index.js\",\n  \"module\": \"index.mjs\",\n  \"types\": \"index.d.ts\"\n}\n"
  },
  {
    "path": "packages/vue/jsx.d.ts",
    "content": "/* eslint-disable @typescript-eslint/ban-ts-comment */\n// global JSX namespace registration\n// somehow we have to copy=pase the jsx-runtime types here to make TypeScript happy\nimport type { NativeElements, ReservedProps, VNode } from '@vue/runtime-dom'\n\ndeclare global {\n  namespace JSX {\n    export interface Element extends VNode {}\n    export interface ElementClass {\n      $props: {}\n    }\n    export interface ElementAttributesProperty {\n      $props: {}\n    }\n    export interface IntrinsicElements extends NativeElements {\n      // allow arbitrary elements\n      // @ts-ignore suppress ts:2374 = Duplicate string index signature.\n      [name: string]: any\n    }\n    export interface IntrinsicAttributes extends ReservedProps {}\n  }\n}\n"
  },
  {
    "path": "packages/vue/package.json",
    "content": "{\n  \"name\": \"vue\",\n  \"version\": \"3.5.30\",\n  \"description\": \"The progressive JavaScript framework for building modern web UI.\",\n  \"main\": \"index.js\",\n  \"module\": \"dist/vue.runtime.esm-bundler.js\",\n  \"types\": \"dist/vue.d.ts\",\n  \"unpkg\": \"dist/vue.global.js\",\n  \"jsdelivr\": \"dist/vue.global.js\",\n  \"files\": [\n    \"index.js\",\n    \"index.mjs\",\n    \"dist\",\n    \"compiler-sfc\",\n    \"server-renderer\",\n    \"jsx-runtime\",\n    \"jsx.d.ts\"\n  ],\n  \"exports\": {\n    \".\": {\n      \"import\": {\n        \"types\": \"./dist/vue.d.mts\",\n        \"node\": \"./index.mjs\",\n        \"default\": \"./dist/vue.runtime.esm-bundler.js\"\n      },\n      \"require\": {\n        \"types\": \"./dist/vue.d.ts\",\n        \"node\": {\n          \"production\": \"./dist/vue.cjs.prod.js\",\n          \"development\": \"./dist/vue.cjs.js\",\n          \"default\": \"./index.js\"\n        },\n        \"default\": \"./index.js\"\n      }\n    },\n    \"./server-renderer\": {\n      \"import\": {\n        \"types\": \"./server-renderer/index.d.mts\",\n        \"default\": \"./server-renderer/index.mjs\"\n      },\n      \"require\": {\n        \"types\": \"./server-renderer/index.d.ts\",\n        \"default\": \"./server-renderer/index.js\"\n      }\n    },\n    \"./compiler-sfc\": {\n      \"import\": {\n        \"types\": \"./compiler-sfc/index.d.mts\",\n        \"browser\": \"./compiler-sfc/index.browser.mjs\",\n        \"default\": \"./compiler-sfc/index.mjs\"\n      },\n      \"require\": {\n        \"types\": \"./compiler-sfc/index.d.ts\",\n        \"browser\": \"./compiler-sfc/index.browser.js\",\n        \"default\": \"./compiler-sfc/index.js\"\n      }\n    },\n    \"./jsx-runtime\": {\n      \"types\": \"./jsx-runtime/index.d.ts\",\n      \"import\": \"./jsx-runtime/index.mjs\",\n      \"require\": \"./jsx-runtime/index.js\"\n    },\n    \"./jsx-dev-runtime\": {\n      \"types\": \"./jsx-runtime/index.d.ts\",\n      \"import\": \"./jsx-runtime/index.mjs\",\n      \"require\": \"./jsx-runtime/index.js\"\n    },\n    \"./jsx\": \"./jsx.d.ts\",\n    \"./dist/*\": \"./dist/*\",\n    \"./package.json\": \"./package.json\"\n  },\n  \"buildOptions\": {\n    \"name\": \"Vue\",\n    \"formats\": [\n      \"esm-bundler\",\n      \"esm-bundler-runtime\",\n      \"cjs\",\n      \"global\",\n      \"global-runtime\",\n      \"esm-browser\",\n      \"esm-browser-runtime\"\n    ]\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/vuejs/core.git\"\n  },\n  \"keywords\": [\n    \"vue\"\n  ],\n  \"author\": \"Evan You\",\n  \"license\": \"MIT\",\n  \"bugs\": {\n    \"url\": \"https://github.com/vuejs/core/issues\"\n  },\n  \"homepage\": \"https://github.com/vuejs/core/tree/main/packages/vue#readme\",\n  \"dependencies\": {\n    \"@vue/shared\": \"workspace:*\",\n    \"@vue/compiler-dom\": \"workspace:*\",\n    \"@vue/runtime-dom\": \"workspace:*\",\n    \"@vue/compiler-sfc\": \"workspace:*\",\n    \"@vue/server-renderer\": \"workspace:*\"\n  },\n  \"peerDependencies\": {\n    \"typescript\": \"*\"\n  },\n  \"peerDependenciesMeta\": {\n    \"typescript\": {\n      \"optional\": true\n    }\n  }\n}\n"
  },
  {
    "path": "packages/vue/server-renderer/index.d.mts",
    "content": "export * from '@vue/server-renderer'\n"
  },
  {
    "path": "packages/vue/server-renderer/index.d.ts",
    "content": "export * from '@vue/server-renderer'\n"
  },
  {
    "path": "packages/vue/server-renderer/index.js",
    "content": "module.exports = require('@vue/server-renderer')\n"
  },
  {
    "path": "packages/vue/server-renderer/index.mjs",
    "content": "export * from '@vue/server-renderer'\n"
  },
  {
    "path": "packages/vue/server-renderer/package.json",
    "content": "{\n  \"main\": \"index.js\",\n  \"module\": \"index.mjs\"\n}\n"
  },
  {
    "path": "packages/vue/src/dev.ts",
    "content": "import { initCustomFormatter } from '@vue/runtime-dom'\n\nexport function initDev(): void {\n  if (__BROWSER__) {\n    if (!__ESM_BUNDLER__) {\n      console.info(\n        `You are running a development build of Vue.\\n` +\n          `Make sure to use the production build (*.prod.js) when deploying for production.`,\n      )\n    }\n\n    initCustomFormatter()\n  }\n}\n"
  },
  {
    "path": "packages/vue/src/index.ts",
    "content": "// This entry is the \"full-build\" that includes both the runtime\n// and the compiler, and supports on-the-fly compilation of the template option.\nimport { initDev } from './dev'\nimport {\n  type CompilerError,\n  type CompilerOptions,\n  compile,\n} from '@vue/compiler-dom'\nimport {\n  type RenderFunction,\n  registerRuntimeCompiler,\n  warn,\n} from '@vue/runtime-dom'\nimport * as runtimeDom from '@vue/runtime-dom'\nimport {\n  NOOP,\n  extend,\n  genCacheKey,\n  generateCodeFrame,\n  isString,\n} from '@vue/shared'\nimport type { InternalRenderFunction } from 'packages/runtime-core/src/component'\n\nif (__DEV__) {\n  initDev()\n}\n\nconst compileCache: Record<string, RenderFunction> = Object.create(null)\n\nfunction compileToFunction(\n  template: string | HTMLElement,\n  options?: CompilerOptions,\n): RenderFunction {\n  if (!isString(template)) {\n    if (template.nodeType) {\n      template = template.innerHTML\n    } else {\n      __DEV__ && warn(`invalid template option: `, template)\n      return NOOP\n    }\n  }\n\n  const key = genCacheKey(template, options)\n  const cached = compileCache[key]\n  if (cached) {\n    return cached\n  }\n\n  if (template[0] === '#') {\n    const el = document.querySelector(template)\n    if (__DEV__ && !el) {\n      warn(`Template element not found or is empty: ${template}`)\n    }\n    // __UNSAFE__\n    // Reason: potential execution of JS expressions in in-DOM template.\n    // The user must make sure the in-DOM template is trusted. If it's rendered\n    // by the server, the template should not contain any user data.\n    template = el ? el.innerHTML : ``\n  }\n\n  const opts = extend(\n    {\n      hoistStatic: true,\n      onError: __DEV__ ? onError : undefined,\n      onWarn: __DEV__ ? e => onError(e, true) : NOOP,\n    } as CompilerOptions,\n    options,\n  )\n\n  if (!opts.isCustomElement && typeof customElements !== 'undefined') {\n    opts.isCustomElement = tag => !!customElements.get(tag)\n  }\n\n  const { code } = compile(template, opts)\n\n  function onError(err: CompilerError, asWarning = false) {\n    const message = asWarning\n      ? err.message\n      : `Template compilation error: ${err.message}`\n    const codeFrame =\n      err.loc &&\n      generateCodeFrame(\n        template as string,\n        err.loc.start.offset,\n        err.loc.end.offset,\n      )\n    warn(codeFrame ? `${message}\\n${codeFrame}` : message)\n  }\n\n  // The wildcard import results in a huge object with every export\n  // with keys that cannot be mangled, and can be quite heavy size-wise.\n  // In the global build we know `Vue` is available globally so we can avoid\n  // the wildcard object.\n  const render = (\n    __GLOBAL__ ? new Function(code)() : new Function('Vue', code)(runtimeDom)\n  ) as RenderFunction\n\n  // mark the function as runtime compiled\n  ;(render as InternalRenderFunction)._rc = true\n\n  return (compileCache[key] = render)\n}\n\nregisterRuntimeCompiler(compileToFunction)\n\nexport { compileToFunction as compile }\nexport * from '@vue/runtime-dom'\n"
  },
  {
    "path": "packages/vue/src/runtime.ts",
    "content": "// This entry exports the runtime only, and is built as\n// `dist/vue.esm-bundler.js` which is used by default for bundlers.\nimport { initDev } from './dev'\nimport { warn } from '@vue/runtime-dom'\n\nif (__DEV__) {\n  initDev()\n}\n\nexport * from '@vue/runtime-dom'\n\nexport const compile = (): void => {\n  if (__DEV__) {\n    warn(\n      `Runtime compilation is not supported in this build of Vue.` +\n        (__ESM_BUNDLER__\n          ? ` Configure your bundler to alias \"vue\" to \"vue/dist/vue.esm-bundler.js\".`\n          : __ESM_BROWSER__\n            ? ` Use \"vue.esm-browser.js\" instead.`\n            : __GLOBAL__\n              ? ` Use \"vue.global.js\" instead.`\n              : ``) /* should not happen */,\n    )\n  }\n}\n"
  },
  {
    "path": "packages/vue-compat/LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2018-present, Yuxi (Evan) You\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "packages/vue-compat/README.md",
    "content": "## Overview\n\n`@vue/compat` (aka \"the migration build\") is a build of Vue 3 that provides configurable Vue 2 compatible behavior.\n\nThe migration build runs in Vue 2 mode by default - most public APIs behave exactly like Vue 2, with only a few exceptions. Usage of features that have changed or been deprecated in Vue 3 will emit runtime warnings. A feature's compatibility can also be enabled/disabled on a per-component basis.\n\n### Intended Use Cases\n\n- Upgrading a Vue 2 application to Vue 3 (with [limitations](#known-limitations))\n- Migrating a library to support Vue 3\n- For experienced Vue 2 developers who have not tried Vue 3 yet, the migration build can be used in place of Vue 3 to help learn the difference between versions.\n\n### Known Limitations\n\nWhile we've tried hard to make the migration build mimic Vue 2 behavior as much as possible, there are some limitations that may prevent your app from being eligible for upgrading:\n\n- Dependencies that rely on Vue 2 internal APIs or undocumented behavior. The most common case is usage of private properties on `VNodes`. If your project relies on component libraries like [Vuetify](https://vuetifyjs.com/en/), [Quasar](https://quasar.dev/) or [ElementUI](https://element.eleme.io/#/en-US), it is best to wait for their Vue 3 compatible versions.\n\n- Internet Explorer 11 support: [Vue 3 has officially dropped the plan for IE11 support](https://github.com/vuejs/rfcs/blob/master/active-rfcs/0038-vue3-ie11-support.md). If you still need to support IE11 or below, you will have to stay on Vue 2.\n\n- Server-side rendering: the migration build can be used for SSR, but migrating a custom SSR setup is much more involved. The general idea is replacing `vue-server-renderer` with [`@vue/server-renderer`](https://github.com/vuejs/core/tree/main/packages/server-renderer). Vue 3 no longer provides a bundle renderer and it is recommended to use Vue 3 SSR with [Vite](https://vitejs.dev/guide/ssr.html). If you are using [Nuxt.js](https://nuxtjs.org/), it is probably better to wait for Nuxt 3.\n\n### Expectations\n\nPlease note that the migration build aims to cover only publicly documented Vue 2 APIs and behavior. If your application fails to run under the migration build due to reliance on undocumented behavior, it is unlikely that we'll tweak the migration build to cater to your specific case. Consider refactoring to remove reliance on the behavior in question instead.\n\nA word of caution: if your application is large and complex, migration will likely be a challenge even with the migration build. If your app is unfortunately not suitable for upgrade, do note that we are planning to backport Composition API and some other Vue 3 features to the 2.7 release (estimated late Q3 2021).\n\nIf you do get your app running on the migration build, you **can** ship it to production before the migration is complete. Although there is a small performance/size overhead, it should not noticeably affect production UX. You may have to do so when you have dependencies that rely on Vue 2 behavior, and cannot be upgraded/replaced.\n\nThe migration build will be provided starting with 3.1, and will continue to be published alongside the 3.2 release line. We do plan to eventually stop publishing the migration build in a future minor version (no earlier than EOY 2021), so you should still aim to switch to the standard build before then.\n\n## Upgrade Workflow\n\nThe following workflow walks through the steps of migrating an actual Vue 2 app (Vue HackerNews 2.0) to Vue 3. The full commits can be found [here](https://github.com/vuejs/vue-hackernews-2.0/compare/migration). Note that the actual steps required for your project may vary, and these steps should be treated as general guidance rather than strict instructions.\n\n### Preparations\n\n- If you are still using the [deprecated named / scoped slot syntax](https://vuejs.org/v2/guide/components-slots.html#Deprecated-Syntax), update it to the latest syntax first (which is already supported in 2.6).\n\n### Installation\n\n1. Upgrade tooling if applicable.\n   - If using custom webpack setup: Upgrade `vue-loader` to `^16.0.0`.\n   - If using `vue-cli`: upgrade to the latest `@vue/cli-service` with `vue upgrade`\n   - (Alternative) migrate to [Vite](https://vitejs.dev/) + [vite-plugin-vue2](https://github.com/underfin/vite-plugin-vue2). [[Example commit](https://github.com/vuejs/vue-hackernews-2.0/commit/565b948919eb58f22a32afca7e321b490cb3b074)]\n\n2. In `package.json`, update `vue` to 3.1, install `@vue/compat` of the same version, and replace `vue-template-compiler` (if present) with `@vue/compiler-sfc`:\n\n   ```diff\n   \"dependencies\": {\n   -  \"vue\": \"^2.6.12\",\n   +  \"vue\": \"^3.1.0\",\n   +  \"@vue/compat\": \"^3.1.0\"\n      ...\n   },\n   \"devDependencies\": {\n   -  \"vue-template-compiler\": \"^2.6.12\"\n   +  \"@vue/compiler-sfc\": \"^3.1.0\"\n   }\n   ```\n\n   [Example commit](https://github.com/vuejs/vue-hackernews-2.0/commit/14f6f1879b43f8610add60342661bf915f5c4b20)\n\n3. In the build setup, alias `vue` to `@vue/compat` and enable compat mode via Vue compiler options.\n\n   **Example Configs**\n\n   <details>\n     <summary><b>vue-cli</b></summary>\n\n   ```js\n   // vue.config.js\n   module.exports = {\n     chainWebpack: config => {\n       config.resolve.alias.set('vue', '@vue/compat')\n\n       config.module\n         .rule('vue')\n         .use('vue-loader')\n         .tap(options => {\n           return {\n             ...options,\n             compilerOptions: {\n               compatConfig: {\n                 MODE: 2,\n               },\n             },\n           }\n         })\n     },\n   }\n   ```\n\n   </details>\n\n   <details>\n     <summary><b>Plain webpack</b></summary>\n\n   ```js\n   // webpack.config.js\n   module.exports = {\n     resolve: {\n       alias: {\n         vue: '@vue/compat',\n       },\n     },\n     module: {\n       rules: [\n         {\n           test: /\\.vue$/,\n           loader: 'vue-loader',\n           options: {\n             compilerOptions: {\n               compatConfig: {\n                 MODE: 2,\n               },\n             },\n           },\n         },\n       ],\n     },\n   }\n   ```\n\n   </details>\n\n   <details>\n     <summary><b>Vite</b></summary>\n\n   ```js\n   // vite.config.js\n   export default {\n     resolve: {\n       alias: {\n         vue: '@vue/compat',\n       },\n     },\n     plugins: [\n       vue({\n         template: {\n           compilerOptions: {\n             compatConfig: {\n               MODE: 2,\n             },\n           },\n         },\n       }),\n     ],\n   }\n   ```\n\n   </details>\n\n4. At this point, your application may encounter some compile-time errors / warnings (e.g. use of filters). Fix them first. If all compiler warnings are gone, you can also set the compiler to Vue 3 mode.\n\n   [Example commit](https://github.com/vuejs/vue-hackernews-2.0/commit/b05d9555f6e115dea7016d7e5a1a80e8f825be52)\n\n5. After fixing the errors, the app should be able to run if it is not subject to the [limitations](#known-limitations) mentioned above.\n\n   You will likely see a LOT of warnings from both the command line and the browser console. Here are some general tips:\n   - You can filter for specific warnings in the browser console. It's a good idea to use the filter and focus on fixing one item at a time. You can also use negated filters like `-GLOBAL_MOUNT`.\n\n   - You can suppress specific deprecations via [compat configuration](#compat-configuration).\n\n   - Some warnings may be caused by a dependency that you use (e.g. `vue-router`). You can check this from the warning's component trace or stack trace (expanded on click). Focus on fixing the warnings that originate from your own source code first.\n\n   - If you are using `vue-router`, note `<transition>` and `<keep-alive>` will not work with `<router-view>` until you upgrade to `vue-router` v4.\n\n6. Update [`<transition>` class names](https://v3-migration.vuejs.org/breaking-changes/transition.html). This is the only feature that does not have a runtime warning. You can do a project-wide search for `.*-enter` and `.*-leave` CSS class names.\n\n   [Example commit](https://github.com/vuejs/vue-hackernews-2.0/commit/d300103ba622ae26ac26a82cd688e0f70b6c1d8f)\n\n7. Update app entry to use [new global mounting API](https://v3-migration.vuejs.org/breaking-changes/global-api.html#a-new-global-api-createapp).\n\n   [Example commit](https://github.com/vuejs/vue-hackernews-2.0/commit/a6e0c9ac7b1f4131908a4b1e43641f608593f714)\n\n8. [Upgrade `vuex` to v4](https://next.vuex.vuejs.org/guide/migrating-to-4-0-from-3-x.html).\n\n   [Example commit](https://github.com/vuejs/vue-hackernews-2.0/commit/5bfd4c61ee50f358cd5daebaa584f2c3f91e0205)\n\n9. [Upgrade `vue-router` to v4](https://next.router.vuejs.org/guide/migration/index.html). If you also use `vuex-router-sync`, you can replace it with a store getter.\n\n   After the upgrade, to use `<transition>` and `<keep-alive>` with `<router-view>` requires using the new [scoped-slot based syntax](https://next.router.vuejs.org/guide/migration/index.html#router-view-keep-alive-and-transition).\n\n   [Example commit](https://github.com/vuejs/vue-hackernews-2.0/commit/758961e73ac4089890079d4ce14996741cf9344b)\n\n10. Pick off individual warnings. Note some features have conflicting behavior between Vue 2 and Vue 3 - for example, the render function API, or the functional component vs. async component change. To migrate to Vue 3 API without affecting the rest of the application, you can opt-in to Vue 3 behavior on a per-component basis with the [`compatConfig` option](#per-component-config).\n\n    [Example commit](https://github.com/vuejs/vue-hackernews-2.0/commit/d0c7d3ae789be71b8fd56ce79cb4cb1f921f893b)\n\n11. When all warnings are fixed, you can remove the migration build and switch to Vue 3 proper. Note you may not be able to do so if you still have dependencies that rely on Vue 2 behavior.\n\n    [Example commit](https://github.com/vuejs/vue-hackernews-2.0/commit/9beb45490bc5f938c9e87b4ac1357cfb799565bd)\n\n## Compat Configuration\n\n### Global Config\n\nCompat features can be disabled individually:\n\n```js\nimport { configureCompat } from 'vue'\n\n// disable compat for certain features\nconfigureCompat({\n  FEATURE_ID_A: false,\n  FEATURE_ID_B: false,\n})\n```\n\nAlternatively, the entire application can default to Vue 3 behavior, with only certain compat features enabled:\n\n```js\nimport { configureCompat } from 'vue'\n\n// default everything to Vue 3 behavior, and only enable compat\n// for certain features\nconfigureCompat({\n  MODE: 3,\n  FEATURE_ID_A: true,\n  FEATURE_ID_B: true,\n})\n```\n\n### Per-Component Config\n\nA component can use the `compatConfig` option, which expects the same options as the global `configureCompat` method:\n\n```js\nexport default {\n  compatConfig: {\n    MODE: 3, // opt-in to Vue 3 behavior for this component only\n    FEATURE_ID_A: true, // features can also be toggled at component level\n  },\n  // ...\n}\n```\n\n### Compiler-specific Config\n\nFeatures that start with `COMPILER_` are compiler-specific: if you are using the full build (with in-browser compiler), they can be configured at runtime. However if using a build setup, they must be configured via the `compilerOptions` in the build config instead (see example configs above).\n\n## Feature Reference\n\n### Compatibility Types\n\n- ✔ Fully compatible\n- ◐ Partially Compatible with caveats\n- ⨂ Incompatible (warning only)\n- ⭘ Compat only (no warning)\n\n### Incompatible\n\n> Should be fixed upfront or will likely lead to errors\n\n| ID                                    | Type | Description                                                             | Docs                                                                                                           |\n| ------------------------------------- | ---- | ----------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |\n| GLOBAL_MOUNT_CONTAINER                | ⨂    | Mounted application does not replace the element it's mounted to        | [link](https://v3-migration.vuejs.org/breaking-changes/mount-changes.html)                                     |\n| CONFIG_DEVTOOLS                       | ⨂    | production devtools is now a build-time flag                            | [link](https://github.com/vuejs/core/tree/main/packages/vue#bundler-build-feature-flags)                       |\n| COMPILER_V_IF_V_FOR_PRECEDENCE        | ⨂    | `v-if` and `v-for` precedence when used on the same element has changed | [link](https://v3-migration.vuejs.org/breaking-changes/v-if-v-for.html)                                        |\n| COMPILER_V_IF_SAME_KEY                | ⨂    | `v-if` branches can no longer have the same key                         | [link](https://v3-migration.vuejs.org/breaking-changes/key-attribute.html#on-conditional-branches)             |\n| COMPILER_V_FOR_TEMPLATE_KEY_PLACEMENT | ⨂    | `<template v-for>` key should now be placed on `<template>`             | [link](https://v3-migration.vuejs.org/breaking-changes/key-attribute.html#with-template-v-for)                 |\n| COMPILER_SFC_FUNCTIONAL               | ⨂    | `<template functional>` is no longer supported in SFCs                  | [link](https://v3-migration.vuejs.org/breaking-changes/functional-components.html#single-file-components-sfcs) |\n\n### Partially Compatible with Caveats\n\n| ID                       | Type | Description                                                                                                                                                                                | Docs                                                                                                                         |\n| ------------------------ | ---- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------- |\n| CONFIG_IGNORED_ELEMENTS  | ◐    | `config.ignoredElements` is now `config.compilerOptions.isCustomElement` (only in browser compiler build). If using build setup, `isCustomElement` must be passed via build configuration. | [link](https://v3-migration.vuejs.org/breaking-changes/global-api.html#config-ignoredelements-is-now-config-iscustomelement) |\n| COMPILER_INLINE_TEMPLATE | ◐    | `inline-template` removed (compat only supported in browser compiler build)                                                                                                                | [link](https://v3-migration.vuejs.org/breaking-changes/inline-template-attribute.html)                                       |\n| PROPS_DEFAULT_THIS       | ◐    | props default factory no longer have access to `this` (in compat mode, `this` is not a real instance - it only exposes props, `$options` and injections)                                   | [link](https://v3-migration.vuejs.org/breaking-changes/props-default-this.html)                                              |\n| INSTANCE_DESTROY         | ◐    | `$destroy` instance method removed (in compat mode, only supported on root instance)                                                                                                       |                                                                                                                              |\n| GLOBAL_PRIVATE_UTIL      | ◐    | `Vue.util` is private and no longer available                                                                                                                                              |                                                                                                                              |\n| CONFIG_PRODUCTION_TIP    | ◐    | `config.productionTip` no longer necessary                                                                                                                                                 | [link](https://v3-migration.vuejs.org/breaking-changes/global-api.html#config-productiontip-removed)                         |\n| CONFIG_SILENT            | ◐    | `config.silent` removed                                                                                                                                                                    |\n\n### Compat only (no warning)\n\n| ID                 | Type | Description                            | Docs                                                                    |\n| ------------------ | ---- | -------------------------------------- | ----------------------------------------------------------------------- |\n| TRANSITION_CLASSES | ⭘    | Transition enter/leave classes changed | [link](https://v3-migration.vuejs.org/breaking-changes/transition.html) |\n\n### Fully Compatible\n\n| ID                           | Type | Description                                                           | Docs                                                                                                                      |\n| ---------------------------- | ---- | --------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |\n| GLOBAL_MOUNT                 | ✔    | new Vue() -> createApp                                                | [link](https://v3-migration.vuejs.org/breaking-changes/global-api.html#mounting-app-instance)                             |\n| GLOBAL_EXTEND                | ✔    | Vue.extend removed (use `defineComponent` or `extends` option)        | [link](https://v3-migration.vuejs.org/breaking-changes/global-api.html#vue-extend-replaced-by-definecomponent)            |\n| GLOBAL_PROTOTYPE             | ✔    | `Vue.prototype` -> `app.config.globalProperties`                      | [link](https://v3-migration.vuejs.org/breaking-changes/global-api.html#vue-prototype-replaced-by-config-globalproperties) |\n| GLOBAL_SET                   | ✔    | `Vue.set` removed (no longer needed)                                  |                                                                                                                           |\n| GLOBAL_DELETE                | ✔    | `Vue.delete` removed (no longer needed)                               |                                                                                                                           |\n| GLOBAL_OBSERVABLE            | ✔    | `Vue.observable` removed (use `reactive`)                             | [link](https://vuejs.org/api/reactivity-core.html#reactive)                                                               |\n| CONFIG_KEY_CODES             | ✔    | config.keyCodes removed                                               | [link](https://v3-migration.vuejs.org/breaking-changes/keycode-modifiers.html)                                            |\n| CONFIG_WHITESPACE            | ✔    | In Vue 3 whitespace defaults to `\"condense\"`                          |                                                                                                                           |\n| INSTANCE_SET                 | ✔    | `vm.$set` removed (no longer needed)                                  |                                                                                                                           |\n| INSTANCE_DELETE              | ✔    | `vm.$delete` removed (no longer needed)                               |                                                                                                                           |\n| INSTANCE_EVENT_EMITTER       | ✔    | `vm.$on`, `vm.$off`, `vm.$once` removed                               | [link](https://v3-migration.vuejs.org/breaking-changes/events-api.html)                                                   |\n| INSTANCE_EVENT_HOOKS         | ✔    | Instance no longer emits `hook:x` events                              | [link](https://v3-migration.vuejs.org/breaking-changes/vnode-lifecycle-events.html)                                       |\n| INSTANCE_CHILDREN            | ✔    | `vm.$children` removed                                                | [link](https://v3-migration.vuejs.org/breaking-changes/children.html)                                                     |\n| INSTANCE_LISTENERS           | ✔    | `vm.$listeners` removed                                               | [link](https://v3-migration.vuejs.org/breaking-changes/listeners-removed.html)                                            |\n| INSTANCE_SCOPED_SLOTS        | ✔    | `vm.$scopedSlots` removed; `vm.$slots` now exposes functions          | [link](https://v3-migration.vuejs.org/breaking-changes/slots-unification.html)                                            |\n| INSTANCE_ATTRS_CLASS_STYLE   | ✔    | `$attrs` now includes `class` and `style`                             | [link](https://v3-migration.vuejs.org/breaking-changes/attrs-includes-class-style.html)                                   |\n| OPTIONS_DATA_FN              | ✔    | `data` must be a function in all cases                                | [link](https://v3-migration.vuejs.org/breaking-changes/data-option.html)                                                  |\n| OPTIONS_DATA_MERGE           | ✔    | `data` from mixin or extension is now shallow merged                  | [link](https://v3-migration.vuejs.org/breaking-changes/data-option.html)                                                  |\n| OPTIONS_BEFORE_DESTROY       | ✔    | `beforeDestroy` -> `beforeUnmount`                                    |                                                                                                                           |\n| OPTIONS_DESTROYED            | ✔    | `destroyed` -> `unmounted`                                            |                                                                                                                           |\n| WATCH_ARRAY                  | ✔    | watching an array no longer triggers on mutation unless deep          | [link](https://v3-migration.vuejs.org/breaking-changes/watch.html)                                                        |\n| V_ON_KEYCODE_MODIFIER        | ✔    | `v-on` no longer supports keyCode modifiers                           | [link](https://v3-migration.vuejs.org/breaking-changes/keycode-modifiers.html)                                            |\n| CUSTOM_DIR                   | ✔    | Custom directive hook names changed                                   | [link](https://v3-migration.vuejs.org/breaking-changes/custom-directives.html)                                            |\n| ATTR_FALSE_VALUE             | ✔    | No longer removes attribute if binding value is boolean `false`       | [link](https://v3-migration.vuejs.org/breaking-changes/attribute-coercion.html)                                           |\n| ATTR_ENUMERATED_COERCION     | ✔    | No longer special case enumerated attributes                          | [link](https://v3-migration.vuejs.org/breaking-changes/attribute-coercion.html)                                           |\n| TRANSITION_GROUP_ROOT        | ✔    | `<transition-group>` no longer renders a root element by default      | [link](https://v3-migration.vuejs.org/breaking-changes/transition-group.html)                                             |\n| COMPONENT_ASYNC              | ✔    | Async component API changed (now requires `defineAsyncComponent`)     | [link](https://v3-migration.vuejs.org/breaking-changes/async-components.html)                                             |\n| COMPONENT_FUNCTIONAL         | ✔    | Functional component API changed (now must be plain functions)        | [link](https://v3-migration.vuejs.org/breaking-changes/functional-components.html)                                        |\n| COMPONENT_V_MODEL            | ✔    | Component v-model reworked                                            | [link](https://v3-migration.vuejs.org/breaking-changes/v-model.html)                                                      |\n| RENDER_FUNCTION              | ✔    | Render function API changed                                           | [link](https://v3-migration.vuejs.org/breaking-changes/render-function-api.html)                                          |\n| FILTERS                      | ✔    | Filters removed (this option affects only runtime filter APIs)        | [link](https://v3-migration.vuejs.org/breaking-changes/filters.html)                                                      |\n| COMPILER_IS_ON_ELEMENT       | ✔    | `is` usage is now restricted to `<component>` only                    | [link](https://v3-migration.vuejs.org/breaking-changes/custom-elements-interop.html)                                      |\n| COMPILER_V_BIND_SYNC         | ✔    | `v-bind.sync` replaced by `v-model` with arguments                    | [link](https://v3-migration.vuejs.org/breaking-changes/v-model.html)                                                      |\n| COMPILER_V_BIND_OBJECT_ORDER | ✔    | `v-bind=\"object\"` is now order sensitive                              | [link](https://v3-migration.vuejs.org/breaking-changes/v-bind.html)                                                       |\n| COMPILER_V_ON_NATIVE         | ✔    | `v-on.native` modifier removed                                        | [link](https://v3-migration.vuejs.org/breaking-changes/v-on-native-modifier-removed.html)                                 |\n| COMPILER_V_FOR_REF           | ✔    | `ref` in `v-for` (compiler support)                                   |                                                                                                                           |\n| COMPILER_NATIVE_TEMPLATE     | ✔    | `<template>` with no special directives now renders as native element |                                                                                                                           |\n| COMPILER_FILTERS             | ✔    | filters (compiler support)                                            |                                                                                                                           |\n"
  },
  {
    "path": "packages/vue-compat/__tests__/compiler.spec.ts",
    "content": "import Vue from '@vue/compat'\nimport { nextTick } from '@vue/runtime-core'\nimport { CompilerDeprecationTypes } from '@vue/compiler-core'\nimport { toggleDeprecationWarning } from '../../runtime-core/src/compat/compatConfig'\nimport { triggerEvent } from './utils'\n\nbeforeEach(() => {\n  toggleDeprecationWarning(false)\n  Vue.configureCompat({\n    MODE: 2,\n  })\n})\n\nafterEach(() => {\n  toggleDeprecationWarning(false)\n  Vue.configureCompat({ MODE: 3 })\n})\n\n// COMPILER_V_FOR_REF is tested in ./refInfor.spec.ts\n// COMPILER_FILTERS is tested in ./filters.spec.ts\n\ntest('COMPILER_IS_ON_ELEMENT', () => {\n  const MyButton = {\n    template: `<div><slot/></div>`,\n  }\n\n  const vm = new Vue({\n    template: `<button is=\"my-button\">text</button>`,\n    components: {\n      MyButton,\n    },\n  }).$mount()\n\n  expect(vm.$el).toBeInstanceOf(HTMLDivElement)\n  expect(vm.$el.outerHTML).toBe(`<div>text</div>`)\n  expect(CompilerDeprecationTypes.COMPILER_IS_ON_ELEMENT).toHaveBeenWarned()\n})\n\ntest('COMPILER_IS_ON_ELEMENT (dynamic)', () => {\n  const MyButton = {\n    template: `<div><slot/></div>`,\n  }\n\n  const vm = new Vue({\n    template: `<button :is=\"'MyButton'\">text</button>`,\n    components: {\n      MyButton,\n    },\n  }).$mount()\n\n  expect(vm.$el).toBeInstanceOf(HTMLDivElement)\n  expect(vm.$el.outerHTML).toBe(`<div>text</div>`)\n  expect(CompilerDeprecationTypes.COMPILER_IS_ON_ELEMENT).toHaveBeenWarned()\n})\n\ntest('COMPILER_V_BIND_SYNC', async () => {\n  const MyButton = {\n    props: ['foo'],\n    template: `<button @click=\"$emit('update:foo', 1)\">{{ foo }}</button>`,\n  }\n\n  const vm = new Vue({\n    data() {\n      return {\n        foo: 0,\n      }\n    },\n    template: `<my-button :foo.sync=\"foo\" />`,\n    components: {\n      MyButton,\n    },\n  }).$mount()\n\n  expect(vm.$el).toBeInstanceOf(HTMLButtonElement)\n  expect(vm.$el.textContent).toBe(`0`)\n\n  triggerEvent(vm.$el as Element, 'click')\n  await nextTick()\n  expect(vm.$el.textContent).toBe(`1`)\n\n  expect(CompilerDeprecationTypes.COMPILER_V_BIND_SYNC).toHaveBeenWarned()\n})\n\ntest('COMPILER_V_BIND_OBJECT_ORDER', () => {\n  const vm = new Vue({\n    template: `<div id=\"foo\" v-bind=\"{ id: 'bar', class: 'baz' }\" />`,\n  }).$mount()\n  expect(vm.$el).toBeInstanceOf(HTMLDivElement)\n  expect(vm.$el.id).toBe('foo')\n  expect(vm.$el.className).toBe('baz')\n  expect(\n    CompilerDeprecationTypes.COMPILER_V_BIND_OBJECT_ORDER,\n  ).toHaveBeenWarned()\n})\n\ntest('should not warn COMPILER_V_BIND_OBJECT_ORDER work with vFor', () => {\n  const vm = new Vue({\n    template: `<div><div v-bind=\"{ id: 'bar', class: 'baz' }\" v-for=\"item in 5\" /></div>`,\n  }).$mount()\n  expect(vm.$el).toBeInstanceOf(HTMLDivElement)\n  expect(\n    CompilerDeprecationTypes.COMPILER_V_BIND_OBJECT_ORDER,\n  ).not.toHaveBeenWarned()\n})\n\ntest('COMPILER_V_ON_NATIVE', () => {\n  const spy = vi.fn()\n  const vm = new Vue({\n    template: `<child @click=\"spy\" @click.native=\"spy\" />`,\n    components: {\n      child: {\n        template: `<button />`,\n      },\n    },\n    methods: {\n      spy,\n    },\n  }).$mount()\n\n  expect(vm.$el).toBeInstanceOf(HTMLButtonElement)\n  triggerEvent(vm.$el as HTMLButtonElement, 'click')\n  expect(spy).toHaveBeenCalledTimes(1)\n  expect(CompilerDeprecationTypes.COMPILER_V_ON_NATIVE).toHaveBeenWarned()\n})\n\ntest('COMPILER_V_IF_V_FOR_PRECEDENCE', () => {\n  new Vue({ template: `<div v-if=\"true\" v-for=\"i in 1\"/>` }).$mount()\n  expect(\n    CompilerDeprecationTypes.COMPILER_V_IF_V_FOR_PRECEDENCE,\n  ).toHaveBeenWarned()\n})\n\ntest('COMPILER_NATIVE_TEMPLATE', () => {\n  const vm = new Vue({\n    template: `<div><template><div/></template></div>`,\n  }).$mount()\n\n  expect(vm.$el).toBeInstanceOf(HTMLDivElement)\n  expect(vm.$el.innerHTML).toBe(`<div></div>`)\n  expect(CompilerDeprecationTypes.COMPILER_NATIVE_TEMPLATE).toHaveBeenWarned()\n})\n\ntest('COMPILER_INLINE_TEMPLATE', () => {\n  const vm = new Vue({\n    template: `<foo inline-template><div>{{ n }}</div></foo>`,\n    components: {\n      foo: {\n        data() {\n          return { n: 123 }\n        },\n      },\n    },\n  }).$mount()\n\n  expect(vm.$el).toBeInstanceOf(HTMLDivElement)\n  expect(vm.$el?.outerHTML).toBe(`<div>123</div>`)\n  expect(CompilerDeprecationTypes.COMPILER_INLINE_TEMPLATE).toHaveBeenWarned()\n})\n"
  },
  {
    "path": "packages/vue-compat/__tests__/componentAsync.spec.ts",
    "content": "import Vue from '@vue/compat'\nimport {\n  DeprecationTypes,\n  deprecationData,\n  toggleDeprecationWarning,\n} from '../../runtime-core/src/compat/compatConfig'\n\nbeforeEach(() => {\n  toggleDeprecationWarning(true)\n  Vue.configureCompat({\n    MODE: 2,\n    GLOBAL_MOUNT: 'suppress-warning',\n  })\n})\n\nafterEach(() => {\n  toggleDeprecationWarning(false)\n  Vue.configureCompat({ MODE: 3 })\n})\n\nconst timeout = (n: number) => new Promise(r => setTimeout(r, n))\n\ndescribe('COMPONENT_ASYNC', () => {\n  test('resolve/reject', async () => {\n    let resolve: any\n    const comp = (r: any) => {\n      resolve = r\n    }\n    const vm = new Vue({\n      template: `<div><comp/></div>`,\n      components: { comp },\n    }).$mount()\n\n    expect(vm.$el).toBeInstanceOf(HTMLDivElement)\n    expect(vm.$el.innerHTML).toBe(`<!---->`)\n\n    resolve({ template: 'foo' })\n    await timeout(0)\n    expect(vm.$el.innerHTML).toBe(`foo`)\n\n    expect(\n      (deprecationData[DeprecationTypes.COMPONENT_ASYNC].message as Function)(\n        comp,\n      ),\n    ).toHaveBeenWarned()\n  })\n\n  test('Promise', async () => {\n    const comp = () => Promise.resolve({ template: 'foo' })\n    const vm = new Vue({\n      template: `<div><comp/></div>`,\n      components: { comp },\n    }).$mount()\n    expect(vm.$el).toBeInstanceOf(HTMLDivElement)\n    expect(vm.$el.innerHTML).toBe(`<!---->`)\n    await timeout(0)\n    expect(vm.$el.innerHTML).toBe(`foo`)\n\n    expect(\n      (deprecationData[DeprecationTypes.COMPONENT_ASYNC].message as Function)(\n        comp,\n      ),\n    ).toHaveBeenWarned()\n  })\n\n  test('object syntax', async () => {\n    const comp = () => ({\n      component: Promise.resolve({ template: 'foo' }),\n    })\n\n    const vm = new Vue({\n      template: `<div><comp/></div>`,\n      components: { comp },\n    }).$mount()\n\n    expect(vm.$el).toBeInstanceOf(HTMLDivElement)\n    expect(vm.$el.innerHTML).toBe(`<!---->`)\n    await timeout(0)\n    expect(vm.$el.innerHTML).toBe(`foo`)\n\n    expect(\n      (deprecationData[DeprecationTypes.COMPONENT_ASYNC].message as Function)(\n        comp,\n      ),\n    ).toHaveBeenWarned()\n  })\n})\n"
  },
  {
    "path": "packages/vue-compat/__tests__/componentFunctional.spec.ts",
    "content": "import Vue from '@vue/compat'\nimport {\n  DeprecationTypes,\n  deprecationData,\n  toggleDeprecationWarning,\n} from '../../runtime-core/src/compat/compatConfig'\n\nbeforeEach(() => {\n  toggleDeprecationWarning(true)\n  Vue.configureCompat({\n    MODE: 2,\n    GLOBAL_MOUNT: 'suppress-warning',\n  })\n})\n\nafterEach(() => {\n  toggleDeprecationWarning(false)\n  Vue.configureCompat({ MODE: 3 })\n})\n\ndescribe('COMPONENT_FUNCTIONAL', () => {\n  test('basic usage', async () => {\n    const func = {\n      name: 'Func',\n      functional: true,\n      props: {\n        x: String,\n      },\n      inject: ['foo'],\n      render: (h: any, { data, props, injections, slots }: any) => {\n        return h('div', { id: props.x, class: data.class }, [\n          h('div', { class: 'inject' }, injections.foo),\n          h('div', { class: 'slot' }, slots().default),\n        ])\n      },\n    }\n\n    const vm = new Vue({\n      provide() {\n        return {\n          foo: 123,\n        }\n      },\n      components: {\n        func,\n      },\n      template: `<func class=\"foo\" x=\"foo\">hello</func>`,\n    }).$mount()\n\n    expect(vm.$el.id).toBe('foo')\n    expect(vm.$el.className).toBe('foo')\n    expect(vm.$el.querySelector('.inject').textContent).toBe('123')\n    expect(vm.$el.querySelector('.slot').textContent).toBe('hello')\n    expect(vm.$el.outerHTML).toMatchInlineSnapshot(\n      `\"<div id=\"foo\" class=\"foo\"><div class=\"inject\">123</div><div class=\"slot\">hello</div></div>\"`,\n    )\n\n    expect(\n      (\n        deprecationData[DeprecationTypes.COMPONENT_FUNCTIONAL]\n          .message as Function\n      )(func),\n    ).toHaveBeenWarned()\n  })\n\n  test('copies compatConfig option', () => {\n    const func = {\n      name: 'Func',\n      functional: true,\n      compatConfig: {\n        ATTR_FALSE_VALUE: 'suppress-warning' as const,\n      },\n      render: (h: any) => {\n        // should not render required: false due to compatConfig\n        return h('div', { 'data-some-attr': false })\n      },\n    }\n\n    const vm = new Vue({\n      components: { func },\n      template: `<func class=\"foo\" x=\"foo\">hello</func>`,\n    }).$mount()\n\n    expect(vm.$el.outerHTML).toMatchInlineSnapshot(`\"<div></div>\"`)\n    expect(\n      (\n        deprecationData[DeprecationTypes.COMPONENT_FUNCTIONAL]\n          .message as Function\n      )(func),\n    ).toHaveBeenWarned()\n    expect(\n      (deprecationData[DeprecationTypes.ATTR_FALSE_VALUE].message as Function)(\n        func,\n      ),\n    ).not.toHaveBeenWarned()\n  })\n})\n"
  },
  {
    "path": "packages/vue-compat/__tests__/componentVModel.spec.ts",
    "content": "import Vue from '@vue/compat'\nimport type { ComponentOptions } from '../../runtime-core/src/component'\nimport { nextTick } from '../../runtime-core/src/scheduler'\nimport {\n  DeprecationTypes,\n  deprecationData,\n  toggleDeprecationWarning,\n} from '../../runtime-core/src/compat/compatConfig'\nimport { triggerEvent } from './utils'\n\nbeforeEach(() => {\n  toggleDeprecationWarning(true)\n  Vue.configureCompat({\n    MODE: 2,\n    GLOBAL_MOUNT: 'suppress-warning',\n  })\n})\n\nafterEach(() => {\n  toggleDeprecationWarning(false)\n  Vue.configureCompat({ MODE: 3 })\n})\n\ndescribe('COMPONENT_V_MODEL', () => {\n  async function runTest(CustomInput: ComponentOptions) {\n    const vm = new Vue({\n      data() {\n        return {\n          text: 'foo',\n        }\n      },\n      components: { CustomInput },\n      template: `\n      <div>\n        <span>{{ text }}</span>\n        <custom-input v-model=\"text\"></custom-input>\n      </div>\n      `,\n    }).$mount() as any\n\n    const input = vm.$el.querySelector('input')\n    const span = vm.$el.querySelector('span')\n\n    expect(input.value).toBe('foo')\n    expect(span.textContent).toBe('foo')\n\n    expect(\n      (deprecationData[DeprecationTypes.COMPONENT_V_MODEL].message as Function)(\n        CustomInput,\n      ),\n    ).toHaveBeenWarned()\n\n    input.value = 'bar'\n    triggerEvent(input, 'input')\n    await nextTick()\n\n    expect(input.value).toBe('bar')\n    expect(span.textContent).toBe('bar')\n\n    vm.text = 'baz'\n    await nextTick()\n    expect(input.value).toBe('baz')\n    expect(span.textContent).toBe('baz')\n  }\n\n  test('basic usage', async () => {\n    await runTest({\n      name: 'CustomInput',\n      props: ['value'],\n      template: `<input :value=\"value\" @input=\"$emit('input', $event.target.value)\">`,\n    })\n  })\n\n  test('with model option', async () => {\n    await runTest({\n      name: 'CustomInput',\n      props: ['input'],\n      model: {\n        prop: 'input',\n        event: 'update',\n      },\n      template: `<input :value=\"input\" @input=\"$emit('update', $event.target.value)\">`,\n    })\n  })\n\n  async function runTestWithModifier(CustomInput: ComponentOptions) {\n    const vm = new Vue({\n      data() {\n        return {\n          text: ' foo ',\n        }\n      },\n      components: {\n        CustomInput,\n      },\n      template: `\n      <div>\n        <span>{{ text }}</span>\n        <custom-input v-model.trim=\"text\"></custom-input>\n      </div>\n      `,\n    }).$mount() as any\n\n    const input = vm.$el.querySelector('input')\n    const span = vm.$el.querySelector('span')\n\n    expect(input.value).toBe(' foo ')\n    expect(span.textContent).toBe(' foo ')\n\n    expect(\n      (deprecationData[DeprecationTypes.COMPONENT_V_MODEL].message as Function)(\n        CustomInput,\n      ),\n    ).toHaveBeenWarned()\n\n    input.value = ' bar '\n    triggerEvent(input, 'input')\n    await nextTick()\n\n    expect(input.value).toBe('bar')\n    expect(span.textContent).toBe('bar')\n  }\n\n  test('with model modifiers', async () => {\n    await runTestWithModifier({\n      name: 'CustomInput',\n      props: ['value'],\n      template: `<input :value=\"value\" @input=\"$emit('input', $event.target.value)\">`,\n    })\n  })\n\n  test('with model modifiers and model option', async () => {\n    await runTestWithModifier({\n      name: 'CustomInput',\n      props: ['foo'],\n      model: {\n        prop: 'foo',\n        event: 'bar',\n      },\n      template: `<input :value=\"foo\" @input=\"$emit('bar', $event.target.value)\">`,\n    })\n  })\n\n  // #14202\n  test('should handle v-model deprecation warning with missing appContext', async () => {\n    const ChildComponent = {\n      template: `<div @click=\"$emit('input', 'new val')\">{{ value }}</div>`,\n      props: ['value'],\n    }\n\n    const vm = new Vue({\n      components: { ChildComponent },\n      data() {\n        return {\n          myVal: 'initial',\n        }\n      },\n      template: `\n        <div>\n          <child-component v-model=\"myVal\"></child-component>\n        </div>\n      `,\n    }).$mount() as any\n\n    expect(vm.$el.textContent).toContain('initial')\n\n    expect(\n      (deprecationData[DeprecationTypes.COMPONENT_V_MODEL].message as Function)(\n        ChildComponent,\n      ),\n    ).toHaveBeenWarned()\n\n    // Should work correctly\n    const child = vm.$el.querySelector('div')\n    child.click()\n    await nextTick()\n    expect(vm.myVal).toBe('new val')\n    expect(vm.$el.textContent).toContain('new val')\n  })\n})\n"
  },
  {
    "path": "packages/vue-compat/__tests__/filters.spec.ts",
    "content": "import Vue from '@vue/compat'\nimport { CompilerDeprecationTypes } from '../../compiler-core/src'\nimport {\n  DeprecationTypes,\n  deprecationData,\n  toggleDeprecationWarning,\n} from '../../runtime-core/src/compat/compatConfig'\n\nbeforeEach(() => {\n  toggleDeprecationWarning(false)\n  Vue.configureCompat({ MODE: 2, GLOBAL_MOUNT: 'suppress-warning' })\n})\n\nafterEach(() => {\n  Vue.configureCompat({ MODE: 3 })\n  toggleDeprecationWarning(false)\n})\n\ndescribe('FILTERS', () => {\n  function upper(v: string) {\n    return v.toUpperCase()\n  }\n\n  function lower(v: string) {\n    return v.toLowerCase()\n  }\n\n  function reverse(v: string) {\n    return v.split('').reverse().join('')\n  }\n\n  function double(v: number) {\n    return v * 2\n  }\n\n  it('global registration', () => {\n    toggleDeprecationWarning(true)\n    Vue.filter('globalUpper', upper)\n    expect(Vue.filter('globalUpper')).toBe(upper)\n    const vm = new Vue({\n      template: '<div>{{ msg | globalUpper }}</div>',\n      data: () => ({\n        msg: 'hi',\n      }),\n    }).$mount()\n    expect(vm.$el).toBeInstanceOf(HTMLDivElement)\n    expect(vm.$el.textContent).toBe('HI')\n    expect(deprecationData[DeprecationTypes.FILTERS].message).toHaveBeenWarned()\n    expect(CompilerDeprecationTypes.COMPILER_FILTERS).toHaveBeenWarned()\n    Vue.filter('globalUpper', undefined)\n  })\n\n  it('basic usage', () => {\n    const vm = new Vue({\n      template: '<div>{{ msg | upper }}</div>',\n      data: () => ({\n        msg: 'hi',\n      }),\n      filters: {\n        upper,\n      },\n    }).$mount()\n    expect(vm.$el.textContent).toBe('HI')\n    expect(CompilerDeprecationTypes.COMPILER_FILTERS).toHaveBeenWarned()\n  })\n\n  it('chained usage', () => {\n    const vm = new Vue({\n      template: '<div>{{ msg | upper | reverse }}</div>',\n      data: () => ({\n        msg: 'hi',\n      }),\n      filters: {\n        upper,\n        reverse,\n      },\n    }).$mount()\n    expect(vm.$el.textContent).toBe('IH')\n    expect(CompilerDeprecationTypes.COMPILER_FILTERS).toHaveBeenWarned()\n  })\n\n  it('in v-bind', () => {\n    const vm = new Vue({\n      template: `\n        <div\n          v-bind:id=\"id | upper | reverse\"\n          :class=\"cls | reverse\"\n          :ref=\"ref | lower\">\n        </div>\n      `,\n      filters: {\n        upper,\n        reverse,\n        lower,\n      },\n      data: () => ({\n        id: 'abc',\n        cls: 'foo',\n        ref: 'BAR',\n      }),\n    }).$mount()\n    expect(vm.$el.id).toBe('CBA')\n    expect(vm.$el.className).toBe('oof')\n    expect(vm.$refs.bar).toBe(vm.$el)\n    expect(CompilerDeprecationTypes.COMPILER_FILTERS).toHaveBeenWarned()\n  })\n\n  it('handle regex with pipe', () => {\n    const vm = new Vue({\n      template: `<test ref=\"test\" :pattern=\"/a|b\\\\// | identity\"></test>`,\n      filters: { identity: (v: any) => v },\n      components: {\n        test: {\n          props: ['pattern'],\n          template: '<div></div>',\n        },\n      },\n    }).$mount() as any\n    expect(vm.$refs.test.pattern).toBeInstanceOf(RegExp)\n    expect(vm.$refs.test.pattern.toString()).toBe('/a|b\\\\//')\n    expect(CompilerDeprecationTypes.COMPILER_FILTERS).toHaveBeenWarned()\n  })\n\n  it('handle division', () => {\n    const vm = new Vue({\n      data: () => ({ a: 2 }),\n      template: `<div>{{ 1/a / 4 | double }}</div>`,\n      filters: { double },\n    }).$mount()\n    expect(vm.$el.textContent).toBe(String(1 / 4))\n    expect(CompilerDeprecationTypes.COMPILER_FILTERS).toHaveBeenWarned()\n  })\n\n  it('handle division with parenthesis', () => {\n    const vm = new Vue({\n      data: () => ({ a: 20 }),\n      template: `<div>{{ (a*2) / 5 | double }}</div>`,\n      filters: { double },\n    }).$mount()\n    expect(vm.$el.textContent).toBe(String(16))\n    expect(CompilerDeprecationTypes.COMPILER_FILTERS).toHaveBeenWarned()\n  })\n\n  it('handle division with dot', () => {\n    const vm = new Vue({\n      template: `<div>{{ 20. / 5 | double }}</div>`,\n      filters: { double },\n    }).$mount()\n    expect(vm.$el.textContent).toBe(String(8))\n    expect(CompilerDeprecationTypes.COMPILER_FILTERS).toHaveBeenWarned()\n  })\n\n  it('handle division with array values', () => {\n    const vm = new Vue({\n      data: () => ({ a: [20] }),\n      template: `<div>{{ a[0] / 5 | double }}</div>`,\n      filters: { double },\n    }).$mount()\n    expect(vm.$el.textContent).toBe(String(8))\n    expect(CompilerDeprecationTypes.COMPILER_FILTERS).toHaveBeenWarned()\n  })\n\n  it('handle division with hash values', () => {\n    const vm = new Vue({\n      data: () => ({ a: { n: 20 } }),\n      template: `<div>{{ a['n'] / 5 | double }}</div>`,\n      filters: { double },\n    }).$mount()\n    expect(vm.$el.textContent).toBe(String(8))\n    expect(CompilerDeprecationTypes.COMPILER_FILTERS).toHaveBeenWarned()\n  })\n\n  it('handle division with variable_', () => {\n    const vm = new Vue({\n      data: () => ({ a_: 8 }),\n      template: `<div>{{ a_ / 2 | double }}</div>`,\n      filters: { double },\n    }).$mount()\n    expect(vm.$el.textContent).toBe(String(8))\n    expect(CompilerDeprecationTypes.COMPILER_FILTERS).toHaveBeenWarned()\n  })\n\n  it('arguments', () => {\n    const vm = new Vue({\n      template: `<div>{{ msg | add(a, 3) }}</div>`,\n      data: () => ({\n        msg: 1,\n        a: 2,\n      }),\n      filters: {\n        add: (v: number, arg1: number, arg2: number) => v + arg1 + arg2,\n      },\n    }).$mount()\n    expect(vm.$el.textContent).toBe('6')\n    expect(CompilerDeprecationTypes.COMPILER_FILTERS).toHaveBeenWarned()\n  })\n\n  it('quotes', () => {\n    const vm = new Vue({\n      template: `<div>{{ msg + \"b | c\" + 'd' | upper }}</div>`,\n      data: () => ({\n        msg: 'a',\n      }),\n      filters: {\n        upper,\n      },\n    }).$mount()\n    expect(vm.$el.textContent).toBe('AB | CD')\n    expect(CompilerDeprecationTypes.COMPILER_FILTERS).toHaveBeenWarned()\n  })\n\n  it('double pipe', () => {\n    const vm = new Vue({\n      template: `<div>{{ b || msg | upper }}</div>`,\n      data: () => ({\n        b: false,\n        msg: 'a',\n      }),\n      filters: {\n        upper,\n      },\n    }).$mount()\n    expect(vm.$el.textContent).toBe('A')\n    expect(CompilerDeprecationTypes.COMPILER_FILTERS).toHaveBeenWarned()\n  })\n\n  it('object literal', () => {\n    const vm = new Vue({\n      template: `<div>{{ { a: 123 } | pick('a') }}</div>`,\n      filters: {\n        pick: (v: any, key: string) => v[key],\n      },\n    }).$mount()\n    expect(vm.$el.textContent).toBe('123')\n    expect(CompilerDeprecationTypes.COMPILER_FILTERS).toHaveBeenWarned()\n  })\n\n  it('array literal', () => {\n    const vm = new Vue({\n      template: `<div>{{ [1, 2, 3] | reverse }}</div>`,\n      filters: {\n        reverse: (arr: any[]) => arr.reverse().join(','),\n      },\n    }).$mount()\n    expect(vm.$el.textContent).toBe('3,2,1')\n    expect(CompilerDeprecationTypes.COMPILER_FILTERS).toHaveBeenWarned()\n  })\n\n  it('bigint support', () => {\n    const vm = new Vue({\n      template: `<div>{{ BigInt(BigInt(10000000)) + BigInt(2000000000n) * 3000000n }}</div>`,\n    }).$mount()\n    expect(vm.$el.textContent).toBe('6000000010000000')\n  })\n})\n"
  },
  {
    "path": "packages/vue-compat/__tests__/global.spec.ts",
    "content": "import Vue from '@vue/compat'\nimport { effect, isReactive } from '@vue/reactivity'\nimport { h, nextTick } from '@vue/runtime-core'\nimport {\n  DeprecationTypes,\n  deprecationData,\n  toggleDeprecationWarning,\n} from '../../runtime-core/src/compat/compatConfig'\nimport { singletonApp } from '../../runtime-core/src/compat/global'\nimport { createApp } from '../src/esm-index'\n\nbeforeEach(() => {\n  toggleDeprecationWarning(false)\n  Vue.configureCompat({ MODE: 2 })\n})\n\nafterEach(() => {\n  Vue.configureCompat({ MODE: 3 })\n  toggleDeprecationWarning(false)\n})\n\ndescribe('GLOBAL_MOUNT', () => {\n  test('new Vue() with el', () => {\n    toggleDeprecationWarning(true)\n\n    const el = document.createElement('div')\n    el.innerHTML = `{{ msg }}`\n    new Vue({\n      el,\n      compatConfig: { GLOBAL_MOUNT: true },\n      data() {\n        return {\n          msg: 'hello',\n        }\n      },\n    })\n    expect(\n      deprecationData[DeprecationTypes.GLOBAL_MOUNT].message,\n    ).toHaveBeenWarned()\n    expect(el.innerHTML).toBe('hello')\n  })\n\n  test('new Vue() + $mount', () => {\n    const el = document.createElement('div')\n    el.innerHTML = `{{ msg }}`\n    new Vue({\n      data() {\n        return {\n          msg: 'hello',\n        }\n      },\n    }).$mount(el)\n    expect(el.innerHTML).toBe('hello')\n  })\n})\n\ndescribe('GLOBAL_MOUNT_CONTAINER', () => {\n  test('should warn', () => {\n    toggleDeprecationWarning(true)\n\n    const el = document.createElement('div')\n    el.innerHTML = `test`\n    el.setAttribute('v-bind:id', 'foo')\n    new Vue().$mount(el)\n    // warning only\n    expect(\n      deprecationData[DeprecationTypes.GLOBAL_MOUNT].message,\n    ).toHaveBeenWarned()\n    expect(\n      deprecationData[DeprecationTypes.GLOBAL_MOUNT_CONTAINER].message,\n    ).toHaveBeenWarned()\n  })\n})\n\ndescribe('GLOBAL_EXTEND', () => {\n  // https://github.com/vuejs/vue/blob/dev/test/unit/features/global-api/extend.spec.js\n  it('should correctly merge options', () => {\n    toggleDeprecationWarning(true)\n\n    const Test = Vue.extend({\n      name: 'test',\n      a: 1,\n      b: 2,\n    })\n    expect(Test.options.a).toBe(1)\n    expect(Test.options.b).toBe(2)\n    expect(Test.super).toBe(Vue)\n    const t = new Test({\n      a: 2,\n    })\n    expect(t.$options.a).toBe(2)\n    expect(t.$options.b).toBe(2)\n    // inheritance\n    const Test2 = Test.extend({\n      a: 2,\n    })\n    expect(Test2.options.a).toBe(2)\n    expect(Test2.options.b).toBe(2)\n    const t2 = new Test2({\n      a: 3,\n    })\n    expect(t2.$options.a).toBe(3)\n    expect(t2.$options.b).toBe(2)\n\n    expect(\n      deprecationData[DeprecationTypes.GLOBAL_MOUNT].message,\n    ).toHaveBeenWarned()\n    expect(\n      deprecationData[DeprecationTypes.GLOBAL_EXTEND].message,\n    ).toHaveBeenWarned()\n  })\n\n  it('should work when used as components', () => {\n    const foo = Vue.extend({\n      template: '<span>foo</span>',\n    })\n    const bar = Vue.extend({\n      template: '<span>bar</span>',\n    })\n    const vm = new Vue({\n      template: '<div><foo></foo><bar></bar></div>',\n      components: { foo, bar },\n    }).$mount()\n    expect(vm.$el).toBeInstanceOf(HTMLDivElement)\n    expect(vm.$el.innerHTML).toBe('<span>foo</span><span>bar</span>')\n  })\n\n  it('should merge lifecycle hooks', () => {\n    const calls: number[] = []\n    const A = Vue.extend({\n      created() {\n        calls.push(1)\n      },\n    })\n    const B = A.extend({\n      created() {\n        calls.push(2)\n      },\n    })\n    new B({\n      created() {\n        calls.push(3)\n      },\n    })\n    expect(calls).toEqual([1, 2, 3])\n  })\n\n  it('should not merge nested mixins created with Vue.extend', () => {\n    const a = vi.fn()\n    const b = vi.fn()\n    const c = vi.fn()\n    const d = vi.fn()\n    const A = Vue.extend({\n      created: a,\n    })\n    const B = Vue.extend({\n      mixins: [A],\n      created: b,\n    })\n    const C = Vue.extend({\n      extends: B,\n      created: c,\n    })\n    const D = Vue.extend({\n      mixins: [C],\n      created: d,\n      render() {\n        return null\n      },\n    })\n    new D().$mount()\n    expect(a.mock.calls.length).toStrictEqual(1)\n    expect(b.mock.calls.length).toStrictEqual(1)\n    expect(c.mock.calls.length).toStrictEqual(1)\n    expect(d.mock.calls.length).toStrictEqual(1)\n  })\n\n  it('should merge methods', () => {\n    const A = Vue.extend({\n      methods: {\n        a() {\n          return this.n\n        },\n      },\n    })\n    const B = A.extend({\n      methods: {\n        b() {\n          return this.n + 1\n        },\n      },\n    })\n    const b = new B({\n      data: () => ({ n: 0 }),\n      methods: {\n        c() {\n          return this.n + 2\n        },\n      },\n    }) as any\n    expect(b.a()).toBe(0)\n    expect(b.b()).toBe(1)\n    expect(b.c()).toBe(2)\n  })\n\n  it('should merge assets', () => {\n    const A = Vue.extend({\n      components: {\n        aa: {\n          template: '<div>A</div>',\n        },\n      },\n    })\n    const B = A.extend({\n      components: {\n        bb: {\n          template: '<div>B</div>',\n        },\n      },\n    })\n    const b = new B({\n      template: '<div><aa></aa><bb></bb></div>',\n    }).$mount()\n    expect(b.$el).toBeInstanceOf(HTMLDivElement)\n    expect(b.$el.innerHTML).toBe('<div>A</div><div>B</div>')\n  })\n\n  it('caching', () => {\n    const options = {\n      template: '<div></div>',\n    }\n    const A = Vue.extend(options)\n    const B = Vue.extend(options)\n    expect(A).toBe(B)\n  })\n\n  it('extended options should use different identify from parent', () => {\n    const A = Vue.extend({ computed: {} })\n    const B = A.extend()\n    B.options.computed.b = () => 'foo'\n    expect(B.options.computed).not.toBe(A.options.computed)\n    expect(A.options.computed.b).toBeUndefined()\n  })\n})\n\ndescribe('GLOBAL_PROTOTYPE', () => {\n  test('plain properties', () => {\n    toggleDeprecationWarning(true)\n    Vue.prototype.$test = 1\n    const vm = new Vue() as any\n    expect(vm.$test).toBe(1)\n    delete Vue.prototype.$test\n    expect(\n      deprecationData[DeprecationTypes.GLOBAL_MOUNT].message,\n    ).toHaveBeenWarned()\n    expect(\n      deprecationData[DeprecationTypes.GLOBAL_PROTOTYPE].message,\n    ).toHaveBeenWarned()\n  })\n\n  test('method this context', () => {\n    Vue.prototype.$test = function () {\n      return this.msg\n    }\n    const vm = new Vue({\n      data() {\n        return { msg: 'method' }\n      },\n    }) as any\n    expect(vm.$test()).toBe('method')\n    delete Vue.prototype.$test\n  })\n\n  test('defined properties', () => {\n    Object.defineProperty(Vue.prototype, '$test', {\n      configurable: true,\n      get() {\n        return this.msg\n      },\n    })\n    const vm = new Vue({\n      data() {\n        return { msg: 'getter' }\n      },\n    }) as any\n    expect(vm.$test).toBe('getter')\n    delete Vue.prototype.$test\n  })\n\n  test('functions keeps additional properties', () => {\n    function test(this: any) {\n      return this.msg\n    }\n    test.additionalFn = () => {\n      return 'additional fn'\n    }\n\n    Vue.prototype.$test = test\n    const vm = new Vue({\n      data() {\n        return {\n          msg: 'test',\n        }\n      },\n    }) as any\n    expect(typeof vm.$test).toBe('function')\n    expect(typeof vm.$test.additionalFn).toBe('function')\n    expect(vm.$test.additionalFn()).toBe('additional fn')\n    delete Vue.prototype.$test\n  })\n\n  test('extended prototype', async () => {\n    const Foo = Vue.extend()\n    Foo.prototype.$test = 1\n    const vm = new Foo() as any\n    expect(vm.$test).toBe(1)\n    const plain = new Vue() as any\n    expect(plain.$test).toBeUndefined()\n  })\n\n  test('should affect apps created via createApp()', () => {\n    Vue.prototype.$test = 1\n    const vm = createApp({\n      template: 'foo',\n    }).mount(document.createElement('div')) as any\n    expect(vm.$test).toBe(1)\n    delete Vue.prototype.$test\n  })\n})\n\ndescribe('GLOBAL_SET/DELETE', () => {\n  test('set', () => {\n    toggleDeprecationWarning(true)\n    const obj: any = {}\n    Vue.set(obj, 'foo', 1)\n    expect(obj.foo).toBe(1)\n    expect(\n      deprecationData[DeprecationTypes.GLOBAL_SET].message,\n    ).toHaveBeenWarned()\n  })\n\n  test('delete', () => {\n    toggleDeprecationWarning(true)\n    const obj: any = { foo: 1 }\n    Vue.delete(obj, 'foo')\n    expect('foo' in obj).toBe(false)\n    expect(\n      deprecationData[DeprecationTypes.GLOBAL_DELETE].message,\n    ).toHaveBeenWarned()\n  })\n})\n\ndescribe('GLOBAL_OBSERVABLE', () => {\n  test('should work', () => {\n    toggleDeprecationWarning(true)\n    const obj = Vue.observable({})\n    expect(isReactive(obj)).toBe(true)\n    expect(\n      deprecationData[DeprecationTypes.GLOBAL_OBSERVABLE].message,\n    ).toHaveBeenWarned()\n  })\n})\n\ndescribe('GLOBAL_PRIVATE_UTIL', () => {\n  test('defineReactive', () => {\n    toggleDeprecationWarning(true)\n    const obj: any = {}\n    Vue.util.defineReactive(obj, 'test', 1)\n\n    let n\n    effect(() => {\n      n = obj.test\n    })\n    expect(n).toBe(1)\n    obj.test++\n    expect(n).toBe(2)\n\n    expect(\n      deprecationData[DeprecationTypes.GLOBAL_PRIVATE_UTIL].message,\n    ).toHaveBeenWarned()\n  })\n\n  test('defineReactive on instance', async () => {\n    const vm = new Vue({\n      beforeCreate() {\n        Vue.util.defineReactive(this, 'foo', 1)\n      },\n      template: `<div>{{ foo }}</div>`,\n    }).$mount() as any\n    expect(vm.$el).toBeInstanceOf(HTMLDivElement)\n    expect(vm.$el.textContent).toBe('1')\n    vm.foo = 2\n    await nextTick()\n    expect(vm.$el.textContent).toBe('2')\n  })\n\n  test('defineReactive on instance with key that starts with $', async () => {\n    const vm = new Vue({\n      beforeCreate() {\n        Vue.util.defineReactive(this, '$foo', 1)\n      },\n      template: `<div>{{ $foo }}</div>`,\n    }).$mount() as any\n    expect(vm.$el.textContent).toBe('1')\n    vm.$foo = 2\n    await nextTick()\n    expect(vm.$el.textContent).toBe('2')\n  })\n\n  test('defineReactive with object value', () => {\n    const obj: any = {}\n    const val = { a: 1 }\n    Vue.util.defineReactive(obj, 'foo', val)\n\n    let n\n    effect(() => {\n      n = obj.foo.a\n    })\n    expect(n).toBe(1)\n    // mutating original\n    val.a++\n    expect(n).toBe(2)\n  })\n\n  test('defineReactive with array value', () => {\n    const obj: any = {}\n    const val = [1]\n    Vue.util.defineReactive(obj, 'foo', val)\n\n    let n\n    effect(() => {\n      n = obj.foo.length\n    })\n    expect(n).toBe(1)\n    // mutating original\n    val.push(2)\n    expect(n).toBe(2)\n  })\n})\n\ntest('global asset registration should affect apps created via createApp', () => {\n  Vue.component('foo', { template: 'foo' })\n  const vm = createApp({\n    template: '<foo/>',\n  }).mount(document.createElement('div')) as any\n  expect(vm.$el.textContent).toBe('foo')\n  delete singletonApp._context.components.foo\n})\n\ntest('post-facto global asset registration should affect apps created via createApp', () => {\n  const app = createApp({\n    template: '<foo/>',\n  })\n  Vue.component('foo', { template: 'foo' })\n  const vm = app.mount(document.createElement('div'))\n  expect(vm.$el.textContent).toBe('foo')\n  delete singletonApp._context.components.foo\n})\n\ntest('local asset registration should not affect other local apps', () => {\n  const app1 = createApp({})\n  const app2 = createApp({})\n\n  app1.component('foo', {})\n  app2.component('foo', {})\n\n  expect(\n    `Component \"foo\" has already been registered in target app`,\n  ).not.toHaveBeenWarned()\n})\n\ntest('local app-level mixin registration should not affect other local apps', () => {\n  const app1 = createApp({ render: () => h('div') })\n  const app2 = createApp({})\n\n  const mixin = { created: vi.fn() }\n  app1.mixin(mixin)\n  app2.mixin(mixin)\n\n  expect(`Mixin has already been applied`).not.toHaveBeenWarned()\n\n  app1.mount(document.createElement('div'))\n  expect(mixin.created).toHaveBeenCalledTimes(1)\n})\n\n// #5699\ntest('local app config should not affect other local apps in v3 mode', () => {\n  Vue.configureCompat({ MODE: 3 })\n  const app1 = createApp({\n    render: () => h('div'),\n    provide() {\n      return {\n        test: 123,\n      }\n    },\n  })\n  app1.config.globalProperties.test = () => {}\n  app1.mount(document.createElement('div'))\n\n  const app2 = createApp({})\n  expect(app2.config.globalProperties.test).toBe(undefined)\n})\n"
  },
  {
    "path": "packages/vue-compat/__tests__/globalConfig.spec.ts",
    "content": "import Vue from '@vue/compat'\nimport {\n  DeprecationTypes,\n  toggleDeprecationWarning,\n} from '../../runtime-core/src/compat/compatConfig'\nimport { createApp } from '../src/esm-index'\nimport { triggerEvent } from './utils'\n\nbeforeEach(() => {\n  toggleDeprecationWarning(false)\n  Vue.configureCompat({ MODE: 2 })\n})\n\nafterEach(() => {\n  Vue.configureCompat({ MODE: 3 })\n  toggleDeprecationWarning(false)\n})\n\n// only testing config options that affect runtime behavior.\n\ntest('GLOBAL_KEY_CODES', () => {\n  Vue.config.keyCodes = {\n    foo: 86,\n    bar: [38, 87],\n  }\n\n  const onFoo = vi.fn()\n  const onBar = vi.fn()\n\n  const el = document.createElement('div')\n  new Vue({\n    el,\n    template: `<input type=\"text\" @keyup.foo=\"onFoo\" @keyup.bar=\"onBar\">`,\n    methods: {\n      onFoo,\n      onBar,\n    },\n  })\n\n  triggerEvent(el.children[0], 'keyup', e => {\n    e.key = '_'\n    e.keyCode = 86\n  })\n  expect(onFoo).toHaveBeenCalledTimes(1)\n  expect(onBar).toHaveBeenCalledTimes(0)\n\n  triggerEvent(el.children[0], 'keyup', e => {\n    e.key = '_'\n    e.keyCode = 38\n  })\n  expect(onFoo).toHaveBeenCalledTimes(1)\n  expect(onBar).toHaveBeenCalledTimes(1)\n\n  triggerEvent(el.children[0], 'keyup', e => {\n    e.key = '_'\n    e.keyCode = 87\n  })\n  expect(onFoo).toHaveBeenCalledTimes(1)\n  expect(onBar).toHaveBeenCalledTimes(2)\n})\n\ntest('GLOBAL_IGNORED_ELEMENTS', () => {\n  Vue.config.ignoredElements = [/^v-/, 'foo']\n  const el = document.createElement('div')\n  new Vue({\n    el,\n    template: `<v-foo/><foo/>`,\n  })\n  expect(el.innerHTML).toBe(`<v-foo></v-foo><foo></foo>`)\n})\n\ntest('singleton config should affect apps created with createApp()', () => {\n  Vue.config.ignoredElements = [/^v-/, 'foo']\n  const el = document.createElement('div')\n  createApp({\n    template: `<v-foo/><foo/>`,\n  }).mount(el)\n  expect(el.innerHTML).toBe(`<v-foo></v-foo><foo></foo>`)\n})\n\ntest('config.optionMergeStrategies', () => {\n  toggleDeprecationWarning(true)\n  expect(typeof Vue.config.optionMergeStrategies.created).toBe('function')\n  expect(DeprecationTypes.CONFIG_OPTION_MERGE_STRATS).toHaveBeenWarned()\n})\n"
  },
  {
    "path": "packages/vue-compat/__tests__/instance.spec.ts",
    "content": "import type { Mock } from 'vitest'\nimport Vue from '@vue/compat'\nimport type { Slots } from '../../runtime-core/src/componentSlots'\nimport { Text } from '../../runtime-core/src/vnode'\nimport {\n  DeprecationTypes,\n  deprecationData,\n  toggleDeprecationWarning,\n} from '../../runtime-core/src/compat/compatConfig'\nimport type { LegacyPublicInstance } from '../../runtime-core/src/compat/instance'\n\nbeforeEach(() => {\n  toggleDeprecationWarning(true)\n  Vue.configureCompat({\n    MODE: 2,\n    GLOBAL_MOUNT: 'suppress-warning',\n    PRIVATE_APIS: 'suppress-warning',\n  })\n})\n\nafterEach(() => {\n  toggleDeprecationWarning(false)\n  Vue.configureCompat({ MODE: 3 })\n})\n\ntest('INSTANCE_SET', () => {\n  const obj: any = {}\n  new Vue().$set(obj, 'foo', 1)\n  expect(obj.foo).toBe(1)\n  expect(\n    deprecationData[DeprecationTypes.INSTANCE_SET].message,\n  ).toHaveBeenWarned()\n})\n\ntest('INSTANCE_DELETE', () => {\n  const obj: any = { foo: 1 }\n  new Vue().$delete(obj, 'foo')\n  expect('foo' in obj).toBe(false)\n  expect(\n    deprecationData[DeprecationTypes.INSTANCE_DELETE].message,\n  ).toHaveBeenWarned()\n})\n\ntest('INSTANCE_DESTROY', () => {\n  new Vue({ template: 'foo' }).$mount().$destroy()\n  expect(\n    deprecationData[DeprecationTypes.INSTANCE_DESTROY].message,\n  ).toHaveBeenWarned()\n})\n\n// https://github.com/vuejs/vue/blob/dev/test/unit/features/instance/methods-events.spec.js\ndescribe('INSTANCE_EVENT_EMITTER', () => {\n  let vm: LegacyPublicInstance\n  let spy: Mock\n\n  beforeEach(() => {\n    vm = new Vue()\n    spy = vi.fn()\n  })\n\n  it('$on', () => {\n    vm.$on('test', function (this: any) {\n      // expect correct context\n      expect(this).toBe(vm)\n      spy.apply(this, arguments as unknown as any[])\n    })\n    vm.$emit('test', 1, 2, 3, 4)\n    expect(spy).toHaveBeenCalledTimes(1)\n    expect(spy).toHaveBeenCalledWith(1, 2, 3, 4)\n    expect(\n      deprecationData[DeprecationTypes.INSTANCE_EVENT_EMITTER].message,\n    ).toHaveBeenWarned()\n  })\n\n  it('$on multi event', () => {\n    vm.$on(['test1', 'test2'], function (this: any) {\n      expect(this).toBe(vm)\n      spy.apply(this, arguments as unknown as any[])\n    })\n    vm.$emit('test1', 1, 2, 3, 4)\n    expect(spy).toHaveBeenCalledTimes(1)\n    expect(spy).toHaveBeenCalledWith(1, 2, 3, 4)\n    vm.$emit('test2', 5, 6, 7, 8)\n    expect(spy).toHaveBeenCalledTimes(2)\n    expect(spy).toHaveBeenCalledWith(5, 6, 7, 8)\n    expect(\n      deprecationData[DeprecationTypes.INSTANCE_EVENT_EMITTER].message,\n    ).toHaveBeenWarned()\n  })\n\n  it('$off multi event', () => {\n    vm.$on(['test1', 'test2', 'test3'], spy)\n    vm.$off(['test1', 'test2'], spy)\n    vm.$emit('test1')\n    vm.$emit('test2')\n    expect(spy).not.toHaveBeenCalled()\n    vm.$emit('test3', 1, 2, 3, 4)\n    expect(spy).toHaveBeenCalledTimes(1)\n    expect(\n      deprecationData[DeprecationTypes.INSTANCE_EVENT_EMITTER].message,\n    ).toHaveBeenWarned()\n  })\n\n  it('$off multi event without callback', () => {\n    vm.$on(['test1', 'test2'], spy)\n    vm.$off(['test1', 'test2'])\n    vm.$emit('test1')\n    expect(spy).not.toHaveBeenCalled()\n    expect(\n      deprecationData[DeprecationTypes.INSTANCE_EVENT_EMITTER].message,\n    ).toHaveBeenWarned()\n  })\n\n  it('$once', () => {\n    vm.$once('test', spy)\n    vm.$emit('test', 1, 2, 3)\n    vm.$emit('test', 2, 3, 4)\n    expect(spy).toHaveBeenCalledTimes(1)\n    expect(spy).toHaveBeenCalledWith(1, 2, 3)\n    expect(\n      deprecationData[DeprecationTypes.INSTANCE_EVENT_EMITTER].message,\n    ).toHaveBeenWarned()\n  })\n\n  it('$off event added by $once', () => {\n    vm.$once('test', spy)\n    vm.$off('test', spy) // test off event and this event added by once\n    vm.$emit('test', 1, 2, 3)\n    expect(spy).not.toHaveBeenCalled()\n    expect(\n      deprecationData[DeprecationTypes.INSTANCE_EVENT_EMITTER].message,\n    ).toHaveBeenWarned()\n  })\n\n  it('$off', () => {\n    vm.$on('test1', spy)\n    vm.$on('test2', spy)\n    vm.$off()\n    vm.$emit('test1')\n    vm.$emit('test2')\n    expect(spy).not.toHaveBeenCalled()\n    expect(\n      deprecationData[DeprecationTypes.INSTANCE_EVENT_EMITTER].message,\n    ).toHaveBeenWarned()\n  })\n\n  it('$off event', () => {\n    vm.$on('test1', spy)\n    vm.$on('test2', spy)\n    vm.$off('test1')\n    vm.$off('test1') // test off something that's already off\n    vm.$emit('test1', 1)\n    vm.$emit('test2', 2)\n    expect(spy).toHaveBeenCalledTimes(1)\n    expect(spy).toHaveBeenCalledWith(2)\n    expect(\n      deprecationData[DeprecationTypes.INSTANCE_EVENT_EMITTER].message,\n    ).toHaveBeenWarned()\n  })\n\n  it('$off event + fn', () => {\n    const spy2 = vi.fn()\n    vm.$on('test', spy)\n    vm.$on('test', spy2)\n    vm.$off('test', spy)\n    vm.$emit('test', 1, 2, 3)\n    expect(spy).not.toHaveBeenCalled()\n    expect(spy2).toHaveBeenCalledTimes(1)\n    expect(spy2).toHaveBeenCalledWith(1, 2, 3)\n    expect(\n      deprecationData[DeprecationTypes.INSTANCE_EVENT_EMITTER].message,\n    ).toHaveBeenWarned()\n  })\n})\n\ndescribe('INSTANCE_EVENT_HOOKS', () => {\n  test('instance API', () => {\n    const spy = vi.fn()\n    const vm = new Vue({ template: 'foo' })\n    vm.$on('hook:mounted', spy)\n    vm.$mount()\n    expect(spy).toHaveBeenCalled()\n    expect(\n      (\n        deprecationData[DeprecationTypes.INSTANCE_EVENT_HOOKS]\n          .message as Function\n      )('hook:mounted'),\n    ).toHaveBeenWarned()\n  })\n\n  test('via template', () => {\n    const spy = vi.fn()\n    new Vue({\n      template: `<child @hook:mounted=\"spy\"/>`,\n      methods: { spy },\n      components: {\n        child: {\n          template: 'foo',\n        },\n      },\n    }).$mount()\n    expect(spy).toHaveBeenCalled()\n    expect(\n      (\n        deprecationData[DeprecationTypes.INSTANCE_EVENT_HOOKS]\n          .message as Function\n      )('hook:mounted'),\n    ).toHaveBeenWarned()\n  })\n})\n\ntest('INSTANCE_EVENT_CHILDREN', () => {\n  const vm = new Vue({\n    template: `<child/><div><child v-for=\"i in 3\"/></div>`,\n    components: {\n      child: {\n        template: 'foo',\n        data() {\n          return { n: 1 }\n        },\n      },\n    },\n  }).$mount()\n  expect(vm.$children.length).toBe(4)\n  vm.$children.forEach((c: any) => {\n    expect(c.n).toBe(1)\n  })\n  expect(\n    deprecationData[DeprecationTypes.INSTANCE_CHILDREN].message,\n  ).toHaveBeenWarned()\n})\n\ntest('INSTANCE_LISTENERS', () => {\n  const foo = () => 'foo'\n  const bar = () => 'bar'\n  let listeners: Record<string, Function>\n\n  new Vue({\n    template: `<child @click=\"foo\" @custom=\"bar\" />`,\n    methods: { foo, bar },\n    components: {\n      child: {\n        template: `<div/>`,\n        mounted() {\n          listeners = this.$listeners\n        },\n      },\n    },\n  }).$mount()\n\n  expect(Object.keys(listeners!)).toMatchObject(['click', 'custom'])\n  expect(listeners!.click()).toBe('foo')\n  expect(listeners!.custom()).toBe('bar')\n\n  expect(\n    deprecationData[DeprecationTypes.INSTANCE_LISTENERS].message,\n  ).toHaveBeenWarned()\n})\n\ndescribe('INSTANCE_SCOPED_SLOTS', () => {\n  test('explicit usage', () => {\n    let slots: Slots\n    new Vue({\n      template: `<child v-slot=\"{ msg }\">{{ msg }}</child>`,\n      components: {\n        child: {\n          compatConfig: { RENDER_FUNCTION: false },\n          render() {\n            slots = this.$scopedSlots\n          },\n        },\n      },\n    }).$mount()\n\n    expect(slots!.default!({ msg: 'hi' })).toMatchObject([\n      {\n        type: Text,\n        children: 'hi',\n      },\n    ])\n\n    expect(\n      deprecationData[DeprecationTypes.INSTANCE_SCOPED_SLOTS].message,\n    ).toHaveBeenWarned()\n  })\n\n  test('should include legacy slot usage in $scopedSlots', () => {\n    let normalSlots: Slots\n    let scopedSlots: Slots\n    new Vue({\n      template: `<child><div>default</div></child>`,\n      components: {\n        child: {\n          compatConfig: { RENDER_FUNCTION: false },\n          render(this: LegacyPublicInstance) {\n            normalSlots = this.$slots\n            scopedSlots = this.$scopedSlots\n          },\n        },\n      },\n    }).$mount()\n\n    expect('default' in normalSlots!).toBe(true)\n    expect('default' in scopedSlots!).toBe(true)\n\n    expect(\n      deprecationData[DeprecationTypes.INSTANCE_SCOPED_SLOTS].message,\n    ).toHaveBeenWarned()\n  })\n})\n\ntest('INSTANCE_ATTR_CLASS_STYLE', () => {\n  const vm = new Vue({\n    template: `<child class=\"foo\" style=\"color:red\" id=\"ok\" />`,\n    components: {\n      child: {\n        inheritAttrs: false,\n        template: `<div><div v-bind=\"$attrs\" /></div>`,\n      },\n    },\n  }).$mount()\n\n  expect(vm.$el).toBeInstanceOf(HTMLDivElement)\n  expect(vm.$el.outerHTML).toBe(\n    `<div class=\"foo\" style=\"color: red;\"><div id=\"ok\"></div></div>`,\n  )\n\n  expect(\n    (\n      deprecationData[DeprecationTypes.INSTANCE_ATTRS_CLASS_STYLE]\n        .message as Function\n    )('Anonymous'),\n  ).toHaveBeenWarned()\n})\n\ntest('$options mutation', () => {\n  const Comp = {\n    props: ['id'],\n    template: '<div/>',\n    data() {\n      return {\n        foo: '',\n      }\n    },\n    created(this: any) {\n      expect(this.$options.parent).toBeDefined()\n      expect(this.$options.test).toBeUndefined()\n      this.$options.test = this.id\n      expect(this.$options.test).toBe(this.id)\n    },\n  }\n\n  new Vue({\n    template: `<div><Comp id=\"1\"/><Comp id=\"2\"/></div>`,\n    components: { Comp },\n  }).$mount()\n})\n\ntest('other private APIs', () => {\n  new Vue({\n    created() {\n      expect(this.$createElement).toBeTruthy()\n    },\n  })\n\n  new Vue({\n    compatConfig: {\n      PRIVATE_APIS: false,\n    },\n    created() {\n      expect(this.$createElement).toBeUndefined()\n    },\n  })\n})\n"
  },
  {
    "path": "packages/vue-compat/__tests__/misc.spec.ts",
    "content": "import Vue from '@vue/compat'\nimport { nextTick } from '../../runtime-core/src/scheduler'\nimport {\n  DeprecationTypes,\n  deprecationData,\n  toggleDeprecationWarning,\n} from '../../runtime-core/src/compat/compatConfig'\nimport { triggerEvent } from './utils'\nimport { h } from '@vue/runtime-core'\n\nbeforeEach(() => {\n  toggleDeprecationWarning(true)\n  Vue.configureCompat({\n    MODE: 2,\n    GLOBAL_MOUNT: 'suppress-warning',\n  })\n})\n\nafterEach(() => {\n  toggleDeprecationWarning(false)\n  Vue.configureCompat({ MODE: 3 })\n})\n\ntest('mode as function', () => {\n  const Foo = {\n    name: 'Foo',\n    render: (h: any) => h('div', 'foo'),\n  }\n\n  const Bar = {\n    name: 'Bar',\n    data: () => ({ msg: 'bar' }),\n    render: (ctx: any) => h('div', ctx.msg),\n  }\n\n  toggleDeprecationWarning(false)\n  Vue.configureCompat({\n    MODE: comp => (comp && comp.name === 'Bar' ? 3 : 2),\n  })\n\n  const vm = new Vue({\n    components: { Foo, Bar },\n    template: `<div><foo/><bar/></div>`,\n  }).$mount()\n\n  expect(vm.$el).toBeInstanceOf(HTMLDivElement)\n  expect(vm.$el.innerHTML).toBe(`<div>foo</div><div>bar</div>`)\n})\n\ntest('WATCH_ARRAY', async () => {\n  const spy = vi.fn()\n  const vm = new Vue({\n    data() {\n      return {\n        foo: [],\n      }\n    },\n    watch: {\n      foo: spy,\n    },\n  }) as any\n  expect(\n    deprecationData[DeprecationTypes.WATCH_ARRAY].message,\n  ).toHaveBeenWarned()\n\n  expect(spy).not.toHaveBeenCalled()\n  vm.foo.push(1)\n  await nextTick()\n  expect(spy).toHaveBeenCalledTimes(1)\n})\n\ntest('PROPS_DEFAULT_THIS', () => {\n  let thisCtx: any\n  const Child = {\n    customOption: 1,\n    inject: ['provided'],\n    props: {\n      foo: null,\n      bar: {\n        default(this: any) {\n          // copy values since injection must be sync\n          thisCtx = {\n            foo: this.foo,\n            $options: this.$options,\n            provided: this.provided,\n          }\n          return this.foo + 1\n        },\n      },\n    },\n    template: `{{ bar }}`,\n  }\n\n  const vm = new Vue({\n    components: { Child },\n    provide: {\n      provided: 2,\n    },\n    template: `<child :foo=\"0\" />`,\n  }).$mount()\n\n  expect(vm.$el.textContent).toBe('1')\n  // other props\n  expect(thisCtx.foo).toBe(0)\n  // $options\n  expect(thisCtx.$options.customOption).toBe(1)\n  // injections\n  expect(thisCtx.provided).toBe(2)\n\n  expect(\n    (deprecationData[DeprecationTypes.PROPS_DEFAULT_THIS].message as Function)(\n      'bar',\n    ),\n  ).toHaveBeenWarned()\n})\n\ntest('V_ON_KEYCODE_MODIFIER', () => {\n  const spy = vi.fn()\n  const vm = new Vue({\n    template: `<input @keyup.1=\"spy\">`,\n    methods: { spy },\n  }).$mount()\n  expect(vm.$el).toBeInstanceOf(HTMLInputElement)\n  triggerEvent(vm.$el, 'keyup', e => {\n    e.key = '_'\n    e.keyCode = 1\n  })\n  expect(spy).toHaveBeenCalled()\n  expect(\n    deprecationData[DeprecationTypes.V_ON_KEYCODE_MODIFIER].message,\n  ).toHaveBeenWarned()\n})\n\ntest('CUSTOM_DIR', async () => {\n  const myDir = {\n    bind: vi.fn(),\n    inserted: vi.fn(),\n    update: vi.fn(),\n    componentUpdated: vi.fn(),\n    unbind: vi.fn(),\n  } as any\n\n  const getCalls = () =>\n    Object.keys(myDir).map(key => myDir[key].mock.calls.length)\n\n  const vm = new Vue({\n    data() {\n      return {\n        ok: true,\n        foo: 1,\n      }\n    },\n    template: `<div v-if=\"ok\" v-my-dir=\"foo\"/>`,\n    directives: {\n      myDir,\n    },\n  }).$mount() as any\n\n  expect(getCalls()).toMatchObject([1, 1, 0, 0, 0])\n\n  expect(\n    (deprecationData[DeprecationTypes.CUSTOM_DIR].message as Function)(\n      'bind',\n      'beforeMount',\n    ),\n  ).toHaveBeenWarned()\n  expect(\n    (deprecationData[DeprecationTypes.CUSTOM_DIR].message as Function)(\n      'inserted',\n      'mounted',\n    ),\n  ).toHaveBeenWarned()\n\n  vm.foo++\n  await nextTick()\n  expect(getCalls()).toMatchObject([1, 1, 1, 1, 0])\n\n  expect(\n    (deprecationData[DeprecationTypes.CUSTOM_DIR].message as Function)(\n      'update',\n      'updated',\n    ),\n  ).toHaveBeenWarned()\n  expect(\n    (deprecationData[DeprecationTypes.CUSTOM_DIR].message as Function)(\n      'componentUpdated',\n      'updated',\n    ),\n  ).toHaveBeenWarned()\n})\n\ntest('ATTR_FALSE_VALUE', () => {\n  const vm = new Vue({\n    template: `<div :id=\"false\" :foo=\"false\"/>`,\n  }).$mount()\n  expect(vm.$el).toBeInstanceOf(HTMLDivElement)\n  expect(vm.$el.hasAttribute('id')).toBe(false)\n  expect(vm.$el.hasAttribute('foo')).toBe(false)\n  expect(\n    (deprecationData[DeprecationTypes.ATTR_FALSE_VALUE].message as Function)(\n      'id',\n    ),\n  ).toHaveBeenWarned()\n  expect(\n    (deprecationData[DeprecationTypes.ATTR_FALSE_VALUE].message as Function)(\n      'foo',\n    ),\n  ).toHaveBeenWarned()\n})\n\ntest('ATTR_FALSE_VALUE with false on input value', () => {\n  const vm = new Vue({\n    template: `<input :value=\"false\"/>`,\n  }).$mount()\n  expect(vm.$el).toBeInstanceOf(HTMLInputElement)\n  expect(vm.$el.hasAttribute('value')).toBe(true)\n  expect(vm.$el.getAttribute('value')).toBe('false')\n  expect(\n    (deprecationData[DeprecationTypes.ATTR_FALSE_VALUE].message as Function)(\n      'value',\n    ),\n  ).not.toHaveBeenWarned()\n})\n\ntest(\"ATTR_FALSE_VALUE with false value shouldn't throw warning\", () => {\n  const vm = new Vue({\n    template: `<div :id=\"false\" :foo=\"false\"/>`,\n    compatConfig: {\n      ATTR_FALSE_VALUE: false,\n    },\n  }).$mount()\n\n  expect(vm.$el).toBeInstanceOf(HTMLDivElement)\n  expect(vm.$el.hasAttribute('id')).toBe(true)\n  expect(vm.$el.getAttribute('id')).toBe('false')\n  expect(vm.$el.hasAttribute('foo')).toBe(true)\n  expect(vm.$el.getAttribute('foo')).toBe('false')\n  expect(\n    (deprecationData[DeprecationTypes.ATTR_FALSE_VALUE].message as Function)(\n      'id',\n    ),\n  ).not.toHaveBeenWarned()\n  expect(\n    (deprecationData[DeprecationTypes.ATTR_FALSE_VALUE].message as Function)(\n      'foo',\n    ),\n  ).not.toHaveBeenWarned()\n})\n\ntest('ATTR_ENUMERATED_COERCION', () => {\n  const vm = new Vue({\n    template: `<div :draggable=\"null\" :spellcheck=\"0\" contenteditable=\"foo\" />`,\n  }).$mount()\n\n  expect(vm.$el).toBeInstanceOf(HTMLDivElement)\n  expect(vm.$el.getAttribute('draggable')).toBe('false')\n  expect(vm.$el.getAttribute('spellcheck')).toBe('true')\n  expect(vm.$el.getAttribute('contenteditable')).toBe('true')\n  expect(\n    (\n      deprecationData[DeprecationTypes.ATTR_ENUMERATED_COERCION]\n        .message as Function\n    )('draggable', null, 'false'),\n  ).toHaveBeenWarned()\n  expect(\n    (\n      deprecationData[DeprecationTypes.ATTR_ENUMERATED_COERCION]\n        .message as Function\n    )('spellcheck', 0, 'true'),\n  ).toHaveBeenWarned()\n  expect(\n    (\n      deprecationData[DeprecationTypes.ATTR_ENUMERATED_COERCION]\n        .message as Function\n    )('contenteditable', 'foo', 'true'),\n  ).toHaveBeenWarned()\n})\n\ntest('ATTR_ENUMERATED_COERCION, coercing \"false\"', () => {\n  const vm = new Vue({\n    template: `<div><div draggable=\"false\" :spellcheck=\"false\">hello</div></div>`,\n  }).$mount()\n  expect(vm.$el.innerHTML).toBe(\n    `<div draggable=\"false\" spellcheck=\"false\">hello</div>`,\n  )\n  expect(\n    (\n      deprecationData[DeprecationTypes.ATTR_ENUMERATED_COERCION]\n        .message as Function\n    )('draggable', 'false', 'false'),\n  ).toHaveBeenWarned()\n  expect(\n    (\n      deprecationData[DeprecationTypes.ATTR_ENUMERATED_COERCION]\n        .message as Function\n    )('spellcheck', 'false', 'false'),\n  ).toHaveBeenWarned()\n})\n"
  },
  {
    "path": "packages/vue-compat/__tests__/options.spec.ts",
    "content": "import Vue from '@vue/compat'\nimport { nextTick } from '../../runtime-core/src/scheduler'\nimport {\n  DeprecationTypes,\n  deprecationData,\n  toggleDeprecationWarning,\n} from '../../runtime-core/src/compat/compatConfig'\n\nbeforeEach(() => {\n  toggleDeprecationWarning(true)\n  Vue.configureCompat({\n    MODE: 2,\n    GLOBAL_MOUNT: 'suppress-warning',\n    GLOBAL_EXTEND: 'suppress-warning',\n  })\n})\n\nafterEach(() => {\n  toggleDeprecationWarning(false)\n  Vue.configureCompat({ MODE: 3 })\n})\n\ntest('root data plain object', () => {\n  const vm = new Vue({\n    data: { foo: 1 } as any,\n    template: `{{ foo }}`,\n  }).$mount()\n  expect(vm.$el.textContent).toBe('1')\n  expect(\n    deprecationData[DeprecationTypes.OPTIONS_DATA_FN].message,\n  ).toHaveBeenWarned()\n})\n\ntest('data deep merge', () => {\n  const mixin = {\n    data() {\n      return {\n        foo: {\n          baz: 2,\n        },\n      }\n    },\n  }\n\n  const vm = new Vue({\n    mixins: [mixin],\n    data: () => ({\n      foo: {\n        bar: 1,\n      },\n      selfData: 3,\n    }),\n    template: `{{ { selfData, foo } }}`,\n  }).$mount()\n\n  expect(vm.$el.textContent).toBe(\n    JSON.stringify({ selfData: 3, foo: { baz: 2, bar: 1 } }, null, 2),\n  )\n  expect(\n    (deprecationData[DeprecationTypes.OPTIONS_DATA_MERGE].message as Function)(\n      'foo',\n    ),\n  ).toHaveBeenWarned()\n})\n\n// #3852\ntest('data deep merge w/ extended constructor', () => {\n  const App = Vue.extend({\n    template: `<pre>{{ { mixinData, selfData } }}</pre>`,\n    mixins: [{ data: () => ({ mixinData: 'mixinData' }) }],\n    data: () => ({ selfData: 'selfData' }),\n  })\n  const vm = new App().$mount()\n  expect(vm.$el.textContent).toBe(\n    JSON.stringify(\n      {\n        mixinData: 'mixinData',\n        selfData: 'selfData',\n      },\n      null,\n      2,\n    ),\n  )\n})\n\ntest('beforeDestroy/destroyed', async () => {\n  const beforeDestroy = vi.fn()\n  const destroyed = vi.fn()\n\n  const child = {\n    template: `foo`,\n    beforeDestroy,\n    destroyed,\n  }\n\n  const vm = new Vue({\n    template: `<child v-if=\"ok\"/>`,\n    data() {\n      return { ok: true }\n    },\n    components: { child },\n  }).$mount() as any\n\n  vm.ok = false\n  await nextTick()\n  expect(beforeDestroy).toHaveBeenCalled()\n  expect(destroyed).toHaveBeenCalled()\n\n  expect(\n    deprecationData[DeprecationTypes.OPTIONS_BEFORE_DESTROY].message,\n  ).toHaveBeenWarned()\n\n  expect(\n    deprecationData[DeprecationTypes.OPTIONS_DESTROYED].message,\n  ).toHaveBeenWarned()\n})\n\ntest('beforeDestroy/destroyed in Vue.extend components', async () => {\n  const beforeDestroy = vi.fn()\n  const destroyed = vi.fn()\n\n  const child = Vue.extend({\n    template: `foo`,\n    beforeDestroy,\n    destroyed,\n  })\n\n  const vm = new Vue({\n    template: `<child v-if=\"ok\"/>`,\n    data() {\n      return { ok: true }\n    },\n    components: { child },\n  }).$mount() as any\n\n  vm.ok = false\n  await nextTick()\n  expect(beforeDestroy).toHaveBeenCalled()\n  expect(destroyed).toHaveBeenCalled()\n\n  expect(\n    deprecationData[DeprecationTypes.OPTIONS_BEFORE_DESTROY].message,\n  ).toHaveBeenWarned()\n\n  expect(\n    deprecationData[DeprecationTypes.OPTIONS_DESTROYED].message,\n  ).toHaveBeenWarned()\n})\n"
  },
  {
    "path": "packages/vue-compat/__tests__/renderFn.spec.ts",
    "content": "import { ShapeFlags } from '@vue/shared'\nimport Vue from '@vue/compat'\nimport { createComponentInstance } from '../../runtime-core/src/component'\nimport { setCurrentRenderingInstance } from '../../runtime-core/src/componentRenderContext'\nimport type { DirectiveBinding } from '../../runtime-core/src/directives'\nimport { createVNode } from '../../runtime-core/src/vnode'\nimport {\n  DeprecationTypes,\n  deprecationData,\n  toggleDeprecationWarning,\n} from '../../runtime-core/src/compat/compatConfig'\nimport { compatH as h } from '../../runtime-core/src/compat/renderFn'\n\nbeforeEach(() => {\n  toggleDeprecationWarning(false)\n  Vue.configureCompat({\n    MODE: 2,\n    GLOBAL_MOUNT: 'suppress-warning',\n  })\n})\n\nafterEach(() => {\n  toggleDeprecationWarning(false)\n  Vue.configureCompat({ MODE: 3 })\n})\n\ndescribe('compat: render function', () => {\n  const mockDir = {}\n  const mockChildComp = {}\n  const mockComponent = {\n    directives: {\n      mockDir,\n    },\n    components: {\n      foo: mockChildComp,\n    },\n  }\n  const mockInstance = createComponentInstance(\n    createVNode(mockComponent),\n    null,\n    null,\n  )\n  beforeEach(() => {\n    setCurrentRenderingInstance(mockInstance)\n  })\n  afterEach(() => {\n    setCurrentRenderingInstance(null)\n  })\n\n  test('string component lookup', () => {\n    expect(h('foo')).toMatchObject({\n      type: mockChildComp,\n    })\n  })\n\n  test('class / style / attrs / domProps / props', () => {\n    expect(\n      h('div', {\n        class: 'foo',\n        style: { color: 'red' },\n        attrs: {\n          id: 'foo',\n        },\n        domProps: {\n          innerHTML: 'hi',\n        },\n        props: {\n          myProp: 'foo',\n        },\n      }),\n    ).toMatchObject({\n      props: {\n        class: 'foo',\n        style: { color: 'red' },\n        id: 'foo',\n        innerHTML: 'hi',\n        myProp: 'foo',\n      },\n    })\n  })\n\n  test('staticClass + class', () => {\n    expect(\n      h('div', {\n        class: { foo: true },\n        staticClass: 'bar',\n      }),\n    ).toMatchObject({\n      props: {\n        class: 'bar foo',\n      },\n    })\n  })\n\n  test('staticStyle + style', () => {\n    expect(\n      h('div', {\n        style: { color: 'red' },\n        staticStyle: { fontSize: '14px' },\n      }),\n    ).toMatchObject({\n      props: {\n        style: {\n          color: 'red',\n          fontSize: '14px',\n        },\n      },\n    })\n  })\n\n  test('on / nativeOn', () => {\n    const fn = () => {}\n    expect(\n      h('div', {\n        on: {\n          click: fn,\n          fooBar: fn,\n        },\n        nativeOn: {\n          click: fn,\n          'bar-baz': fn,\n        },\n      }),\n    ).toMatchObject({\n      props: {\n        onClick: fn,\n        onClickNative: fn,\n        onFooBar: fn,\n        'onBar-bazNative': fn,\n      },\n    })\n  })\n\n  test('v2 legacy event prefixes', () => {\n    const fn = () => {}\n    expect(\n      h('div', {\n        on: {\n          '&click': fn,\n          '~keyup': fn,\n          '!touchend': fn,\n        },\n      }),\n    ).toMatchObject({\n      props: {\n        onClickPassive: fn,\n        onKeyupOnce: fn,\n        onTouchendCapture: fn,\n      },\n    })\n  })\n\n  test('directives', () => {\n    expect(\n      h('div', {\n        directives: [\n          {\n            name: 'mock-dir',\n            value: '2',\n            // expression: '1 + 1',\n            arg: 'foo',\n            modifiers: {\n              bar: true,\n            },\n          },\n        ],\n      }),\n    ).toMatchObject({\n      dirs: [\n        {\n          dir: mockDir,\n          instance: mockInstance.proxy,\n          value: '2',\n          oldValue: void 0,\n          arg: 'foo',\n          modifiers: {\n            bar: true,\n          },\n        },\n      ] as DirectiveBinding[],\n    })\n  })\n\n  test('scopedSlots', () => {\n    const scopedSlots = {\n      default() {},\n    }\n    const vnode = h(mockComponent, {\n      scopedSlots,\n    })\n    expect(vnode).toMatchObject({\n      children: scopedSlots,\n    })\n    expect('scopedSlots' in vnode.props!).toBe(false)\n    expect(vnode.shapeFlag & ShapeFlags.SLOTS_CHILDREN).toBeTruthy()\n  })\n\n  test('legacy named slot', () => {\n    const vnode = h(mockComponent, [\n      'text',\n      h('div', { slot: 'foo' }, 'one'),\n      h('div', { slot: 'bar' }, 'two'),\n      h('div', { slot: 'foo' }, 'three'),\n      h('div', 'four'),\n    ])\n    expect(vnode.shapeFlag & ShapeFlags.SLOTS_CHILDREN).toBeTruthy()\n    const slots = vnode.children as any\n\n    // default\n    expect(slots.default()).toMatchObject(['text', { children: 'four' }])\n    expect(slots.foo()).toMatchObject([\n      { children: 'one' },\n      { children: 'three' },\n    ])\n    expect(slots.bar()).toMatchObject([{ children: 'two' }])\n  })\n\n  test('in component usage', () => {\n    toggleDeprecationWarning(true)\n\n    const vm = new Vue({\n      render(h: any) {\n        return h(\n          'div',\n          {\n            class: 'foo',\n            attrs: { id: 'bar' },\n          },\n          'hello',\n        )\n      },\n    }).$mount()\n    expect(vm.$el).toBeInstanceOf(HTMLDivElement)\n    expect(vm.$el.outerHTML).toBe(`<div class=\"foo\" id=\"bar\">hello</div>`)\n    expect(\n      deprecationData[DeprecationTypes.RENDER_FUNCTION].message,\n    ).toHaveBeenWarned()\n  })\n\n  test('should detect v3 compiled render fn', () => {\n    const vm = new Vue({\n      data() {\n        return {\n          a: 'hello',\n        }\n      },\n      // check is arg length based\n      render(c: any, _c: any) {\n        return createVNode('div', null, c.a)\n      },\n    }).$mount()\n    expect(vm.$el).toBeInstanceOf(HTMLDivElement)\n    expect(vm.$el.outerHTML).toBe(`<div>hello</div>`)\n  })\n})\n"
  },
  {
    "path": "packages/vue-compat/__tests__/utils.ts",
    "content": "export function triggerEvent(\n  target: Element,\n  event: string,\n  process?: (e: any) => any,\n): Event {\n  const e = new Event(event, {\n    bubbles: true,\n    cancelable: true,\n  })\n  if (process) process(e)\n  target.dispatchEvent(e)\n  return e\n}\n"
  },
  {
    "path": "packages/vue-compat/index.js",
    "content": "'use strict'\n\nif (process.env.NODE_ENV === 'production') {\n  module.exports = require('./dist/vue.cjs.prod.js')\n} else {\n  module.exports = require('./dist/vue.cjs.js')\n}\n"
  },
  {
    "path": "packages/vue-compat/package.json",
    "content": "{\n  \"name\": \"@vue/compat\",\n  \"version\": \"3.5.30\",\n  \"description\": \"Vue 3 compatibility build for Vue 2\",\n  \"main\": \"index.js\",\n  \"module\": \"dist/vue.runtime.esm-bundler.js\",\n  \"unpkg\": \"dist/vue.global.js\",\n  \"jsdelivr\": \"dist/vue.global.js\",\n  \"files\": [\n    \"index.js\",\n    \"dist\"\n  ],\n  \"exports\": {\n    \".\": {\n      \"types\": \"./dist/vue.d.ts\",\n      \"node\": {\n        \"production\": \"./dist/vue.cjs.prod.js\",\n        \"development\": \"./dist/vue.cjs.js\",\n        \"default\": \"./index.js\"\n      },\n      \"module\": \"./dist/vue.esm-bundler.js\",\n      \"import\": \"./dist/vue.esm-bundler.js\",\n      \"require\": \"./index.js\"\n    },\n    \"./*\": \"./*\"\n  },\n  \"buildOptions\": {\n    \"name\": \"Vue\",\n    \"filename\": \"vue\",\n    \"compat\": true,\n    \"formats\": [\n      \"esm-bundler\",\n      \"esm-bundler-runtime\",\n      \"cjs\",\n      \"global\",\n      \"global-runtime\",\n      \"esm-browser\",\n      \"esm-browser-runtime\"\n    ]\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/vuejs/core.git\"\n  },\n  \"keywords\": [\n    \"vue\"\n  ],\n  \"author\": \"Evan You\",\n  \"license\": \"MIT\",\n  \"bugs\": {\n    \"url\": \"https://github.com/vuejs/core/issues\"\n  },\n  \"homepage\": \"https://github.com/vuejs/core/tree/main/packages/vue-compat#readme\",\n  \"dependencies\": {\n    \"@babel/parser\": \"catalog:\",\n    \"entities\": \"catalog:\",\n    \"estree-walker\": \"catalog:\",\n    \"source-map-js\": \"catalog:\"\n  },\n  \"peerDependencies\": {\n    \"vue\": \"workspace:*\"\n  }\n}\n"
  },
  {
    "path": "packages/vue-compat/src/createCompatVue.ts",
    "content": "// This entry exports the runtime only, and is built as\n// `dist/vue.esm-bundler.js` which is used by default for bundlers.\nimport { initDev } from './dev'\nimport {\n  type CompatVue,\n  DeprecationTypes,\n  KeepAlive,\n  Transition,\n  TransitionGroup,\n  compatUtils,\n  createApp,\n  vModelDynamic,\n  vShow,\n} from '@vue/runtime-dom'\nimport { extend } from '@vue/shared'\n\nif (__DEV__) {\n  initDev()\n}\n\nimport * as runtimeDom from '@vue/runtime-dom'\n\nfunction wrappedCreateApp(...args: any[]) {\n  // @ts-expect-error\n  const app = createApp(...args)\n  if (compatUtils.isCompatEnabled(DeprecationTypes.RENDER_FUNCTION, null)) {\n    // register built-in components so that they can be resolved via strings\n    // in the legacy h() call. The __compat__ prefix is to ensure that v3 h()\n    // doesn't get affected.\n    app.component('__compat__transition', Transition)\n    app.component('__compat__transition-group', TransitionGroup)\n    app.component('__compat__keep-alive', KeepAlive)\n    // built-in directives. No need for prefix since there's no render fn API\n    // for resolving directives via string in v3.\n    app._context.directives.show = vShow\n    app._context.directives.model = vModelDynamic\n  }\n  return app\n}\n\nexport function createCompatVue(): CompatVue {\n  const Vue = compatUtils.createCompatVue(createApp, wrappedCreateApp)\n  extend(Vue, runtimeDom)\n  return Vue\n}\n"
  },
  {
    "path": "packages/vue-compat/src/dev.ts",
    "content": "import { initCustomFormatter } from '@vue/runtime-dom'\n\nexport function initDev(): void {\n  if (__BROWSER__) {\n    if (!__ESM_BUNDLER__) {\n      console.info(\n        `You are running a development build of Vue.\\n` +\n          `Make sure to use the production build (*.prod.js) when deploying for production.`,\n      )\n    }\n\n    initCustomFormatter()\n  }\n}\n"
  },
  {
    "path": "packages/vue-compat/src/esm-index.ts",
    "content": "import Vue from './index'\n\nexport default Vue\nexport * from '@vue/runtime-dom'\n\nconst configureCompat: typeof Vue.configureCompat = Vue.configureCompat\nexport { configureCompat }\n"
  },
  {
    "path": "packages/vue-compat/src/esm-runtime.ts",
    "content": "import Vue from './runtime'\n\nexport default Vue\nexport * from '@vue/runtime-dom'\n\nconst configureCompat: typeof Vue.configureCompat = Vue.configureCompat\nexport { configureCompat }\n"
  },
  {
    "path": "packages/vue-compat/src/index.ts",
    "content": "// This entry is the \"full-build\" that includes both the runtime\n// and the compiler, and supports on-the-fly compilation of the template option.\nimport { createCompatVue } from './createCompatVue'\nimport {\n  type CompilerError,\n  type CompilerOptions,\n  compile,\n} from '@vue/compiler-dom'\nimport {\n  type CompatVue,\n  type RenderFunction,\n  registerRuntimeCompiler,\n  warn,\n} from '@vue/runtime-dom'\nimport {\n  NOOP,\n  extend,\n  genCacheKey,\n  generateCodeFrame,\n  isString,\n} from '@vue/shared'\nimport type { InternalRenderFunction } from 'packages/runtime-core/src/component'\nimport * as runtimeDom from '@vue/runtime-dom'\nimport {\n  DeprecationTypes,\n  warnDeprecation,\n} from '../../runtime-core/src/compat/compatConfig'\n\nconst compileCache: Record<string, RenderFunction> = Object.create(null)\n\nfunction compileToFunction(\n  template: string | HTMLElement,\n  options?: CompilerOptions,\n): RenderFunction {\n  if (!isString(template)) {\n    if (template.nodeType) {\n      template = template.innerHTML\n    } else {\n      __DEV__ && warn(`invalid template option: `, template)\n      return NOOP\n    }\n  }\n\n  const key = genCacheKey(template, options)\n  const cached = compileCache[key]\n  if (cached) {\n    return cached\n  }\n\n  if (template[0] === '#') {\n    const el = document.querySelector(template)\n    if (__DEV__ && !el) {\n      warn(`Template element not found or is empty: ${template}`)\n    }\n    // __UNSAFE__\n    // Reason: potential execution of JS expressions in in-DOM template.\n    // The user must make sure the in-DOM template is trusted. If it's rendered\n    // by the server, the template should not contain any user data.\n    template = el ? el.innerHTML : ``\n  }\n\n  if (__DEV__ && !__TEST__ && (!options || !options.whitespace)) {\n    warnDeprecation(DeprecationTypes.CONFIG_WHITESPACE, null)\n  }\n\n  const { code } = compile(\n    template,\n    extend(\n      {\n        hoistStatic: true,\n        whitespace: 'preserve',\n        onError: __DEV__ ? onError : undefined,\n        onWarn: __DEV__ ? e => onError(e, true) : NOOP,\n      } as CompilerOptions,\n      options,\n    ),\n  )\n\n  function onError(err: CompilerError, asWarning = false) {\n    const message = asWarning\n      ? err.message\n      : `Template compilation error: ${err.message}`\n    const codeFrame =\n      err.loc &&\n      generateCodeFrame(\n        template as string,\n        err.loc.start.offset,\n        err.loc.end.offset,\n      )\n    warn(codeFrame ? `${message}\\n${codeFrame}` : message)\n  }\n\n  // The wildcard import results in a huge object with every export\n  // with keys that cannot be mangled, and can be quite heavy size-wise.\n  // In the global build we know `Vue` is available globally so we can avoid\n  // the wildcard object.\n  const render = (\n    __GLOBAL__ ? new Function(code)() : new Function('Vue', code)(runtimeDom)\n  ) as RenderFunction\n\n  // mark the function as runtime compiled\n  ;(render as InternalRenderFunction)._rc = true\n\n  return (compileCache[key] = render)\n}\n\nregisterRuntimeCompiler(compileToFunction)\n\nconst Vue: CompatVue = createCompatVue()\nVue.compile = compileToFunction\n\nexport default Vue\n"
  },
  {
    "path": "packages/vue-compat/src/runtime.ts",
    "content": "// This entry exports the runtime only, and is built as\n// `dist/vue.esm-bundler.js` which is used by default for bundlers.\nimport { createCompatVue } from './createCompatVue'\nimport { type CompatVue, warn } from '@vue/runtime-core'\n\nconst Vue: CompatVue = createCompatVue()\n\nVue.compile = (() => {\n  if (__DEV__) {\n    warn(\n      `Runtime compilation is not supported in this build of Vue.` +\n        (__ESM_BUNDLER__\n          ? ` Configure your bundler to alias \"vue\" to \"@vue/compat/dist/vue.esm-bundler.js\".`\n          : __ESM_BROWSER__\n            ? ` Use \"vue.esm-browser.js\" instead.`\n            : __GLOBAL__\n              ? ` Use \"vue.global.js\" instead.`\n              : ``) /* should not happen */,\n    )\n  }\n}) as any\n\nexport default Vue\n"
  },
  {
    "path": "packages-private/dts-built-test/README.md",
    "content": "# dts built-package test\n\nThis package is private and for testing only. It is used to verify edge cases for external libraries that build their types using Vue core types - e.g. Vuetify as in [#8376](https://github.com/vuejs/core/issues/8376).\n\nWhen running the `build-dts` task, this package's types are built alongside other packages. Then, during `test-dts-only` it is imported and used in [`packages-private/dts-test/built.test-d.ts`](https://github.com/vuejs/core/blob/main/packages-private/dts-test/built.test-d.ts) to verify that the built types work correctly.\n"
  },
  {
    "path": "packages-private/dts-built-test/package.json",
    "content": "{\n  \"name\": \"dts-built-test\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"types\": \"dist/index.d.ts\",\n  \"dependencies\": {\n    \"@vue/shared\": \"workspace:*\",\n    \"@vue/reactivity\": \"workspace:*\",\n    \"vue\": \"workspace:*\"\n  }\n}\n"
  },
  {
    "path": "packages-private/dts-built-test/src/index.ts",
    "content": "import { defineComponent } from 'vue'\n\nconst _CustomPropsNotErased = defineComponent({\n  props: {},\n  setup() {},\n})\n\n// #8376\nexport const CustomPropsNotErased =\n  _CustomPropsNotErased as typeof _CustomPropsNotErased & {\n    foo: string\n  }\n"
  },
  {
    "path": "packages-private/dts-built-test/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"baseUrl\": \".\",\n    \"outDir\": \"dist\",\n    \"jsx\": \"preserve\",\n    \"module\": \"esnext\",\n    \"strict\": true,\n    \"moduleResolution\": \"Bundler\",\n    \"lib\": [\"esnext\", \"dom\"],\n    \"declaration\": true,\n    \"emitDeclarationOnly\": true\n  },\n  \"include\": [\"./src\"]\n}\n"
  },
  {
    "path": "packages-private/dts-test/README.md",
    "content": "# dts-test\n\nTests TypeScript types to ensure the types remain as expected.\n\n- This directory is included in the root `tsconfig.json`, where package imports are aliased to `src` directories, so in IDEs and the `pnpm check` script the types are validated against source code.\n\n- When running `tsc` with `packages-private/dts-test/tsconfig.test.json`, packages are resolved using normal `node` resolution, so the types are validated against actual **built** types. This requires the types to be built first via `pnpm build-dts`.\n"
  },
  {
    "path": "packages-private/dts-test/appDirective.test-d.ts",
    "content": "import { createApp } from 'vue'\nimport { expectType } from './utils'\n\nconst app = createApp({})\n\napp.directive<HTMLElement, string, 'prevent' | 'stop', 'arg1' | 'arg2'>(\n  'custom',\n  {\n    mounted(el, binding) {\n      expectType<HTMLElement>(el)\n      expectType<string>(binding.value)\n      expectType<{ prevent?: boolean; stop?: boolean }>(binding.modifiers)\n      expectType<'arg1' | 'arg2'>(binding.arg!)\n\n      // @ts-expect-error not any\n      expectType<number>(binding.value)\n    },\n  },\n)\n"
  },
  {
    "path": "packages-private/dts-test/appUse.test-d.ts",
    "content": "import { type App, type Plugin, createApp, defineComponent } from 'vue'\n\nconst app = createApp({})\n\n// Plugin without types accept anything\nconst PluginWithoutType: Plugin = {\n  install(app: App) {},\n}\n\napp.use(PluginWithoutType)\napp.use(PluginWithoutType, 2)\napp.use(PluginWithoutType, { anything: 'goes' }, true)\n\ntype PluginOptions = {\n  /** option1 */\n  option1?: string\n  /** option2 */\n  option2: number\n  /** option3 */\n  option3: boolean\n}\n\nconst PluginWithObjectOptions = {\n  install(app: App, options: PluginOptions) {\n    options.option1\n    options.option2\n    options.option3\n  },\n}\n\nconst objectPluginOptional = {\n  install(app: App, options?: PluginOptions) {},\n}\napp.use(objectPluginOptional)\napp.use(\n  objectPluginOptional,\n  // Test JSDoc and `go to definition` for options\n  {\n    option1: 'foo',\n    option2: 1,\n    option3: true,\n  },\n)\n\nfor (const Plugin of [\n  PluginWithObjectOptions,\n  PluginWithObjectOptions.install,\n]) {\n  // @ts-expect-error: no params\n  app.use(Plugin)\n\n  // @ts-expect-error option2 and option3 (required) missing\n  app.use(Plugin, {})\n  // @ts-expect-error type mismatch\n  app.use(Plugin, undefined)\n  // valid options\n  app.use(Plugin, { option2: 1, option3: true })\n  app.use(Plugin, { option1: 'foo', option2: 1, option3: true })\n}\n\nconst PluginNoOptions = {\n  install(app: App) {},\n}\n\nfor (const Plugin of [PluginNoOptions, PluginNoOptions.install]) {\n  // no args\n  app.use(Plugin)\n  // @ts-expect-error unexpected plugin option\n  app.use(Plugin, {})\n  // @ts-expect-error only no options is valid\n  app.use(Plugin, undefined)\n}\n\nconst PluginMultipleArgs = {\n  install: (app: App, a: string, b: number) => {},\n}\n\nfor (const Plugin of [PluginMultipleArgs, PluginMultipleArgs.install]) {\n  // @ts-expect-error: 2 arguments expected\n  app.use(Plugin, 'hey')\n  app.use(Plugin, 'hey', 2)\n}\n\nconst PluginOptionalOptions = {\n  install(\n    app: App,\n    options: PluginOptions = { option2: 2, option3: true, option1: 'foo' },\n  ) {\n    options.option1\n    options.option2\n    options.option3\n  },\n}\n\nfor (const Plugin of [PluginOptionalOptions, PluginOptionalOptions.install]) {\n  // both version are valid\n  app.use(Plugin)\n  app.use(Plugin, undefined)\n\n  // @ts-expect-error option2 and option3 (required) missing\n  app.use(Plugin, {})\n  // valid options\n  app.use(Plugin, { option2: 1, option3: true })\n  app.use(Plugin, { option1: 'foo', option2: 1, option3: true })\n}\n\n// still valid but it's better to use the regular function because this one can accept an optional param\nconst PluginTyped: Plugin<PluginOptions> = (app, options) => {}\n\n// @ts-expect-error: needs options\napp.use(PluginTyped)\napp.use(\n  PluginTyped,\n  // Test autocomplete for options\n  {\n    option1: '',\n    option2: 2,\n    option3: true,\n  },\n)\n\nconst functionPluginOptional = (app: App, options?: PluginOptions) => {}\napp.use(functionPluginOptional)\napp.use(functionPluginOptional, { option2: 2, option3: true })\n\n// type optional params\nconst functionPluginOptional2: Plugin<[options?: PluginOptions]> = (\n  app,\n  options,\n) => {}\napp.use(functionPluginOptional2)\napp.use(functionPluginOptional2, { option2: 2, option3: true })\n\n// vuetify usage\nconst key: string = ''\nconst aliases: Record<string, any> = {}\napp.component(\n  key,\n  defineComponent({\n    ...aliases[key],\n    name: key,\n    aliasName: aliases[key].name,\n  }),\n)\n"
  },
  {
    "path": "packages-private/dts-test/built.test-d.ts",
    "content": "import { CustomPropsNotErased } from 'dts-built-test/src/index'\nimport { describe, expectType } from './utils'\n\ndeclare module 'vue' {\n  interface ComponentCustomProps {\n    custom?: number\n  }\n}\n\n// #8376 - custom props should not be erased\ndescribe('Custom Props not erased', () => {\n  expectType<number | undefined>(new CustomPropsNotErased().$props.custom)\n})\n"
  },
  {
    "path": "packages-private/dts-test/compiler.test-d.ts",
    "content": "import {\n  Comment,\n  Fragment,\n  Static,\n  Suspense,\n  Teleport,\n  Text,\n  type VNode,\n  createBlock,\n  defineComponent,\n} from 'vue'\nimport { expectType } from './utils'\n\nexpectType<VNode>(createBlock(Teleport))\nexpectType<VNode>(createBlock(Text))\nexpectType<VNode>(createBlock(Static))\nexpectType<VNode>(createBlock(Comment))\nexpectType<VNode>(createBlock(Fragment))\nexpectType<VNode>(createBlock(Suspense))\nexpectType<VNode>(createBlock(defineComponent({})))\n"
  },
  {
    "path": "packages-private/dts-test/component.test-d.ts",
    "content": "import {\n  type Component,\n  type ComponentPublicInstance,\n  type EmitsOptions,\n  type FunctionalComponent,\n  type PropType,\n  type Ref,\n  type SetupContext,\n  type ShallowUnwrapRef,\n  defineComponent,\n  ref,\n  toRefs,\n} from 'vue'\nimport { type IsAny, describe, expectAssignable, expectType } from './utils'\n\ndeclare function extractComponentOptions<\n  Props,\n  RawBindings,\n  Emits extends EmitsOptions | Record<string, any[]>,\n  Slots extends Record<string, any>,\n>(\n  obj: Component<Props, RawBindings, any, any, any, Emits, Slots>,\n): {\n  props: Props\n  emits: Emits\n  slots: Slots\n  rawBindings: RawBindings\n  setup: ShallowUnwrapRef<RawBindings>\n}\n\ndescribe('object props', () => {\n  interface ExpectedProps {\n    a?: number | undefined\n    b: string\n    e?: Function\n    bb: string\n    bbb: string\n    cc?: string[] | undefined\n    dd: { n: 1 }\n    ee?: () => string\n    ff?: (a: number, b: string) => { a: boolean }\n    ccc?: string[] | undefined\n    ddd: string[]\n    eee: () => { a: string }\n    fff: (a: number, b: string) => { a: boolean }\n    hhh: boolean\n    ggg: 'foo' | 'bar'\n    ffff: (a: number, b: string) => { a: boolean }\n    validated?: string\n    object?: object\n  }\n\n  interface ExpectedRefs {\n    a: Ref<number | undefined>\n    b: Ref<string>\n    e: Ref<Function | undefined>\n    bb: Ref<string>\n    bbb: Ref<string>\n    cc: Ref<string[] | undefined>\n    dd: Ref<{ n: 1 }>\n    ee: Ref<(() => string) | undefined>\n    ff: Ref<((a: number, b: string) => { a: boolean }) | undefined>\n    ccc: Ref<string[] | undefined>\n    ddd: Ref<string[]>\n    eee: Ref<() => { a: string }>\n    fff: Ref<(a: number, b: string) => { a: boolean }>\n    hhh: Ref<boolean>\n    ggg: Ref<'foo' | 'bar'>\n    ffff: Ref<(a: number, b: string) => { a: boolean }>\n    validated: Ref<string | undefined>\n    object: Ref<object | undefined>\n    zzz: any\n  }\n\n  describe('defineComponent', () => {\n    const MyComponent = defineComponent({\n      props: {\n        a: Number,\n        // required should make property non-void\n        b: {\n          type: String,\n          required: true,\n        },\n        e: Function,\n        // default value should infer type and make it non-void\n        bb: {\n          default: 'hello',\n        },\n        bbb: {\n          // Note: default function value requires arrow syntax + explicit\n          // annotation\n          default: (props: any) => (props.bb as string) || 'foo',\n        },\n        // explicit type casting\n        cc: Array as PropType<string[]>,\n        // required + type casting\n        dd: {\n          type: Object as PropType<{ n: 1 }>,\n          required: true,\n        },\n        // return type\n        ee: Function as PropType<() => string>,\n        // arguments + object return\n        ff: Function as PropType<(a: number, b: string) => { a: boolean }>,\n        // explicit type casting with constructor\n        ccc: Array as () => string[],\n        // required + constructor type casting\n        ddd: {\n          type: Array as () => string[],\n          required: true,\n        },\n        // required + object return\n        eee: {\n          type: Function as PropType<() => { a: string }>,\n          required: true,\n        },\n        // required + arguments + object return\n        fff: {\n          type: Function as PropType<(a: number, b: string) => { a: boolean }>,\n          required: true,\n        },\n        hhh: {\n          type: Boolean,\n          required: true,\n        },\n        // default + type casting\n        ggg: {\n          type: String as PropType<'foo' | 'bar'>,\n          default: 'foo',\n        },\n        // default + function\n        ffff: {\n          type: Function as PropType<(a: number, b: string) => { a: boolean }>,\n          default: (_a: number, _b: string) => ({ a: true }),\n        },\n        validated: {\n          type: String,\n          // validator requires explicit annotation\n          validator: (val: unknown) => val !== '',\n        },\n        object: Object as PropType<object>,\n        zzz: Object as PropType<any>,\n      },\n      setup(props) {\n        const refs = toRefs(props)\n        expectType<ExpectedRefs['a']>(refs.a)\n        expectType<ExpectedRefs['b']>(refs.b)\n        expectType<ExpectedRefs['e']>(refs.e)\n        expectType<ExpectedRefs['bb']>(refs.bb)\n        expectType<ExpectedRefs['bbb']>(refs.bbb)\n        expectType<ExpectedRefs['cc']>(refs.cc)\n        expectType<ExpectedRefs['dd']>(refs.dd)\n        expectType<ExpectedRefs['ee']>(refs.ee)\n        expectType<ExpectedRefs['ff']>(refs.ff)\n        expectType<ExpectedRefs['ccc']>(refs.ccc)\n        expectType<ExpectedRefs['ddd']>(refs.ddd)\n        expectType<ExpectedRefs['eee']>(refs.eee)\n        expectType<ExpectedRefs['fff']>(refs.fff)\n        expectType<ExpectedRefs['hhh']>(refs.hhh)\n        expectType<ExpectedRefs['ggg']>(refs.ggg)\n        expectType<ExpectedRefs['ffff']>(refs.ffff)\n        expectType<ExpectedRefs['validated']>(refs.validated)\n        expectType<ExpectedRefs['object']>(refs.object)\n        expectType<IsAny<typeof props.zzz>>(true)\n\n        return {\n          setupA: 1,\n          setupB: ref(1),\n          setupC: {\n            a: ref(2),\n          },\n          setupD: undefined as Ref<number> | undefined,\n          setupProps: props,\n        }\n      },\n    })\n\n    const { props, rawBindings, setup } = extractComponentOptions(MyComponent)\n\n    // props\n    expectType<ExpectedProps['a']>(props.a)\n    expectType<ExpectedProps['b']>(props.b)\n    expectType<ExpectedProps['e']>(props.e)\n    expectType<ExpectedProps['bb']>(props.bb)\n    expectType<ExpectedProps['bbb']>(props.bbb)\n    expectType<ExpectedProps['cc']>(props.cc)\n    expectType<ExpectedProps['dd']>(props.dd)\n    expectType<ExpectedProps['ee']>(props.ee)\n    expectType<ExpectedProps['ff']>(props.ff)\n    expectType<ExpectedProps['ccc']>(props.ccc)\n    expectType<ExpectedProps['ddd']>(props.ddd)\n    expectType<ExpectedProps['eee']>(props.eee)\n    expectType<ExpectedProps['fff']>(props.fff)\n    expectType<ExpectedProps['hhh']>(props.hhh)\n    expectType<ExpectedProps['ggg']>(props.ggg)\n    expectType<ExpectedProps['ffff']>(props.ffff)\n    expectType<ExpectedProps['validated']>(props.validated)\n    expectType<ExpectedProps['object']>(props.object)\n\n    // raw bindings\n    expectType<Number>(rawBindings.setupA)\n    expectType<Ref<Number>>(rawBindings.setupB)\n    expectType<Ref<Number>>(rawBindings.setupC.a)\n    expectType<Ref<Number> | undefined>(rawBindings.setupD)\n\n    // raw bindings props\n    expectType<ExpectedProps['a']>(rawBindings.setupProps.a)\n    expectType<ExpectedProps['b']>(rawBindings.setupProps.b)\n    expectType<ExpectedProps['e']>(rawBindings.setupProps.e)\n    expectType<ExpectedProps['bb']>(rawBindings.setupProps.bb)\n    expectType<ExpectedProps['bbb']>(rawBindings.setupProps.bbb)\n    expectType<ExpectedProps['cc']>(rawBindings.setupProps.cc)\n    expectType<ExpectedProps['dd']>(rawBindings.setupProps.dd)\n    expectType<ExpectedProps['ee']>(rawBindings.setupProps.ee)\n    expectType<ExpectedProps['ff']>(rawBindings.setupProps.ff)\n    expectType<ExpectedProps['ccc']>(rawBindings.setupProps.ccc)\n    expectType<ExpectedProps['ddd']>(rawBindings.setupProps.ddd)\n    expectType<ExpectedProps['eee']>(rawBindings.setupProps.eee)\n    expectType<ExpectedProps['fff']>(rawBindings.setupProps.fff)\n    expectType<ExpectedProps['hhh']>(rawBindings.setupProps.hhh)\n    expectType<ExpectedProps['ggg']>(rawBindings.setupProps.ggg)\n    expectType<ExpectedProps['ffff']>(rawBindings.setupProps.ffff)\n    expectType<ExpectedProps['validated']>(rawBindings.setupProps.validated)\n\n    // setup\n    expectType<Number>(setup.setupA)\n    expectType<Number>(setup.setupB)\n    expectType<Ref<Number>>(setup.setupC.a)\n    expectType<number | undefined>(setup.setupD)\n\n    // raw bindings props\n    expectType<ExpectedProps['a']>(setup.setupProps.a)\n    expectType<ExpectedProps['b']>(setup.setupProps.b)\n    expectType<ExpectedProps['e']>(setup.setupProps.e)\n    expectType<ExpectedProps['bb']>(setup.setupProps.bb)\n    expectType<ExpectedProps['bbb']>(setup.setupProps.bbb)\n    expectType<ExpectedProps['cc']>(setup.setupProps.cc)\n    expectType<ExpectedProps['dd']>(setup.setupProps.dd)\n    expectType<ExpectedProps['ee']>(setup.setupProps.ee)\n    expectType<ExpectedProps['ff']>(setup.setupProps.ff)\n    expectType<ExpectedProps['ccc']>(setup.setupProps.ccc)\n    expectType<ExpectedProps['ddd']>(setup.setupProps.ddd)\n    expectType<ExpectedProps['eee']>(setup.setupProps.eee)\n    expectType<ExpectedProps['fff']>(setup.setupProps.fff)\n    expectType<ExpectedProps['hhh']>(setup.setupProps.hhh)\n    expectType<ExpectedProps['ggg']>(setup.setupProps.ggg)\n    expectType<ExpectedProps['ffff']>(setup.setupProps.ffff)\n    expectType<ExpectedProps['validated']>(setup.setupProps.validated)\n\n    // instance\n    const instance = new MyComponent()\n    expectType<number>(instance.setupA)\n    expectType<number | undefined>(instance.setupD)\n    // @ts-expect-error\n    instance.notExist\n  })\n\n  describe('options', () => {\n    const MyComponent = {\n      props: {\n        a: Number,\n        // required should make property non-void\n        b: {\n          type: String,\n          required: true,\n        },\n        e: Function,\n        // default value should infer type and make it non-void\n        bb: {\n          default: 'hello',\n        },\n        bbb: {\n          // Note: default function value requires arrow syntax + explicit\n          // annotation\n          default: (props: any) => (props.bb as string) || 'foo',\n        },\n        // explicit type casting\n        cc: Array as PropType<string[]>,\n        // required + type casting\n        dd: {\n          type: Object as PropType<{ n: 1 }>,\n          required: true,\n        },\n        // return type\n        ee: Function as PropType<() => string>,\n        // arguments + object return\n        ff: Function as PropType<(a: number, b: string) => { a: boolean }>,\n        // explicit type casting with constructor\n        ccc: Array as () => string[],\n        // required + constructor type casting\n        ddd: {\n          type: Array as () => string[],\n          required: true,\n        },\n        // required + object return\n        eee: {\n          type: Function as PropType<() => { a: string }>,\n          required: true,\n        },\n        // required + arguments + object return\n        fff: {\n          type: Function as PropType<(a: number, b: string) => { a: boolean }>,\n          required: true,\n        },\n        hhh: {\n          type: Boolean,\n          required: true,\n        },\n        // default + type casting\n        ggg: {\n          type: String as PropType<'foo' | 'bar'>,\n          default: 'foo',\n        },\n        // default + function\n        ffff: {\n          type: Function as PropType<(a: number, b: string) => { a: boolean }>,\n          default: (_a: number, _b: string) => ({ a: true }),\n        },\n        validated: {\n          type: String,\n          // validator requires explicit annotation\n          validator: (val: unknown) => val !== '',\n        },\n        object: Object as PropType<object>,\n      },\n\n      setup() {\n        return {\n          setupA: 1,\n        }\n      },\n    } as const\n\n    const { props, rawBindings, setup } = extractComponentOptions(MyComponent)\n\n    // props\n    expectType<ExpectedProps['a']>(props.a)\n    expectType<ExpectedProps['b']>(props.b)\n    expectType<ExpectedProps['e']>(props.e)\n    expectType<ExpectedProps['bb']>(props.bb)\n    expectType<ExpectedProps['bbb']>(props.bbb)\n    expectType<ExpectedProps['cc']>(props.cc)\n    expectType<ExpectedProps['dd']>(props.dd)\n    expectType<ExpectedProps['ee']>(props.ee)\n    expectType<ExpectedProps['ff']>(props.ff)\n    expectType<ExpectedProps['ccc']>(props.ccc)\n    expectType<ExpectedProps['ddd']>(props.ddd)\n    expectType<ExpectedProps['eee']>(props.eee)\n    expectType<ExpectedProps['fff']>(props.fff)\n    expectType<ExpectedProps['hhh']>(props.hhh)\n    expectType<ExpectedProps['ggg']>(props.ggg)\n    // expectType<ExpectedProps['ffff']>(props.ffff) // todo fix\n    expectType<ExpectedProps['validated']>(props.validated)\n    expectType<ExpectedProps['object']>(props.object)\n\n    // rawBindings\n    expectType<Number>(rawBindings.setupA)\n\n    //setup\n    expectType<Number>(setup.setupA)\n  })\n})\n\ndescribe('array props', () => {\n  describe('defineComponent', () => {\n    const MyComponent = defineComponent({\n      props: ['a', 'b'],\n      setup() {\n        return {\n          c: 1,\n        }\n      },\n    })\n\n    const { props, rawBindings, setup } = extractComponentOptions(MyComponent)\n\n    // @ts-expect-error props should be readonly\n    props.a = 1\n    expectType<any>(props.a)\n    expectType<any>(props.b)\n\n    expectType<number>(rawBindings.c)\n    expectType<number>(setup.c)\n  })\n\n  describe('options', () => {\n    const MyComponent = {\n      props: ['a', 'b'] as const,\n      setup() {\n        return {\n          c: 1,\n        }\n      },\n    }\n\n    const { props, rawBindings, setup } = extractComponentOptions(MyComponent)\n\n    // @ts-expect-error props should be readonly\n    props.a = 1\n\n    // TODO infer the correct keys\n    // expectType<any>(props.a)\n    // expectType<any>(props.b)\n\n    expectType<number>(rawBindings.c)\n    expectType<number>(setup.c)\n  })\n})\n\ndescribe('no props', () => {\n  describe('defineComponent', () => {\n    const MyComponent = defineComponent({\n      setup() {\n        return {\n          setupA: 1,\n        }\n      },\n    })\n\n    const { rawBindings, setup } = extractComponentOptions(MyComponent)\n\n    expectType<number>(rawBindings.setupA)\n    expectType<number>(setup.setupA)\n\n    // instance\n    const instance = new MyComponent()\n    expectType<number>(instance.setupA)\n    // @ts-expect-error\n    instance.notExist\n  })\n\n  describe('options', () => {\n    const MyComponent = {\n      setup() {\n        return {\n          setupA: 1,\n        }\n      },\n    }\n\n    const { rawBindings, setup } = extractComponentOptions(MyComponent)\n\n    expectType<number>(rawBindings.setupA)\n    expectType<number>(setup.setupA)\n  })\n})\n\ndescribe('functional', () => {\n  // TODO `props.foo` is `number|undefined`\n  //   describe('defineComponent', () => {\n  //     const MyComponent = defineComponent((props: { foo: number }) => {})\n\n  //     const { props } = extractComponentOptions(MyComponent)\n\n  //     expectType<number>(props.foo)\n  //   })\n\n  describe('function', () => {\n    const MyComponent = (props: { foo: number }) => props.foo\n    const { props } = extractComponentOptions(MyComponent)\n\n    expectType<number>(props.foo)\n  })\n\n  describe('typed', () => {\n    type Props = { foo: number }\n    type Emits = { change: [value: string]; inc: [value: number] }\n    type Slots = { default: (scope: { foo: string }) => any }\n\n    const MyComponent: FunctionalComponent<Props, Emits, Slots> = (\n      props,\n      { emit, slots },\n    ) => {\n      expectType<Props>(props)\n      expectType<{\n        (event: 'change', value: string): void\n        (event: 'inc', value: number): void\n      }>(emit)\n      expectType<Slots>(slots)\n    }\n\n    const { props, emits, slots } = extractComponentOptions(MyComponent)\n\n    expectType<Props>(props)\n    expectType<Emits>(emits)\n    expectType<Slots>(slots)\n  })\n})\n\ndeclare type VueClass<Props = {}> = {\n  new (): ComponentPublicInstance<Props>\n}\n\ndescribe('class', () => {\n  const MyComponent: VueClass<{ foo: number }> = {} as any\n\n  const { props } = extractComponentOptions(MyComponent)\n\n  expectType<number>(props.foo)\n})\n\ndescribe('SetupContext', () => {\n  describe('can assign', () => {\n    const wider: SetupContext<{ a: () => true; b: () => true }> = {} as any\n\n    expectAssignable<SetupContext<{ b: () => true }>>(wider)\n  })\n\n  describe('short emits', () => {\n    const {\n      emit,\n    }: SetupContext<{\n      a: [val: string]\n      b: [val: number]\n    }> = {} as any\n\n    expectType<{\n      (event: 'a', val: string): void\n      (event: 'b', val: number): void\n    }>(emit)\n  })\n})\n"
  },
  {
    "path": "packages-private/dts-test/componentInstance.test-d.tsx",
    "content": "import {\n  type ComponentInstance,\n  type ComponentPublicInstance,\n  type FunctionalComponent,\n  defineComponent,\n  ref,\n} from 'vue'\nimport { describe, expectType } from './utils'\n\ndescribe('defineComponent', () => {\n  const CompSetup = defineComponent({\n    props: {\n      test: String,\n    },\n    setup() {\n      return {\n        a: 1,\n      }\n    },\n  })\n  const compSetup: ComponentInstance<typeof CompSetup> = {} as any\n\n  expectType<string | undefined>(compSetup.test)\n  expectType<number>(compSetup.a)\n  expectType<ComponentPublicInstance>(compSetup)\n})\ndescribe('functional component', () => {\n  // Functional\n  const CompFunctional: FunctionalComponent<{ test?: string }> = {} as any\n  const compFunctional: ComponentInstance<typeof CompFunctional> = {} as any\n\n  expectType<string | undefined>(compFunctional.test)\n  expectType<ComponentPublicInstance>(compFunctional)\n\n  const CompFunction: (props: { test?: string }) => any = {} as any\n  const compFunction: ComponentInstance<typeof CompFunction> = {} as any\n\n  expectType<string | undefined>(compFunction.test)\n  expectType<ComponentPublicInstance>(compFunction)\n})\n\ndescribe('options component', () => {\n  // Options\n  const CompOptions = defineComponent({\n    props: {\n      test: String,\n    },\n    data() {\n      return {\n        a: 1,\n      }\n    },\n    computed: {\n      b() {\n        return 'test'\n      },\n    },\n    methods: {\n      func(a: string) {\n        return true\n      },\n    },\n  })\n  const compOptions: ComponentInstance<typeof CompOptions> = {} as any\n  expectType<string | undefined>(compOptions.test)\n  expectType<number>(compOptions.a)\n  expectType<(a: string) => boolean>(compOptions.func)\n  expectType<ComponentPublicInstance>(compOptions)\n})\n\ndescribe('object no defineComponent', () => {\n  // object - no defineComponent\n\n  const CompObjectSetup = {\n    props: {\n      test: String,\n    },\n    setup() {\n      return {\n        a: 1,\n      }\n    },\n  }\n  const compObjectSetup: ComponentInstance<typeof CompObjectSetup> = {} as any\n  expectType<string | undefined>(compObjectSetup.test)\n  expectType<number>(compObjectSetup.a)\n  expectType<ComponentPublicInstance>(compObjectSetup)\n\n  const CompObjectData = {\n    props: {\n      test: String,\n    },\n    data() {\n      return {\n        a: 1,\n      }\n    },\n  }\n  const compObjectData: ComponentInstance<typeof CompObjectData> = {} as any\n  expectType<string | undefined>(compObjectData.test)\n  expectType<number>(compObjectData.a)\n  expectType<ComponentPublicInstance>(compObjectData)\n\n  const CompObjectNoProps = {\n    data() {\n      return {\n        a: 1,\n      }\n    },\n  }\n  const compObjectNoProps: ComponentInstance<typeof CompObjectNoProps> =\n    {} as any\n  expectType<string | undefined>(compObjectNoProps.test)\n  expectType<number>(compObjectNoProps.a)\n  expectType<ComponentPublicInstance>(compObjectNoProps)\n})\n\ndescribe('Generic component', () => {\n  const Comp = defineComponent(\n    // TODO: babel plugin to auto infer runtime props options from type\n    // similar to defineProps<{...}>()\n    <T extends string | number>(props: { msg: T; list: T[] }) => {\n      // use Composition API here like in <script setup>\n      const count = ref(0)\n\n      return () => (\n        // return a render function (both JSX and h() works)\n        <div>\n          {props.msg} {count.value}\n        </div>\n      )\n    },\n  )\n\n  // defaults to known types since types are resolved on instantiation\n  const comp: ComponentInstance<typeof Comp> = {} as any\n  expectType<string | number>(comp.msg)\n  expectType<Array<string | number>>(comp.list)\n})\n\n// #12751\n{\n  const Comp = defineComponent({\n    __typeEmits: {} as {\n      'update:visible': [value?: boolean]\n    },\n  })\n  const comp: ComponentInstance<typeof Comp> = {} as any\n\n  expectType<((value?: boolean) => any) | undefined>(comp['onUpdate:visible'])\n  expectType<{ 'onUpdate:visible'?: (value?: boolean) => any }>(comp['$props'])\n  // @ts-expect-error\n  comp['$props']['$props']\n}\n"
  },
  {
    "path": "packages-private/dts-test/componentTypeExtensions.test-d.tsx",
    "content": "import { type DefineComponent, type Directive, defineComponent } from 'vue'\nimport { expectType } from './utils'\n\ndeclare module 'vue' {\n  interface ComponentCustomOptions {\n    test?(n: number): void\n  }\n\n  interface GlobalDirectives {\n    test: Directive\n  }\n\n  interface GlobalComponents {\n    RouterView: DefineComponent<{}>\n  }\n\n  interface ComponentCustomProperties {\n    state?: 'stopped' | 'running'\n  }\n\n  interface ComponentCustomProps {\n    custom?: number\n  }\n}\n\nexport const Custom = defineComponent({\n  props: {\n    bar: String,\n    baz: {\n      type: Number,\n      required: true,\n    },\n  },\n\n  data: () => ({ counter: 0 }),\n\n  test(n) {\n    expectType<number>(n)\n  },\n\n  methods: {\n    aMethod() {\n      this.counter++\n      this.state = 'running'\n      this.$.appContext.config.globalProperties.state = 'running'\n\n      // @ts-expect-error\n      this.notExisting\n      // @ts-expect-error\n      this.state = 'not valid'\n      // @ts-expect-error\n      this.$.appContext.config.globalProperties.state = 'not valid'\n    },\n  },\n})\n\nexpectType<Directive>(Custom.directives!.test)\nexpectType<DefineComponent<{}>>(Custom.components!.RouterView)\nexpectType<JSX.Element>(<Custom baz={1} />)\nexpectType<JSX.Element>(<Custom custom={1} baz={1} />)\nexpectType<JSX.Element>(<Custom bar=\"bar\" baz={1} />)\nexpectType<JSX.Element>(<Custom ref={''} bar=\"bar\" baz={1} />)\n\n// @ts-expect-error\nexpectType<JSX.Element>(<Custom />)\n// @ts-expect-error\n;<Custom bar=\"bar\" />\n// @ts-expect-error\n;<Custom baz=\"baz\" />\n// @ts-expect-error\n;<Custom baz={1} notExist={1} />\n// @ts-expect-error\n;<Custom baz={1} custom=\"custom\" />\n"
  },
  {
    "path": "packages-private/dts-test/defineComponent.test-d.tsx",
    "content": "import {\n  type Component,\n  type ComponentOptions,\n  type ComponentPublicInstance,\n  type PropType,\n  type SetupContext,\n  type Slots,\n  type SlotsType,\n  type VNode,\n  createApp,\n  defineComponent,\n  h,\n  reactive,\n  ref,\n  withKeys,\n  withModifiers,\n} from 'vue'\nimport { type IsAny, type IsUnion, describe, expectType } from './utils'\n\ndescribe('with object props', () => {\n  interface ExpectedProps {\n    a?: number | undefined\n    aa: number\n    aaa: number | null\n    aaaa: number | undefined\n    b: string\n    e?: Function\n    h: boolean\n    j: undefined | (() => string | undefined)\n    bb: string\n    bbb: string\n    bbbb: string | undefined\n    bbbbb: string | undefined\n    cc?: string[] | undefined\n    dd: { n: 1 }\n    ee?: () => string\n    ff?: (a: number, b: string) => { a: boolean }\n    ccc?: string[] | undefined\n    ddd: string[]\n    eee: () => { a: string }\n    fff: (a: number, b: string) => { a: boolean }\n    hhh: boolean\n    ggg: 'foo' | 'bar'\n    ffff: (a: number, b: string) => { a: boolean }\n    iii?: (() => string) | (() => number)\n    jjj: ((arg1: string) => string) | ((arg1: string, arg2: string) => string)\n    kkk?: any\n    validated?: string\n    date?: Date\n    l?: Date\n    ll?: Date | number\n    lll?: string | number\n  }\n\n  type GT = string & { __brand: unknown }\n\n  const props = {\n    a: Number,\n    aa: {\n      type: Number as PropType<number | undefined>,\n      default: 1,\n    },\n    aaa: {\n      type: Number as PropType<number | null>,\n      default: 1,\n    },\n    aaaa: {\n      type: Number as PropType<number | undefined>,\n      // `as const` prevents widening to `boolean` (keeps literal `true` type)\n      required: true as const,\n    },\n    // required should make property non-void\n    b: {\n      type: String,\n      required: true as true,\n    },\n    e: Function,\n    h: Boolean,\n    j: Function as PropType<undefined | (() => string | undefined)>,\n    // default value should infer type and make it non-void\n    bb: {\n      default: 'hello',\n    },\n    bbb: {\n      // Note: default function value requires arrow syntax + explicit\n      // annotation\n      default: (props: any) => (props.bb as string) || 'foo',\n    },\n    bbbb: {\n      type: String,\n      default: undefined,\n    },\n    bbbbb: {\n      type: String,\n      default: () => undefined,\n    },\n    // explicit type casting\n    cc: Array as PropType<string[]>,\n    // required + type casting\n    dd: {\n      type: Object as PropType<{ n: 1 }>,\n      required: true as true,\n    },\n    // return type\n    ee: Function as PropType<() => string>,\n    // arguments + object return\n    ff: Function as PropType<(a: number, b: string) => { a: boolean }>,\n    // explicit type casting with constructor\n    ccc: Array as () => string[],\n    // required + constructor type casting\n    ddd: {\n      type: Array as () => string[],\n      required: true as true,\n    },\n    // required + object return\n    eee: {\n      type: Function as PropType<() => { a: string }>,\n      required: true as true,\n    },\n    // required + arguments + object return\n    fff: {\n      type: Function as PropType<(a: number, b: string) => { a: boolean }>,\n      required: true as true,\n    },\n    hhh: {\n      type: Boolean,\n      required: true as true,\n    },\n    // default + type casting\n    ggg: {\n      type: String as PropType<'foo' | 'bar'>,\n      default: 'foo',\n    },\n    // default + function\n    ffff: {\n      type: Function as PropType<(a: number, b: string) => { a: boolean }>,\n      default: (a: number, b: string) => ({ a: a > +b }),\n    },\n    // union + function with different return types\n    iii: Function as PropType<(() => string) | (() => number)>,\n    // union + function with different args & same return type\n    jjj: {\n      type: Function as PropType<\n        ((arg1: string) => string) | ((arg1: string, arg2: string) => string)\n      >,\n      required: true as true,\n    },\n    kkk: null,\n    validated: {\n      type: String,\n      // validator requires explicit annotation\n      validator: (val: unknown) => val !== '',\n    },\n    date: Date,\n    l: [Date],\n    ll: [Date, Number],\n    lll: [String, Number],\n  }\n\n  const MyComponent = defineComponent({\n    props,\n    setup(props) {\n      // type assertion. See https://github.com/SamVerschueren/tsd\n      expectType<ExpectedProps['a']>(props.a)\n      expectType<ExpectedProps['aa']>(props.aa)\n      expectType<ExpectedProps['aaa']>(props.aaa)\n\n      // @ts-expect-error should included `undefined`\n      expectType<number>(props.aaaa)\n      expectType<ExpectedProps['aaaa']>(props.aaaa)\n\n      expectType<ExpectedProps['b']>(props.b)\n      expectType<ExpectedProps['e']>(props.e)\n      expectType<ExpectedProps['h']>(props.h)\n      expectType<ExpectedProps['j']>(props.j)\n      expectType<ExpectedProps['bb']>(props.bb)\n      expectType<ExpectedProps['bbb']>(props.bbb)\n      expectType<ExpectedProps['bbbb']>(props.bbbb)\n      expectType<ExpectedProps['bbbbb']>(props.bbbbb)\n      expectType<ExpectedProps['cc']>(props.cc)\n      expectType<ExpectedProps['dd']>(props.dd)\n      expectType<ExpectedProps['ee']>(props.ee)\n      expectType<ExpectedProps['ff']>(props.ff)\n      expectType<ExpectedProps['ccc']>(props.ccc)\n      expectType<ExpectedProps['ddd']>(props.ddd)\n      expectType<ExpectedProps['eee']>(props.eee)\n      expectType<ExpectedProps['fff']>(props.fff)\n      expectType<ExpectedProps['hhh']>(props.hhh)\n      expectType<ExpectedProps['ggg']>(props.ggg)\n      expectType<ExpectedProps['ffff']>(props.ffff)\n      if (typeof props.iii !== 'function') {\n        expectType<undefined>(props.iii)\n      }\n      expectType<ExpectedProps['iii']>(props.iii)\n      expectType<IsUnion<typeof props.jjj>>(true)\n      expectType<ExpectedProps['jjj']>(props.jjj)\n      expectType<ExpectedProps['kkk']>(props.kkk)\n      expectType<ExpectedProps['validated']>(props.validated)\n      expectType<ExpectedProps['date']>(props.date)\n      expectType<ExpectedProps['l']>(props.l)\n      expectType<ExpectedProps['ll']>(props.ll)\n      expectType<ExpectedProps['lll']>(props.lll)\n\n      // @ts-expect-error props should be readonly\n      props.a = 1\n\n      // setup context\n      return {\n        c: ref(1),\n        d: {\n          e: ref('hi'),\n        },\n        f: reactive({\n          g: ref('hello' as GT),\n        }),\n      }\n    },\n    provide() {\n      return {}\n    },\n    render() {\n      const props = this.$props\n      expectType<ExpectedProps['a']>(props.a)\n      expectType<ExpectedProps['aa']>(props.aa)\n      expectType<ExpectedProps['aaa']>(props.aaa)\n      expectType<ExpectedProps['b']>(props.b)\n      expectType<ExpectedProps['e']>(props.e)\n      expectType<ExpectedProps['h']>(props.h)\n      expectType<ExpectedProps['bb']>(props.bb)\n      expectType<ExpectedProps['cc']>(props.cc)\n      expectType<ExpectedProps['dd']>(props.dd)\n      expectType<ExpectedProps['ee']>(props.ee)\n      expectType<ExpectedProps['ff']>(props.ff)\n      expectType<ExpectedProps['ccc']>(props.ccc)\n      expectType<ExpectedProps['ddd']>(props.ddd)\n      expectType<ExpectedProps['eee']>(props.eee)\n      expectType<ExpectedProps['fff']>(props.fff)\n      expectType<ExpectedProps['hhh']>(props.hhh)\n      expectType<ExpectedProps['ggg']>(props.ggg)\n      if (typeof props.iii !== 'function') {\n        expectType<undefined>(props.iii)\n      }\n      expectType<ExpectedProps['iii']>(props.iii)\n      expectType<IsUnion<typeof props.jjj>>(true)\n      expectType<ExpectedProps['jjj']>(props.jjj)\n      expectType<ExpectedProps['kkk']>(props.kkk)\n\n      // @ts-expect-error props should be readonly\n      props.a = 1\n\n      // should also expose declared props on `this`\n      expectType<ExpectedProps['a']>(this.a)\n      expectType<ExpectedProps['aa']>(this.aa)\n      expectType<ExpectedProps['aaa']>(this.aaa)\n      expectType<ExpectedProps['b']>(this.b)\n      expectType<ExpectedProps['e']>(this.e)\n      expectType<ExpectedProps['h']>(this.h)\n      expectType<ExpectedProps['bb']>(this.bb)\n      expectType<ExpectedProps['cc']>(this.cc)\n      expectType<ExpectedProps['dd']>(this.dd)\n      expectType<ExpectedProps['ee']>(this.ee)\n      expectType<ExpectedProps['ff']>(this.ff)\n      expectType<ExpectedProps['ccc']>(this.ccc)\n      expectType<ExpectedProps['ddd']>(this.ddd)\n      expectType<ExpectedProps['eee']>(this.eee)\n      expectType<ExpectedProps['fff']>(this.fff)\n      expectType<ExpectedProps['hhh']>(this.hhh)\n      expectType<ExpectedProps['ggg']>(this.ggg)\n      if (typeof this.iii !== 'function') {\n        expectType<undefined>(this.iii)\n      }\n      expectType<ExpectedProps['iii']>(this.iii)\n      const { jjj } = this\n      expectType<IsUnion<typeof jjj>>(true)\n      expectType<ExpectedProps['jjj']>(this.jjj)\n      expectType<ExpectedProps['kkk']>(this.kkk)\n\n      // @ts-expect-error props on `this` should be readonly\n      this.a = 1\n\n      // assert setup context unwrapping\n      expectType<number>(this.c)\n      expectType<string>(this.d.e.value)\n      expectType<GT>(this.f.g)\n\n      // setup context properties should be mutable\n      this.c = 2\n\n      return null\n    },\n  })\n\n  expectType<Component>(MyComponent)\n\n  // Test TSX\n  expectType<JSX.Element>(\n    <MyComponent\n      a={1}\n      aaaa={1}\n      b=\"b\"\n      bb=\"bb\"\n      e={() => {}}\n      cc={['cc']}\n      dd={{ n: 1 }}\n      ee={() => 'ee'}\n      ccc={['ccc']}\n      ddd={['ddd']}\n      eee={() => ({ a: 'eee' })}\n      fff={(a, b) => ({ a: a > +b })}\n      hhh={false}\n      ggg=\"foo\"\n      jjj={() => ''}\n      // should allow class/style as attrs\n      class=\"bar\"\n      style={{ color: 'red' }}\n      // should allow key\n      key={'foo'}\n      // should allow ref\n      ref={'foo'}\n      ref_for={true}\n    />,\n  )\n\n  expectType<Component>(\n    <MyComponent\n      aaaa={1}\n      b=\"b\"\n      dd={{ n: 1 }}\n      ddd={['ddd']}\n      eee={() => ({ a: 'eee' })}\n      fff={(a, b) => ({ a: a > +b })}\n      hhh={false}\n      jjj={() => ''}\n    />,\n  )\n\n  // @ts-expect-error missing required props\n  let c = <MyComponent />\n  // @ts-expect-error wrong prop types\n  c = <MyComponent a={'wrong type'} b=\"foo\" dd={{ n: 1 }} ddd={['foo']} />\n  // @ts-expect-error wrong prop types\n  c = <MyComponent ggg=\"baz\" />\n\n  // @ts-expect-error\n  ;<MyComponent b=\"foo\" dd={{ n: 'string' }} ddd={['foo']} />\n\n  // `this` should be void inside of prop validators and prop default factories\n  defineComponent({\n    props: {\n      myProp: {\n        type: Number,\n        validator(val: unknown): boolean {\n          // @ts-expect-error\n          return val !== this.otherProp\n        },\n        default(): number {\n          // @ts-expect-error\n          return this.otherProp + 1\n        },\n      },\n      otherProp: {\n        type: Number,\n        required: true,\n      },\n    },\n  })\n})\n\ndescribe('type inference w/ optional props declaration', () => {\n  const MyComponent = defineComponent<{ a: string[]; msg: string }>({\n    setup(props) {\n      expectType<string>(props.msg)\n      expectType<string[]>(props.a)\n      return {\n        b: 1,\n      }\n    },\n  })\n\n  expectType<JSX.Element>(<MyComponent msg=\"1\" a={['1']} />)\n  // @ts-expect-error\n  ;<MyComponent />\n  // @ts-expect-error\n  ;<MyComponent msg=\"1\" />\n})\n\ndescribe('type inference w/ direct setup function', () => {\n  const MyComponent = defineComponent((_props: { msg: string }) => () => {})\n  expectType<JSX.Element>(<MyComponent msg=\"foo\" />)\n  // @ts-expect-error\n  ;<MyComponent />\n  // @ts-expect-error\n  ;<MyComponent msg={1} />\n})\n\ndescribe('type inference w/ array props declaration', () => {\n  const MyComponent = defineComponent({\n    props: ['a', 'b'],\n    setup(props) {\n      // @ts-expect-error props should be readonly\n      props.a = 1\n      expectType<any>(props.a)\n      expectType<any>(props.b)\n      return {\n        c: 1,\n      }\n    },\n    render() {\n      expectType<any>(this.$props.a)\n      expectType<any>(this.$props.b)\n      // @ts-expect-error\n      this.$props.a = 1\n      expectType<any>(this.a)\n      expectType<any>(this.b)\n      expectType<number>(this.c)\n    },\n  })\n  expectType<JSX.Element>(<MyComponent a={[1, 2]} b=\"b\" />)\n  // @ts-expect-error\n  ;<MyComponent other=\"other\" />\n})\n\ndescribe('type inference w/ options API', () => {\n  defineComponent({\n    props: { a: Number },\n    setup() {\n      return {\n        b: 123,\n      }\n    },\n    data() {\n      // Limitation: we cannot expose the return result of setup() on `this`\n      // here in data() - somehow that would mess up the inference\n      expectType<number | undefined>(this.a)\n      return {\n        c: this.a || 123,\n        someRef: ref(0),\n      }\n    },\n    computed: {\n      d() {\n        expectType<number>(this.b)\n        return this.b + 1\n      },\n      e: {\n        get() {\n          expectType<number>(this.b)\n          expectType<number>(this.d)\n\n          return this.b + this.d\n        },\n        set(v: number) {\n          expectType<number>(this.b)\n          expectType<number>(this.d)\n          expectType<number>(v)\n        },\n      },\n    },\n    watch: {\n      a() {\n        expectType<number>(this.b)\n        this.b + 1\n      },\n    },\n    created() {\n      // props\n      expectType<number | undefined>(this.a)\n      // returned from setup()\n      expectType<number>(this.b)\n      // returned from data()\n      expectType<number>(this.c)\n      // computed\n      expectType<number>(this.d)\n      // computed get/set\n      expectType<number>(this.e)\n      expectType<number>(this.someRef)\n    },\n    methods: {\n      doSomething() {\n        // props\n        expectType<number | undefined>(this.a)\n        // returned from setup()\n        expectType<number>(this.b)\n        // returned from data()\n        expectType<number>(this.c)\n        // computed\n        expectType<number>(this.d)\n        // computed get/set\n        expectType<number>(this.e)\n      },\n      returnSomething() {\n        return this.a\n      },\n    },\n    render() {\n      // props\n      expectType<number | undefined>(this.a)\n      // returned from setup()\n      expectType<number>(this.b)\n      // returned from data()\n      expectType<number>(this.c)\n      // computed\n      expectType<number>(this.d)\n      // computed get/set\n      expectType<number>(this.e)\n      // method\n      expectType<() => number | undefined>(this.returnSomething)\n    },\n  })\n})\n\n// #4051\ndescribe('type inference w/ empty prop object', () => {\n  const MyComponent = defineComponent({\n    props: {},\n    setup(props) {\n      return {}\n    },\n    render() {},\n  })\n  expectType<JSX.Element>(<MyComponent />)\n  // AllowedComponentProps\n  expectType<JSX.Element>(<MyComponent class={'foo'} />)\n  // ComponentCustomProps\n  expectType<JSX.Element>(<MyComponent custom={1} />)\n  // VNodeProps\n  expectType<JSX.Element>(<MyComponent key=\"1\" />)\n  // @ts-expect-error\n  expectError(<MyComponent other=\"other\" />)\n})\n\ndescribe('with mixins', () => {\n  const MixinA = defineComponent({\n    emits: ['bar'],\n    props: {\n      aP1: {\n        type: String,\n        default: 'aP1',\n      },\n      aP2: Boolean,\n    },\n    data() {\n      return {\n        a: 1,\n      }\n    },\n  })\n  const MixinB = defineComponent({\n    props: ['bP1', 'bP2'],\n    data() {\n      return {\n        b: 2,\n      }\n    },\n  })\n  const MixinC = defineComponent({\n    data() {\n      return {\n        c: 3,\n      }\n    },\n  })\n  const MixinD = defineComponent({\n    mixins: [MixinA],\n    data() {\n      //@ts-expect-error computed are not available on data()\n      expectError<number>(this.dC1)\n      //@ts-expect-error computed are not available on data()\n      expectError<string>(this.dC2)\n\n      return {\n        d: 4,\n      }\n    },\n    setup(props) {\n      expectType<string>(props.aP1)\n    },\n    computed: {\n      dC1() {\n        return this.d + this.a\n      },\n      dC2() {\n        return this.aP1 + 'dC2'\n      },\n    },\n  })\n  const MyComponent = defineComponent({\n    mixins: [MixinA, MixinB, MixinC, MixinD],\n    emits: ['click'],\n    props: {\n      // required should make property non-void\n      z: {\n        type: String,\n        required: true,\n      },\n    },\n\n    data(vm) {\n      expectType<number>(vm.a)\n      expectType<number>(vm.b)\n      expectType<number>(vm.c)\n      expectType<number>(vm.d)\n\n      // should also expose declared props on `this`\n      expectType<number>(this.a)\n      expectType<string>(this.aP1)\n      expectType<boolean | undefined>(this.aP2)\n      expectType<number>(this.b)\n      expectType<any>(this.bP1)\n      expectType<number>(this.c)\n      expectType<number>(this.d)\n\n      return {}\n    },\n\n    setup(props) {\n      expectType<string>(props.z)\n      // props\n      expectType<((...args: any[]) => any) | undefined>(props.onClick)\n      // from MixinA\n      expectType<((...args: any[]) => any) | undefined>(props.onBar)\n      expectType<string>(props.aP1)\n      expectType<boolean | undefined>(props.aP2)\n      expectType<any>(props.bP1)\n      expectType<any>(props.bP2)\n      expectType<string>(props.z)\n    },\n    render() {\n      const props = this.$props\n      // props\n      expectType<((...args: any[]) => any) | undefined>(props.onClick)\n      // from MixinA\n      expectType<((...args: any[]) => any) | undefined>(props.onBar)\n      expectType<string>(props.aP1)\n      expectType<boolean | undefined>(props.aP2)\n      expectType<any>(props.bP1)\n      expectType<any>(props.bP2)\n      expectType<string>(props.z)\n\n      const data = this.$data\n      expectType<number>(data.a)\n      expectType<number>(data.b)\n      expectType<number>(data.c)\n      expectType<number>(data.d)\n\n      // should also expose declared props on `this`\n      expectType<number>(this.a)\n      expectType<string>(this.aP1)\n      expectType<boolean | undefined>(this.aP2)\n      expectType<number>(this.b)\n      expectType<any>(this.bP1)\n      expectType<number>(this.c)\n      expectType<number>(this.d)\n      expectType<number>(this.dC1)\n      expectType<string>(this.dC2)\n\n      // props should be readonly\n      // @ts-expect-error\n      this.aP1 = 'new'\n      // @ts-expect-error\n      this.z = 1\n\n      // props on `this` should be readonly\n      // @ts-expect-error\n      this.bP1 = 1\n\n      // string value can not assigned to number type value\n      // @ts-expect-error\n      this.c = '1'\n\n      // setup context properties should be mutable\n      this.d = 5\n\n      return null\n    },\n  })\n\n  // Test TSX\n  expectType<JSX.Element>(\n    <MyComponent aP1={'aP'} aP2 bP1={1} bP2={[1, 2]} z={'z'} />,\n  )\n\n  // missing required props\n  // @ts-expect-error\n  ;<MyComponent />\n\n  // wrong prop types\n  // @ts-expect-error\n  ;<MyComponent aP1=\"ap\" aP2={'wrong type'} bP1=\"b\" z={'z'} />\n  // @ts-expect-error\n  ;<MyComponent aP1={1} bP2={[1]} />\n})\n\ndescribe('with extends', () => {\n  const Base = defineComponent({\n    props: {\n      aP1: Boolean,\n      aP2: {\n        type: Number,\n        default: 2,\n      },\n    },\n    data() {\n      return {\n        a: 1,\n      }\n    },\n    computed: {\n      c(): number {\n        return this.aP2 + this.a\n      },\n    },\n  })\n  const MyComponent = defineComponent({\n    extends: Base,\n    props: {\n      // required should make property non-void\n      z: {\n        type: String,\n        required: true,\n      },\n    },\n    render() {\n      const props = this.$props\n      // props\n      expectType<boolean | undefined>(props.aP1)\n      expectType<number>(props.aP2)\n      expectType<string>(props.z)\n\n      const data = this.$data\n      expectType<number>(data.a)\n\n      // should also expose declared props on `this`\n      expectType<number>(this.a)\n      expectType<boolean | undefined>(this.aP1)\n      expectType<number>(this.aP2)\n\n      // setup context properties should be mutable\n      this.a = 5\n\n      return null\n    },\n  })\n\n  // Test TSX\n  expectType<JSX.Element>(<MyComponent aP2={3} aP1 z={'z'} />)\n\n  // missing required props\n  // @ts-expect-error\n  ;<MyComponent />\n\n  // wrong prop types\n  // @ts-expect-error\n  ;<MyComponent aP2={'wrong type'} z={'z'} />\n  // @ts-expect-error\n  ;<MyComponent aP1={3} />\n})\n\ndescribe('extends with mixins', () => {\n  const Mixin = defineComponent({\n    emits: ['bar'],\n    props: {\n      mP1: {\n        type: String,\n        default: 'mP1',\n      },\n      mP2: Boolean,\n      mP3: {\n        type: Boolean,\n        required: true,\n      },\n    },\n    data() {\n      return {\n        a: 1,\n      }\n    },\n  })\n  const Base = defineComponent({\n    emits: ['foo'],\n    props: {\n      p1: Boolean,\n      p2: {\n        type: Number,\n        default: 2,\n      },\n      p3: {\n        type: Boolean,\n        required: true,\n      },\n    },\n    data() {\n      return {\n        b: 2,\n      }\n    },\n    computed: {\n      c(): number {\n        return this.p2 + this.b\n      },\n    },\n  })\n  const MyComponent = defineComponent({\n    extends: Base,\n    mixins: [Mixin],\n    emits: ['click'],\n    props: {\n      // required should make property non-void\n      z: {\n        type: String,\n        required: true,\n      },\n    },\n    render() {\n      const props = this.$props\n      // props\n      expectType<((...args: any[]) => any) | undefined>(props.onClick)\n      // from Mixin\n      expectType<((...args: any[]) => any) | undefined>(props.onBar)\n      // from Base\n      expectType<((...args: any[]) => any) | undefined>(props.onFoo)\n      expectType<boolean | undefined>(props.p1)\n      expectType<number>(props.p2)\n      expectType<string>(props.z)\n      expectType<string>(props.mP1)\n      expectType<boolean | undefined>(props.mP2)\n\n      const data = this.$data\n      expectType<number>(data.a)\n      expectType<number>(data.b)\n\n      // should also expose declared props on `this`\n      expectType<number>(this.a)\n      expectType<number>(this.b)\n      expectType<boolean | undefined>(this.p1)\n      expectType<number>(this.p2)\n      expectType<string>(this.mP1)\n      expectType<boolean | undefined>(this.mP2)\n\n      // setup context properties should be mutable\n      this.a = 5\n\n      return null\n    },\n  })\n\n  // Test TSX\n  expectType<JSX.Element>(<MyComponent mP1=\"p1\" mP2 mP3 p1 p2={1} p3 z={'z'} />)\n\n  // mP1, mP2, p1, and p2 have default value. these are not required\n  expectType<JSX.Element>(<MyComponent mP3 p3 z={'z'} />)\n\n  // missing required props\n  // @ts-expect-error\n  ;<MyComponent mP3 p3 /* z='z' */ />\n  // missing required props from mixin\n  // @ts-expect-error\n  ;<MyComponent /* mP3 */ p3 z=\"z\" />\n  // missing required props from extends\n  // @ts-expect-error\n  ;<MyComponent mP3 /* p3 */ z=\"z\" />\n\n  // wrong prop types\n  // @ts-expect-error\n  ;<MyComponent p2={'wrong type'} z={'z'} />\n  // @ts-expect-error\n  ;<MyComponent mP1={3} />\n\n  // #3468\n  const CompWithD = defineComponent({\n    data() {\n      return { foo: 1 }\n    },\n  })\n  const CompWithC = defineComponent({\n    computed: {\n      foo() {\n        return 1\n      },\n    },\n  })\n  const CompWithM = defineComponent({ methods: { foo() {} } })\n  const CompEmpty = defineComponent({})\n\n  defineComponent({\n    mixins: [CompWithD, CompEmpty],\n    mounted() {\n      expectType<number>(this.foo)\n    },\n  })\n  defineComponent({\n    mixins: [CompWithC, CompEmpty],\n    mounted() {\n      expectType<number>(this.foo)\n    },\n  })\n  defineComponent({\n    mixins: [CompWithM, CompEmpty],\n    mounted() {\n      expectType<() => void>(this.foo)\n    },\n  })\n})\n\ndescribe('compatibility w/ createApp', () => {\n  const comp = defineComponent({})\n  createApp(comp).mount('#hello')\n\n  const comp2 = defineComponent({\n    props: { foo: String },\n  })\n  createApp(comp2).mount('#hello')\n\n  const comp3 = defineComponent({\n    setup() {\n      return {\n        a: 1,\n      }\n    },\n  })\n  createApp(comp3).mount('#hello')\n})\n\ndescribe('defineComponent', () => {\n  describe('should accept components defined with defineComponent', () => {\n    const comp = defineComponent({})\n    defineComponent({\n      components: { comp },\n    })\n  })\n\n  describe('should accept class components with receiving constructor arguments', () => {\n    class Comp {\n      static __vccOpts = {}\n      constructor(_props: { foo: string }) {}\n    }\n    defineComponent({\n      components: { Comp },\n    })\n  })\n})\n\ndescribe('emits', () => {\n  // Note: for TSX inference, ideally we want to map emits to onXXX props,\n  // but that requires type-level string constant concatenation as suggested in\n  // https://github.com/Microsoft/TypeScript/issues/12754\n\n  // The workaround for TSX users is instead of using emits, declare onXXX props\n  // and call them instead. Since `v-on:click` compiles to an `onClick` prop,\n  // this would also support other users consuming the component in templates\n  // with `v-on` listeners.\n\n  // with object emits\n  defineComponent({\n    emits: {\n      click: (n: number) => typeof n === 'number',\n      input: (b: string) => b.length > 1,\n      Focus: (f: boolean) => !!f,\n    },\n    setup(props, { emit }) {\n      expectType<((n: number) => boolean) | undefined>(props.onClick)\n      expectType<((b: string) => boolean) | undefined>(props.onInput)\n      expectType<((f: boolean) => boolean) | undefined>(props.onFocus)\n      emit('click', 1)\n      emit('input', 'foo')\n      emit('Focus', true)\n      //  @ts-expect-error\n      emit('nope')\n      //  @ts-expect-error\n      emit('click')\n      //  @ts-expect-error\n      emit('click', 'foo')\n      //  @ts-expect-error\n      emit('input')\n      //  @ts-expect-error\n      emit('input', 1)\n      //  @ts-expect-error\n      emit('focus')\n      //  @ts-expect-error\n      emit('focus', true)\n    },\n    created() {\n      this.$emit('click', 1)\n      this.$emit('input', 'foo')\n      //  @ts-expect-error\n      this.$emit('nope')\n      //  @ts-expect-error\n      this.$emit('click')\n      //  @ts-expect-error\n      this.$emit('click', 'foo')\n      //  @ts-expect-error\n      this.$emit('input')\n      //  @ts-expect-error\n      this.$emit('input', 1)\n      //  @ts-expect-error\n      this.$emit('focus')\n      //  @ts-expect-error\n      this.$emit('focus', true)\n    },\n    mounted() {\n      // #3599\n      this.$nextTick(function () {\n        // this should be bound to this instance\n\n        this.$emit('click', 1)\n        this.$emit('input', 'foo')\n        //  @ts-expect-error\n        this.$emit('nope')\n        //  @ts-expect-error\n        this.$emit('click')\n        //  @ts-expect-error\n        this.$emit('click', 'foo')\n        //  @ts-expect-error\n        this.$emit('input')\n        //  @ts-expect-error\n        this.$emit('input', 1)\n        //  @ts-expect-error\n        this.$emit('focus')\n        //  @ts-expect-error\n        this.$emit('focus', true)\n      })\n    },\n  })\n\n  // with array emits\n  defineComponent({\n    emits: ['foo', 'bar'],\n    setup(props, { emit }) {\n      expectType<((...args: any[]) => any) | undefined>(props.onFoo)\n      expectType<((...args: any[]) => any) | undefined>(props.onBar)\n      emit('foo')\n      emit('foo', 123)\n      emit('bar')\n      //  @ts-expect-error\n      emit('nope')\n    },\n    created() {\n      this.$emit('foo')\n      this.$emit('foo', 123)\n      this.$emit('bar')\n      //  @ts-expect-error\n      this.$emit('nope')\n    },\n  })\n\n  // with tsx\n  const Component = defineComponent({\n    emits: {\n      click: (n: number) => typeof n === 'number',\n    },\n    setup(props, { emit }) {\n      expectType<((n: number) => any) | undefined>(props.onClick)\n      emit('click', 1)\n      //  @ts-expect-error\n      emit('click')\n      //  @ts-expect-error\n      emit('click', 'foo')\n    },\n  })\n\n  defineComponent({\n    render() {\n      return (\n        <Component\n          onClick={(n: number) => {\n            return n + 1\n          }}\n        />\n      )\n    },\n  })\n\n  // #11803 manual props annotation in setup()\n  const Hello = defineComponent({\n    name: 'HelloWorld',\n    inheritAttrs: false,\n    props: { foo: String },\n    emits: {\n      customClick: (args: string) => typeof args === 'string',\n    },\n    setup(props: { foo?: string }) {},\n  })\n  ;<Hello onCustomClick={() => {}} />\n\n  // without emits\n  defineComponent({\n    setup(props, { emit }) {\n      emit('test', 1)\n      emit('test')\n    },\n  })\n\n  // emit should be valid when ComponentPublicInstance is used.\n  const instance = {} as ComponentPublicInstance\n  instance.$emit('test', 1)\n  instance.$emit('test')\n\n  // `this` should be void inside of emits validators\n  defineComponent({\n    props: ['bar'],\n    emits: {\n      foo(): boolean {\n        // @ts-expect-error\n        return this.bar === 3\n      },\n    },\n  })\n})\n\ndescribe('inject', () => {\n  // with object inject\n  defineComponent({\n    props: {\n      a: String,\n    },\n    inject: {\n      foo: 'foo',\n      bar: 'bar',\n    },\n    created() {\n      expectType<unknown>(this.foo)\n      expectType<unknown>(this.bar)\n      //  @ts-expect-error\n      this.foobar = 1\n    },\n  })\n\n  // with array inject\n  defineComponent({\n    props: ['a', 'b'],\n    inject: ['foo', 'bar'],\n    created() {\n      expectType<unknown>(this.foo)\n      expectType<unknown>(this.bar)\n      //  @ts-expect-error\n      this.foobar = 1\n    },\n  })\n\n  // with no props\n  defineComponent({\n    inject: {\n      foo: {\n        from: 'pfoo',\n        default: 'foo',\n      },\n      bar: {\n        from: 'pbar',\n        default: 'bar',\n      },\n    },\n    created() {\n      expectType<unknown>(this.foo)\n      expectType<unknown>(this.bar)\n      //  @ts-expect-error\n      this.foobar = 1\n    },\n  })\n\n  // without inject\n  defineComponent({\n    props: ['a', 'b'],\n    created() {\n      //  @ts-expect-error\n      this.foo = 1\n      //  @ts-expect-error\n      this.bar = 1\n    },\n  })\n})\n\ndescribe('componentOptions setup should be `SetupContext`', () => {\n  expectType<ComponentOptions['setup']>(\n    {} as (props: Record<string, any>, ctx: SetupContext) => any,\n  )\n})\n\ndescribe('extract instance type', () => {\n  const Base = defineComponent({\n    props: {\n      baseA: {\n        type: Number,\n        default: 1,\n      },\n    },\n  })\n  const MixinA = defineComponent({\n    props: {\n      mA: {\n        type: String,\n        default: '',\n      },\n    },\n  })\n  const CompA = defineComponent({\n    extends: Base,\n    mixins: [MixinA],\n    props: {\n      a: {\n        type: Boolean,\n        default: false,\n      },\n      b: {\n        type: String,\n        required: true,\n      },\n      c: Number,\n    },\n  })\n\n  const compA = {} as InstanceType<typeof CompA>\n\n  expectType<boolean>(compA.a)\n  expectType<string>(compA.b)\n  expectType<number | undefined>(compA.c)\n  // mixins\n  expectType<string>(compA.mA)\n  // extends\n  expectType<number>(compA.baseA)\n\n  //  @ts-expect-error\n  compA.a = true\n  //  @ts-expect-error\n  compA.b = 'foo'\n  //  @ts-expect-error\n  compA.c = 1\n  //  @ts-expect-error\n  compA.mA = 'foo'\n  //  @ts-expect-error\n  compA.baseA = 1\n})\n\ndescribe('async setup', () => {\n  type GT = string & { __brand: unknown }\n  const Comp = defineComponent({\n    async setup() {\n      // setup context\n      return {\n        a: ref(1),\n        b: {\n          c: ref('hi'),\n        },\n        d: reactive({\n          e: ref('hello' as GT),\n        }),\n      }\n    },\n    render() {\n      // assert setup context unwrapping\n      expectType<number>(this.a)\n      expectType<string>(this.b.c.value)\n      expectType<GT>(this.d.e)\n\n      // setup context properties should be mutable\n      this.a = 2\n    },\n  })\n\n  const vm = {} as InstanceType<typeof Comp>\n  // assert setup context unwrapping\n  expectType<number>(vm.a)\n  expectType<string>(vm.b.c.value)\n  expectType<GT>(vm.d.e)\n\n  // setup context properties should be mutable\n  vm.a = 2\n})\n\n// #5948\ndescribe('DefineComponent should infer correct types when assigning to Component', () => {\n  let component: Component\n  component = defineComponent({\n    setup(_, { attrs, slots }) {\n      // @ts-expect-error should not be any\n      expectType<[]>(attrs)\n      // @ts-expect-error should not be any\n      expectType<[]>(slots)\n    },\n  })\n  expectType<Component>(component)\n})\n\n// #5969\ndescribe('should allow to assign props', () => {\n  const Child = defineComponent({\n    props: {\n      bar: String,\n    },\n  })\n\n  const Parent = defineComponent({\n    props: {\n      ...Child.props,\n      foo: String,\n    },\n  })\n\n  const child = new Child()\n  expectType<JSX.Element>(<Parent {...child.$props} />)\n})\n\n// #6052\ndescribe('prop starting with `on*` is broken', () => {\n  defineComponent({\n    props: {\n      onX: {\n        type: Function as PropType<(a: 1) => void>,\n        required: true,\n      },\n    },\n    setup(props) {\n      expectType<(a: 1) => void>(props.onX)\n      props.onX(1)\n    },\n  })\n\n  defineComponent({\n    props: {\n      onX: {\n        type: Function as PropType<(a: 1) => void>,\n        required: true,\n      },\n    },\n    emits: {\n      test: (a: 1) => true,\n    },\n    setup(props) {\n      expectType<(a: 1) => void>(props.onX)\n      expectType<undefined | ((a: 1) => any)>(props.onTest)\n    },\n  })\n})\n\ndescribe('function syntax w/ generics', () => {\n  const Comp = defineComponent(\n    // TODO: babel plugin to auto infer runtime props options from type\n    // similar to defineProps<{...}>()\n    <T extends string | number>(props: { msg: T; list: T[] }) => {\n      // use Composition API here like in <script setup>\n      const count = ref(0)\n\n      return () => (\n        // return a render function (both JSX and h() works)\n        <div>\n          {props.msg} {count.value}\n        </div>\n      )\n    },\n  )\n\n  expectType<JSX.Element>(<Comp msg=\"fse\" list={['foo']} />)\n  expectType<JSX.Element>(<Comp msg={123} list={[123]} />)\n\n  expectType<JSX.Element>(\n    // @ts-expect-error missing prop\n    <Comp msg={123} />,\n  )\n\n  expectType<JSX.Element>(\n    // @ts-expect-error generics don't match\n    <Comp msg=\"fse\" list={[123]} />,\n  )\n  expectType<JSX.Element>(\n    // @ts-expect-error generics don't match\n    <Comp msg={123} list={['123']} />,\n  )\n})\n\ndescribe('function syntax w/ emits', () => {\n  const Foo = defineComponent(\n    (props: { msg: string }, ctx) => {\n      ctx.emit('foo')\n      // @ts-expect-error\n      ctx.emit('bar')\n      return () => {}\n    },\n    {\n      emits: ['foo'],\n    },\n  )\n  expectType<JSX.Element>(<Foo msg=\"hi\" onFoo={() => {}} />)\n  // @ts-expect-error\n  expectType<JSX.Element>(<Foo msg=\"hi\" onBar={() => {}} />)\n\n  defineComponent(\n    (props: { msg: string }, ctx) => {\n      ctx.emit('foo', 'hi')\n      // @ts-expect-error\n      ctx.emit('foo')\n      // @ts-expect-error\n      ctx.emit('bar')\n      return () => {}\n    },\n    {\n      emits: {\n        foo: (a: string) => true,\n      },\n    },\n  )\n})\n\ndescribe('function syntax w/ runtime props', () => {\n  // with runtime props, the runtime props must match\n  // manual type declaration\n  const Comp1 = defineComponent(\n    (_props: { msg: string }) => {\n      return () => {}\n    },\n    {\n      props: ['msg'],\n    },\n  )\n\n  // @ts-expect-error bar isn't specified in props definition\n  defineComponent(\n    (_props: { msg: string }) => {\n      return () => {}\n    },\n    {\n      props: ['msg', 'bar'],\n    },\n  )\n\n  defineComponent(\n    (_props: { msg: string; bar: string }) => {\n      return () => {}\n    },\n    {\n      props: ['msg'],\n    },\n  )\n\n  expectType<JSX.Element>(<Comp1 msg=\"1\" />)\n  // @ts-expect-error msg type is incorrect\n  expectType<JSX.Element>(<Comp1 msg={1} />)\n  // @ts-expect-error msg is missing\n  expectType<JSX.Element>(<Comp1 />)\n  // @ts-expect-error bar doesn't exist\n  expectType<JSX.Element>(<Comp1 msg=\"1\" bar=\"2\" />)\n\n  const Comp2 = defineComponent(\n    <T extends string>(_props: { msg: T }) => {\n      return () => {}\n    },\n    {\n      props: ['msg'],\n    },\n  )\n\n  // @ts-expect-error bar isn't specified in props definition\n  defineComponent(\n    <T extends string>(_props: { msg: T }) => {\n      return () => {}\n    },\n    {\n      props: ['msg', 'bar'],\n    },\n  )\n\n  defineComponent(\n    <T extends string>(_props: { msg: T; bar: T }) => {\n      return () => {}\n    },\n    {\n      props: ['msg'],\n    },\n  )\n\n  expectType<JSX.Element>(<Comp2 msg=\"1\" />)\n  expectType<JSX.Element>(<Comp2<string> msg=\"1\" />)\n  // @ts-expect-error msg type is incorrect\n  expectType<JSX.Element>(<Comp2 msg={1} />)\n  // @ts-expect-error msg is missing\n  expectType<JSX.Element>(<Comp2 />)\n  // @ts-expect-error bar doesn't exist\n  expectType<JSX.Element>(<Comp2 msg=\"1\" bar=\"2\" />)\n\n  // Note: generics aren't supported with object runtime props\n  const Comp3 = defineComponent(\n    <T extends string>(_props: { msg: T }) => {\n      return () => {}\n    },\n    {\n      props: {\n        msg: String,\n      },\n    },\n  )\n\n  defineComponent(\n    // @ts-expect-error bar isn't specified in props definition\n    <T extends string>(_props: { msg: T }) => {\n      return () => {}\n    },\n    {\n      props: {\n        bar: String,\n      },\n    },\n  )\n\n  defineComponent(\n    // @ts-expect-error generics aren't supported with object runtime props\n    <T extends string>(_props: { msg: T; bar: T }) => {\n      return () => {}\n    },\n    {\n      props: {\n        msg: String,\n      },\n    },\n  )\n\n  expectType<JSX.Element>(<Comp3 msg=\"1\" />)\n  // @ts-expect-error generics aren't supported with object runtime props\n  expectType<JSX.Element>(<Comp3<string> msg=\"1\" />)\n  // @ts-expect-error msg type is incorrect\n  expectType<JSX.Element>(<Comp3 msg={1} />)\n  // @ts-expect-error msg is missing\n  expectType<JSX.Element>(<Comp3 />)\n  // @ts-expect-error bar doesn't exist\n  expectType<JSX.Element>(<Comp3 msg=\"1\" bar=\"2\" />)\n\n  // @ts-expect-error string prop names don't match\n  defineComponent(\n    (_props: { msg: string }) => {\n      return () => {}\n    },\n    {\n      props: ['bar'],\n    },\n  )\n\n  defineComponent(\n    (_props: { msg: string }) => {\n      return () => {}\n    },\n    {\n      props: {\n        // @ts-expect-error prop type mismatch\n        msg: Number,\n      },\n    },\n  )\n})\n\n// check if defineComponent can be exported\nexport default {\n  // function components\n  a: defineComponent(_ => () => h('div')),\n  // no props\n  b: defineComponent({\n    data() {\n      return {}\n    },\n  }),\n  c: defineComponent({\n    props: ['a'],\n  }),\n  d: defineComponent({\n    props: {\n      a: Number,\n    },\n  }),\n}\n\ndescribe('slots', () => {\n  const comp1 = defineComponent({\n    slots: Object as SlotsType<{\n      default: { foo: string; bar: number }\n      optional?: { data: string }\n      undefinedScope: undefined | { data: string }\n      optionalUndefinedScope?: undefined | { data: string }\n    }>,\n    setup(props, { slots }) {\n      expectType<(scope: { foo: string; bar: number }) => VNode[]>(\n        slots.default,\n      )\n      expectType<((scope: { data: string }) => VNode[]) | undefined>(\n        slots.optional,\n      )\n\n      slots.default({ foo: 'foo', bar: 1 })\n\n      // @ts-expect-error it's optional\n      slots.optional({ data: 'foo' })\n      slots.optional?.({ data: 'foo' })\n\n      expectType<{\n        (): VNode[]\n        (scope: undefined | { data: string }): VNode[]\n      }>(slots.undefinedScope)\n\n      expectType<\n        | { (): VNode[]; (scope: undefined | { data: string }): VNode[] }\n        | undefined\n      >(slots.optionalUndefinedScope)\n\n      slots.default({ foo: 'foo', bar: 1 })\n      // @ts-expect-error it's optional\n      slots.optional({ data: 'foo' })\n      slots.optional?.({ data: 'foo' })\n      slots.undefinedScope()\n      slots.undefinedScope(undefined)\n      // @ts-expect-error\n      slots.undefinedScope('foo')\n\n      slots.optionalUndefinedScope?.()\n      slots.optionalUndefinedScope?.(undefined)\n      slots.optionalUndefinedScope?.({ data: 'foo' })\n      // @ts-expect-error\n      slots.optionalUndefinedScope()\n      // @ts-expect-error\n      slots.optionalUndefinedScope?.('foo')\n\n      expectType<typeof slots | undefined>(new comp1().$slots)\n    },\n  })\n\n  const comp2 = defineComponent({\n    setup(props, { slots }) {\n      // unknown slots\n      expectType<Slots>(slots)\n      expectType<((...args: any[]) => VNode[]) | undefined>(slots.default)\n    },\n  })\n  expectType<Slots | undefined>(new comp2().$slots)\n})\n\n// #5885\ndescribe('should work when props type is incompatible with setup returned type ', () => {\n  type SizeType = 'small' | 'big'\n  const Comp = defineComponent({\n    props: {\n      size: {\n        type: String as PropType<SizeType>,\n        required: true,\n      },\n    },\n    setup(props) {\n      expectType<SizeType>(props.size)\n      return {\n        size: 1,\n      }\n    },\n  })\n  type CompInstance = InstanceType<typeof Comp>\n\n  const CompA = {} as CompInstance\n  expectType<ComponentPublicInstance>(CompA)\n  expectType<number>(CompA.size)\n  expectType<SizeType>(CompA.$props.size)\n})\n\ndescribe('withKeys and withModifiers as pro', () => {\n  const onKeydown = withKeys(e => {}, [''])\n  const onClick = withModifiers(e => {}, [])\n  ;<input onKeydown={onKeydown} onClick={onClick} />\n})\n\n// #3367 expose components types\ndescribe('expose component types', () => {\n  const child = defineComponent({\n    props: {\n      a: String,\n    },\n  })\n\n  const parent = defineComponent({\n    components: {\n      child,\n      child2: {\n        template: `<div></div>`,\n      },\n    },\n  })\n\n  expectType<typeof child>(parent.components!.child)\n  expectType<Component>(parent.components!.child2)\n\n  // global components\n  expectType<Readonly<KeepAliveProps>>(\n    new parent.components!.KeepAlive().$props,\n  )\n  expectType<Readonly<KeepAliveProps>>(new child.components!.KeepAlive().$props)\n\n  // runtime-dom components\n  expectType<Readonly<TransitionProps>>(\n    new parent.components!.Transition().$props,\n  )\n  expectType<Readonly<TransitionProps>>(\n    new child.components!.Transition().$props,\n  )\n})\n\ndescribe('directive typing', () => {\n  const customDirective: Directive = {\n    created(_) {},\n  }\n\n  const comp = defineComponent({\n    props: {\n      a: String,\n    },\n    directives: {\n      customDirective,\n      localDirective: {\n        created(_, { arg }) {\n          expectType<string | undefined>(arg)\n        },\n      },\n    },\n  })\n\n  expectType<typeof customDirective>(comp.directives!.customDirective)\n  expectType<Directive>(comp.directives!.localDirective)\n\n  // global directive\n  expectType<typeof vShow>(comp.directives!.vShow)\n})\n\ndescribe('expose typing', () => {\n  const Comp = defineComponent({\n    expose: ['a', 'b'],\n    props: {\n      some: String,\n    },\n    data() {\n      return { a: 1, b: '2', c: 1 }\n    },\n  })\n\n  expectType<Array<'a' | 'b'>>(Comp.expose!)\n\n  const vm = new Comp()\n  // internal should still be exposed\n  vm.$props\n\n  expectType<number>(vm.a)\n  expectType<string>(vm.b)\n\n  // @ts-expect-error shouldn't be exposed\n  vm.c\n})\n\nimport type {\n  AllowedComponentProps,\n  ComponentCustomProps,\n  ComponentInstance,\n  ComponentOptionsMixin,\n  DefineComponent,\n  Directive,\n  EmitsOptions,\n  ExtractPropTypes,\n  KeepAliveProps,\n  TransitionProps,\n  VNodeProps,\n  vShow,\n} from 'vue'\n\n// code generated by tsc / vue-tsc, make sure this continues to work\n// so we don't accidentally change the args order of DefineComponent\ndeclare const MyButton: DefineComponent<\n  {},\n  () => JSX.Element,\n  {},\n  {},\n  {},\n  ComponentOptionsMixin,\n  ComponentOptionsMixin,\n  EmitsOptions,\n  string,\n  VNodeProps & AllowedComponentProps & ComponentCustomProps,\n  Readonly<ExtractPropTypes<{}>>,\n  {},\n  {}\n>\n;<MyButton class=\"x\" />\n\ndescribe('__typeProps backdoor for union type for conditional props', () => {\n  interface CommonProps {\n    size?: 'xl' | 'l' | 'm' | 's' | 'xs'\n  }\n\n  type ConditionalProps =\n    | {\n        color?: 'normal' | 'primary' | 'secondary'\n        appearance?: 'normal' | 'outline' | 'text'\n      }\n    | {\n        color: 'white'\n        appearance: 'outline'\n      }\n\n  type Props = CommonProps & ConditionalProps\n\n  const Comp = defineComponent({\n    __typeProps: {} as Props,\n  })\n  // @ts-expect-error\n  ;<Comp color=\"white\" />\n  // @ts-expect-error\n  ;<Comp color=\"white\" appearance=\"normal\" />\n  ;<Comp color=\"white\" appearance=\"outline\" />\n\n  const c = new Comp()\n\n  // @ts-expect-error\n  c.$props = { color: 'white' }\n  // @ts-expect-error\n  c.$props = { color: 'white', appearance: 'text' }\n  c.$props = { color: 'white', appearance: 'outline' }\n})\n\ndescribe('__typeEmits backdoor, 3.3+ object syntax', () => {\n  type Emits = {\n    change: [id: number]\n    update: [value: string]\n  }\n\n  const Comp = defineComponent({\n    __typeEmits: {} as Emits,\n    mounted() {\n      this.$props.onChange?.(123)\n      // @ts-expect-error\n      this.$props.onChange?.('123')\n      this.$props.onUpdate?.('foo')\n      // @ts-expect-error\n      this.$props.onUpdate?.(123)\n\n      // @ts-expect-error\n      this.$emit('foo')\n\n      this.$emit('change', 123)\n      // @ts-expect-error\n      this.$emit('change', '123')\n\n      this.$emit('update', 'test')\n      // @ts-expect-error\n      this.$emit('update', 123)\n    },\n  })\n\n  ;<Comp onChange={id => id.toFixed(2)} />\n  ;<Comp onUpdate={id => id.toUpperCase()} />\n  // @ts-expect-error\n  ;<Comp onChange={id => id.slice(1)} />\n  // @ts-expect-error\n  ;<Comp onUpdate={id => id.toFixed(2)} />\n\n  const c = new Comp()\n  // @ts-expect-error\n  c.$emit('foo')\n\n  c.$emit('change', 123)\n  // @ts-expect-error\n  c.$emit('change', '123')\n\n  c.$emit('update', 'test')\n  // @ts-expect-error\n  c.$emit('update', 123)\n})\n\ndescribe('__typeEmits backdoor, call signature syntax', () => {\n  type Emits = {\n    (e: 'change', id: number): void\n    (e: 'update', value: string): void\n  }\n\n  const Comp = defineComponent({\n    __typeEmits: {} as Emits,\n    mounted() {\n      this.$props.onChange?.(123)\n      // @ts-expect-error\n      this.$props.onChange?.('123')\n      this.$props.onUpdate?.('foo')\n      // @ts-expect-error\n      this.$props.onUpdate?.(123)\n\n      // @ts-expect-error\n      this.$emit('foo')\n\n      this.$emit('change', 123)\n      // @ts-expect-error\n      this.$emit('change', '123')\n\n      this.$emit('update', 'test')\n      // @ts-expect-error\n      this.$emit('update', 123)\n    },\n  })\n\n  ;<Comp onChange={id => id.toFixed(2)} />\n  ;<Comp onUpdate={id => id.toUpperCase()} />\n  // @ts-expect-error\n  ;<Comp onChange={id => id.slice(1)} />\n  // @ts-expect-error\n  ;<Comp onUpdate={id => id.toFixed(2)} />\n\n  const c = new Comp()\n  // @ts-expect-error\n  c.$emit('foo')\n\n  c.$emit('change', 123)\n  // @ts-expect-error\n  c.$emit('change', '123')\n\n  c.$emit('update', 'test')\n  // @ts-expect-error\n  c.$emit('update', 123)\n})\n\ndescribe('__typeRefs backdoor, object syntax', () => {\n  type Refs = {\n    foo: number\n  }\n\n  const Parent = defineComponent({\n    __typeRefs: {} as { child: ComponentInstance<typeof Child> },\n  })\n  const Child = defineComponent({\n    __typeRefs: {} as Refs,\n  })\n  const c = new Parent()\n  const refs = c.$refs\n\n  expectType<ComponentInstance<typeof Child>>(refs.child)\n  expectType<number>(refs.child.$refs.foo)\n})\n\ndescribe('__typeEl backdoor', () => {\n  const Comp = defineComponent({\n    __typeEl: {} as HTMLAnchorElement,\n  })\n  const c = new Comp()\n\n  expectType<HTMLAnchorElement>(c.$el)\n})\n\ndefineComponent({\n  props: {\n    foo: [String, null],\n  },\n  setup(props) {\n    expectType<IsAny<typeof props.foo>>(false)\n    expectType<string | null | undefined>(props.foo)\n  },\n})\n\nimport type * as vue from 'vue'\n\ninterface ErrorMessageSlotProps {\n  message: string | undefined\n}\n/**\n * #10842\n * component types generated by vue-tsc\n * relying on legacy CreateComponentPublicInstance signature\n */\ndeclare const ErrorMessage: {\n  new (...args: any[]): vue.CreateComponentPublicInstance<\n    Readonly<\n      vue.ExtractPropTypes<{\n        as: {\n          type: StringConstructor\n          default: any\n        }\n        name: {\n          type: StringConstructor\n          required: true\n        }\n      }>\n    >,\n    () =>\n      | VNode<\n          vue.RendererNode,\n          vue.RendererElement,\n          {\n            [key: string]: any\n          }\n        >\n      | vue.Slot<any>\n      | VNode<\n          vue.RendererNode,\n          vue.RendererElement,\n          {\n            [key: string]: any\n          }\n        >[]\n      | {\n          default: () => VNode<\n            vue.RendererNode,\n            vue.RendererElement,\n            {\n              [key: string]: any\n            }\n          >[]\n        },\n    unknown,\n    {},\n    {},\n    vue.ComponentOptionsMixin,\n    vue.ComponentOptionsMixin,\n    {},\n    vue.VNodeProps &\n      vue.AllowedComponentProps &\n      vue.ComponentCustomProps &\n      Readonly<\n        vue.ExtractPropTypes<{\n          as: {\n            type: StringConstructor\n            default: any\n          }\n          name: {\n            type: StringConstructor\n            required: true\n          }\n        }>\n      >,\n    {\n      as: string\n    },\n    true,\n    {},\n    {},\n    {\n      P: {}\n      B: {}\n      D: {}\n      C: {}\n      M: {}\n      Defaults: {}\n    },\n    Readonly<\n      vue.ExtractPropTypes<{\n        as: {\n          type: StringConstructor\n          default: any\n        }\n        name: {\n          type: StringConstructor\n          required: true\n        }\n      }>\n    >,\n    () =>\n      | VNode<\n          vue.RendererNode,\n          vue.RendererElement,\n          {\n            [key: string]: any\n          }\n        >\n      | vue.Slot<any>\n      | VNode<\n          vue.RendererNode,\n          vue.RendererElement,\n          {\n            [key: string]: any\n          }\n        >[]\n      | {\n          default: () => VNode<\n            vue.RendererNode,\n            vue.RendererElement,\n            {\n              [key: string]: any\n            }\n          >[]\n        },\n    {},\n    {},\n    {},\n    {\n      as: string\n    }\n  >\n  __isFragment?: never\n  __isTeleport?: never\n  __isSuspense?: never\n} & vue.ComponentOptionsBase<\n  Readonly<\n    vue.ExtractPropTypes<{\n      as: {\n        type: StringConstructor\n        default: any\n      }\n      name: {\n        type: StringConstructor\n        required: true\n      }\n    }>\n  >,\n  () =>\n    | VNode<\n        vue.RendererNode,\n        vue.RendererElement,\n        {\n          [key: string]: any\n        }\n      >\n    | vue.Slot<any>\n    | VNode<\n        vue.RendererNode,\n        vue.RendererElement,\n        {\n          [key: string]: any\n        }\n      >[]\n    | {\n        default: () => VNode<\n          vue.RendererNode,\n          vue.RendererElement,\n          {\n            [key: string]: any\n          }\n        >[]\n      },\n  unknown,\n  {},\n  {},\n  vue.ComponentOptionsMixin,\n  vue.ComponentOptionsMixin,\n  {},\n  string,\n  {\n    as: string\n  },\n  {},\n  string,\n  {}\n> &\n  vue.VNodeProps &\n  vue.AllowedComponentProps &\n  vue.ComponentCustomProps &\n  (new () => {\n    $slots: {\n      default: (arg: ErrorMessageSlotProps) => VNode[]\n    }\n  })\n;<ErrorMessage name=\"password\" class=\"error\" />\n\n// #10843\ncreateApp({}).component(\n  'SomeComponent',\n  defineComponent({\n    props: {\n      title: String,\n    },\n    setup(props) {\n      expectType<string | undefined>(props.title)\n      return {}\n    },\n  }),\n)\n\nconst Comp = defineComponent({\n  props: {\n    actionText: {\n      type: {} as PropType<string>,\n      default: 'Become a sponsor',\n    },\n  },\n  __typeProps: {} as {\n    actionText?: string\n  },\n})\n\nconst instance = new Comp()\nfunction expectString(s: string) {}\n// instance prop with default should be non-null\nexpectString(instance.actionText)\n\n// public prop on $props should be optional\n// @ts-expect-error\nexpectString(instance.$props.actionText)\n\n// #12122\ndefineComponent({\n  props: { foo: String },\n  render() {\n    expectType<{ readonly foo?: string }>(this.$props)\n    // @ts-expect-error\n    expectType<string>(this.$props)\n  },\n})\n\n// #14117\ndefineComponent({\n  setup() {\n    const setup1 = ref('setup1')\n    const setup2 = ref('setup2')\n    return { setup1, setup2 }\n  },\n  data() {\n    return {\n      data1: 1,\n    }\n  },\n  props: {\n    props1: {\n      type: String,\n    },\n  },\n  methods: {\n    methods1() {\n      return `methods1`\n    },\n  },\n  computed: {\n    computed1() {\n      this.setup1\n      this.setup2\n      this.data1\n      this.props1\n      this.methods1()\n      return `computed1`\n    },\n  },\n  expose: ['setup1'],\n})\n"
  },
  {
    "path": "packages-private/dts-test/defineCustomElement.test-d.ts",
    "content": "import {\n  type VueElementConstructor,\n  defineComponent,\n  defineCustomElement,\n} from 'vue'\nimport { describe, expectType, test } from './utils'\n\ndescribe('inject', () => {\n  // with object inject\n  defineCustomElement({\n    props: {\n      a: String,\n    },\n    inject: {\n      foo: 'foo',\n      bar: 'bar',\n    },\n    created() {\n      expectType<unknown>(this.foo)\n      expectType<unknown>(this.bar)\n      //  @ts-expect-error\n      this.foobar = 1\n    },\n  })\n\n  // with array inject\n  defineCustomElement({\n    props: ['a', 'b'],\n    inject: ['foo', 'bar'],\n    created() {\n      expectType<unknown>(this.foo)\n      expectType<unknown>(this.bar)\n      //  @ts-expect-error\n      this.foobar = 1\n    },\n  })\n\n  // with no props\n  defineCustomElement({\n    inject: {\n      foo: {\n        from: 'pbar',\n        default: 'foo',\n      },\n      bar: {\n        from: 'pfoo',\n        default: 'bar',\n      },\n    },\n    created() {\n      expectType<unknown>(this.foo)\n      expectType<unknown>(this.bar)\n      //  @ts-expect-error\n      this.foobar = 1\n    },\n  })\n\n  // without inject\n  defineCustomElement({\n    props: ['a', 'b'],\n    created() {\n      //  @ts-expect-error\n      this.foo = 1\n      //  @ts-expect-error\n      this.bar = 1\n    },\n  })\n})\n\ndescribe('defineCustomElement using defineComponent return type', () => {\n  test('with object emits', () => {\n    const Comp1Vue = defineComponent({\n      props: {\n        a: String,\n      },\n      emits: {\n        click: () => true,\n      },\n    })\n    const Comp = defineCustomElement(Comp1Vue)\n    expectType<VueElementConstructor>(Comp)\n\n    const instance = new Comp()\n    expectType<string | undefined>(instance.a)\n    instance.a = ''\n  })\n\n  test('with array emits', () => {\n    const Comp1Vue = defineComponent({\n      props: {\n        a: Number,\n      },\n      emits: ['click'],\n    })\n    const Comp = defineCustomElement(Comp1Vue)\n    expectType<VueElementConstructor>(Comp)\n\n    const instance = new Comp()\n    expectType<number | undefined>(instance.a)\n    instance.a = 42\n  })\n\n  test('with required props', () => {\n    const Comp1Vue = defineComponent({\n      props: {\n        a: { type: Number, required: true },\n      },\n    })\n    const Comp = defineCustomElement(Comp1Vue)\n    expectType<VueElementConstructor>(Comp)\n\n    const instance = new Comp()\n    expectType<number>(instance.a)\n    instance.a = 42\n  })\n\n  test('with default props', () => {\n    const Comp1Vue = defineComponent({\n      props: {\n        a: {\n          type: Number,\n          default: 1,\n          validator: () => true,\n        },\n      },\n      emits: ['click'],\n    })\n    const Comp = defineCustomElement(Comp1Vue)\n    expectType<VueElementConstructor>(Comp)\n\n    const instance = new Comp()\n    expectType<number>(instance.a)\n    instance.a = 42\n  })\n})\n"
  },
  {
    "path": "packages-private/dts-test/directives.test-d.ts",
    "content": "import { type Directive, type ObjectDirective, vModelText } from 'vue'\nimport { describe, expectType } from './utils'\n\ntype ExtractBinding<T> = T extends (\n  el: any,\n  binding: infer B,\n  vnode: any,\n  prev: any,\n) => any\n  ? B\n  : never\n\ndeclare function testDirective<\n  Value,\n  Modifiers extends string = string,\n  Arg = any,\n>(): ExtractBinding<Directive<any, Value, Modifiers, Arg>>\n\ndescribe('vmodel', () => {\n  expectType<ObjectDirective<any, any, 'trim' | 'number' | 'lazy', string>>(\n    vModelText,\n  )\n  // @ts-expect-error\n  expectType<ObjectDirective<any, any, 'not-valid', string>>(vModelText)\n})\n\ndescribe('custom', () => {\n  expectType<{\n    value: number\n    oldValue: number | null\n    arg?: 'Arg'\n    modifiers: Partial<Record<'a' | 'b', boolean>>\n  }>(testDirective<number, 'a' | 'b', 'Arg'>())\n\n  expectType<{\n    value: number\n    oldValue: number | null\n    arg?: 'Arg'\n    modifiers: Record<'a' | 'b', boolean>\n    // @ts-expect-error\n  }>(testDirective<number, 'a', 'Arg'>())\n\n  expectType<{\n    value: number\n    oldValue: number | null\n    arg?: 'Arg'\n    modifiers: Partial<Record<'a' | 'b', boolean>>\n    // @ts-expect-error\n  }>(testDirective<number, 'a' | 'b', 'Argx'>())\n\n  expectType<{\n    value: number\n    oldValue: number | null\n    arg?: 'Arg'\n    modifiers: Partial<Record<'a' | 'b', boolean>>\n    // @ts-expect-error\n  }>(testDirective<string, 'a' | 'b', 'Arg'>())\n\n  expectType<{\n    value: number\n    oldValue: number | null\n    arg?: HTMLElement\n    modifiers: Partial<Record<'a' | 'b', boolean>>\n  }>(testDirective<number, 'a' | 'b', HTMLElement>())\n\n  expectType<{\n    value: number\n    oldValue: number | null\n    arg?: HTMLElement\n    modifiers: Partial<Record<'a' | 'b', boolean>>\n    // @ts-expect-error\n  }>(testDirective<number, 'a' | 'b', string>())\n\n  expectType<{\n    value: number\n    oldValue: number | null\n    arg?: HTMLElement\n    modifiers: Partial<Record<'a' | 'b', boolean>>\n  }>(testDirective<number, 'a' | 'b'>())\n})\n"
  },
  {
    "path": "packages-private/dts-test/extractProps.test-d.ts",
    "content": "import type { ExtractPropTypes, ExtractPublicPropTypes } from 'vue'\nimport { type Prettify, expectType } from './utils'\n\nconst propsOptions = {\n  foo: {\n    default: 1,\n  },\n  bar: {\n    type: String,\n    required: true,\n  },\n  baz: Boolean,\n  qux: Array,\n} as const\n\n// internal facing props\ndeclare const props: Prettify<ExtractPropTypes<typeof propsOptions>>\n\nexpectType<number>(props.foo)\nexpectType<string>(props.bar)\nexpectType<boolean>(props.baz)\nexpectType<unknown[] | undefined>(props.qux)\n\n// external facing props\ndeclare const publicProps: Prettify<ExtractPublicPropTypes<typeof propsOptions>>\n\nexpectType<number | undefined>(publicProps.foo)\nexpectType<string>(publicProps.bar)\nexpectType<boolean | undefined>(publicProps.baz)\nexpectType<unknown[] | undefined>(publicProps.qux)\n"
  },
  {
    "path": "packages-private/dts-test/functionalComponent.test-d.tsx",
    "content": "import {\n  type Component,\n  type FunctionalComponent,\n  Text,\n  type VNode,\n  h,\n} from 'vue'\nimport { expectType } from './utils'\n\n// simple function signature\nconst Foo = (props: { foo: number }) => h(Text, null, props.foo)\n\n// TSX\nexpectType<JSX.Element>(<Foo foo={1} />)\nexpectType<JSX.Element>(<Foo foo={1} key=\"1\" />)\nexpectType<JSX.Element>(<Foo foo={1} ref=\"ref\" />)\n// @ts-expect-error\n;<Foo />\n//  @ts-expect-error\n;<Foo foo=\"bar\" />\n//  @ts-expect-error\n;<Foo baz=\"bar\" />\n\n// Explicit signature with props + emits\nconst Bar: FunctionalComponent<\n  { foo: number },\n  { update: (value: number) => void }\n> = (props, { emit }) => {\n  expectType<number>(props.foo)\n\n  emit('update', 123)\n  //  @ts-expect-error\n  emit('nope')\n  //  @ts-expect-error\n  emit('update')\n  //  @ts-expect-error\n  emit('update', 'nope')\n}\n\n// assigning runtime options\nBar.props = {\n  foo: Number,\n}\n//  @ts-expect-error\nBar.props = { foo: String }\n\nBar.emits = {\n  update: value => value > 1,\n}\n//  @ts-expect-error\nBar.emits = { baz: () => void 0 }\n\n// TSX\nexpectType<JSX.Element>(<Bar foo={1} onUpdate={() => {}} />)\n//  @ts-expect-error\n;<Foo />\n//  @ts-expect-error\n;<Bar foo=\"bar\" />\n//  @ts-expect-error\n;<Foo baz=\"bar\" />\n\nconst Baz: FunctionalComponent<{}, string[]> = (props, { emit }) => {\n  expectType<{}>(props)\n  expectType<(event: string) => void>(emit)\n}\n\nexpectType<Component>(Baz)\n\nconst Qux: FunctionalComponent<{}, ['foo', 'bar']> = (props, { emit }) => {\n  emit('foo')\n  emit('foo', 1, 2)\n  emit('bar')\n  emit('bar', 1, 2)\n}\n\nexpectType<Component>(Qux)\n\nconst Quux: FunctionalComponent<\n  {},\n  {},\n  {\n    default: { foo: number }\n    optional?: { foo: number }\n  }\n> = (props, { emit, slots }) => {\n  expectType<{\n    default: (scope: { foo: number }) => VNode[]\n    optional?: (scope: { foo: number }) => VNode[]\n  }>(slots)\n\n  slots.default({ foo: 123 })\n  // @ts-expect-error\n  slots.default({ foo: 'fesf' })\n\n  slots.optional?.({ foo: 123 })\n  // @ts-expect-error\n  slots.optional?.({ foo: 'fesf' })\n  // @ts-expect-error\n  slots.optional({ foo: 123 })\n}\nexpectType<Component>(Quux)\n;<Quux />\n"
  },
  {
    "path": "packages-private/dts-test/h.test-d.ts",
    "content": "import {\n  type Component,\n  type DefineComponent,\n  Fragment,\n  type FunctionalComponent,\n  Suspense,\n  Teleport,\n  type VNode,\n  defineComponent,\n  h,\n  ref,\n  resolveComponent,\n} from 'vue'\nimport { describe, expectAssignable, expectType } from './utils'\n\ndescribe('h inference w/ element', () => {\n  // key\n  h('div', { key: 1 })\n  h('div', { key: 'foo' })\n  //  @ts-expect-error\n  h('div', { key: [] })\n  //  @ts-expect-error\n  h('div', { key: {} })\n  // ref\n  h('div', { ref: 'foo' })\n  h('div', { ref: ref(null) })\n  h('div', { ref: _el => {} })\n  //  @ts-expect-error\n  h('div', { ref: [] })\n  //  @ts-expect-error\n  h('div', { ref: {} })\n  //  @ts-expect-error\n  h('div', { ref: 123 })\n  // slots\n  const slots = { default: () => {} } // RawSlots\n  h('div', {}, slots)\n  // events\n  h('div', {\n    onClick: e => {\n      expectType<MouseEvent>(e)\n    },\n  })\n  h('input', {\n    onFocus(e) {\n      expectType<FocusEvent>(e)\n    },\n  })\n})\n\ndescribe('h inference w/ Fragment', () => {\n  // only accepts array children\n  h(Fragment, ['hello'])\n  h(Fragment, { key: 123 }, ['hello'])\n  // @ts-expect-error\n  h(Fragment, 'foo')\n  //  @ts-expect-error\n  h(Fragment, { key: 123 }, 'bar')\n})\n\ndescribe('h inference w/ Teleport', () => {\n  h(Teleport, { to: '#foo' }, 'hello')\n  h(Teleport, { to: '#foo' }, { default() {} })\n  // @ts-expect-error\n  h(Teleport)\n  // @ts-expect-error\n  h(Teleport, {})\n  // @ts-expect-error\n  h(Teleport, { to: '#foo' })\n})\n\ndescribe('h inference w/ Suspense', () => {\n  h(Suspense, { onRecede: () => {}, onResolve: () => {} }, 'hello')\n  h(Suspense, 'foo')\n  h(Suspense, () => 'foo')\n  h(Suspense, null, {\n    default: () => 'foo',\n  })\n  //  @ts-expect-error\n  h(Suspense, { onResolve: 1 })\n})\n\ndeclare const fc: FunctionalComponent<\n  {\n    foo: string\n    bar?: number\n    onClick: (evt: MouseEvent) => void\n  },\n  ['click'],\n  {\n    default: () => VNode\n    title: (scope: { id: number }) => VNode\n  }\n>\ndeclare const vnode: VNode\ndescribe('h inference w/ functional component', () => {\n  const Func = (_props: { foo: string; bar?: number }) => ''\n  h(Func, { foo: 'hello' })\n  h(Func, { foo: 'hello', bar: 123 })\n  //  @ts-expect-error\n  h(Func, { foo: 123 })\n  //  @ts-expect-error\n  h(Func, {})\n  //  @ts-expect-error\n  h(Func, { bar: 123 })\n\n  h(\n    fc,\n    { foo: 'hello', onClick: () => {} },\n    {\n      default: () => vnode,\n      title: ({ id }: { id: number }) => vnode,\n    },\n  )\n})\n\ndescribe('h support w/ plain object component', () => {\n  const Foo = {\n    props: {\n      foo: String,\n    },\n  }\n  h(Foo, { foo: 'ok' })\n  h(Foo, { foo: 'ok', class: 'extra' })\n  // no inference in this case\n})\n\ndescribe('h inference w/ defineComponent', () => {\n  const Foo = defineComponent({\n    props: {\n      foo: String,\n      bar: {\n        type: Number,\n        required: true,\n      },\n    },\n  })\n\n  h(Foo, { bar: 1 })\n  h(Foo, { bar: 1, foo: 'ok' })\n  // should allow extraneous props (attrs fallthrough)\n  h(Foo, { bar: 1, foo: 'ok', class: 'extra' })\n  // @ts-expect-error should fail on missing required prop\n  h(Foo, {})\n  //  @ts-expect-error\n  h(Foo, { foo: 'ok' })\n  // @ts-expect-error should fail on wrong type\n  h(Foo, { bar: 1, foo: 1 })\n})\n\n// describe('h inference w/ defineComponent + optional props', () => {\n//   const Foo = defineComponent({\n//     setup(_props: { foo?: string; bar: number }) {}\n//   })\n\n//   h(Foo, { bar: 1 })\n//   h(Foo, { bar: 1, foo: 'ok' })\n//   // should allow extraneous props (attrs fallthrough)\n//   h(Foo, { bar: 1, foo: 'ok', class: 'extra' })\n//   // @ts-expect-error should fail on missing required prop\n//   h(Foo, {})\n//   // @ts-expect-error\n//   h(Foo, { foo: 'ok' })\n//   // @ts-expect-error should fail on wrong type\n//   h(Foo, { bar: 1, foo: 1 })\n// })\n\n// describe('h inference w/ defineComponent + direct function', () => {\n//   const Foo = defineComponent((_props: { foo?: string; bar: number }) => {})\n\n//   h(Foo, { bar: 1 })\n//   h(Foo, { bar: 1, foo: 'ok' })\n//   // should allow extraneous props (attrs fallthrough)\n//   h(Foo, { bar: 1, foo: 'ok', class: 'extra' })\n//   // @ts-expect-error should fail on missing required prop\n//   h(Foo, {})\n//   //  @ts-expect-error\n//   h(Foo, { foo: 'ok' })\n//   // @ts-expect-error should fail on wrong type\n//   h(Foo, { bar: 1, foo: 1 })\n// })\n\n// #922 and #3218\ndescribe('h support for generic component type', () => {\n  function foo(bar: Component) {\n    h(bar)\n    h(bar, 'hello')\n    h(bar, { id: 'ok' }, 'hello')\n  }\n  foo({})\n})\n\n// #993\ndescribe('describeComponent extends Component', () => {\n  // functional\n  expectAssignable<Component>(\n    defineComponent((_props: { foo?: string; bar: number }) => () => {}),\n  )\n\n  // typed props\n  expectAssignable<Component>(defineComponent({}))\n\n  // prop arrays\n  expectAssignable<Component>(\n    defineComponent({\n      props: ['a', 'b'],\n    }),\n  )\n\n  // prop object\n  expectAssignable<Component>(\n    defineComponent({\n      props: {\n        foo: String,\n        bar: {\n          type: Number,\n          required: true,\n        },\n      },\n    }),\n  )\n})\n\n// #1385\ndescribe('component w/ props w/ default value', () => {\n  const MyComponent = defineComponent({\n    props: {\n      message: {\n        type: String,\n        default: 'hello',\n      },\n    },\n  })\n\n  h(MyComponent, {})\n})\n\n// #2338\ndescribe('Boolean prop implicit false', () => {\n  const MyComponent = defineComponent({\n    props: {\n      visible: Boolean,\n    },\n  })\n\n  h(MyComponent, {})\n\n  const RequiredComponent = defineComponent({\n    props: {\n      visible: {\n        type: Boolean,\n        required: true,\n      },\n    },\n  })\n\n  h(RequiredComponent, {\n    visible: true,\n  })\n  // @ts-expect-error\n  h(RequiredComponent, {})\n})\n\n// #2357\ndescribe('resolveComponent should work', () => {\n  h(resolveComponent('test'))\n  h(resolveComponent('test'), {\n    message: '1',\n  })\n})\n\n// #5431\ndescribe('h should work with multiple types', () => {\n  const serializers = {\n    Paragraph: 'p',\n    Component: {} as Component,\n    DefineComponent: {} as DefineComponent,\n  }\n\n  const sampleComponent = serializers['' as keyof typeof serializers]\n\n  h(sampleComponent)\n  h(sampleComponent, {})\n  h(sampleComponent, {}, [])\n})\n"
  },
  {
    "path": "packages-private/dts-test/inject.test-d.ts",
    "content": "import {\n  type InjectionKey,\n  type Ref,\n  createApp,\n  defineComponent,\n  inject,\n  provide,\n  ref,\n} from 'vue'\nimport { expectType } from './utils'\n\n// non-symbol keys\nprovide('foo', 123)\nprovide(123, 123)\n\nconst key: InjectionKey<number> = Symbol()\n\nprovide(key, 1)\n// @ts-expect-error\nprovide(key, 'foo')\n// @ts-expect-error\nprovide(key, null)\n\nexpectType<number | undefined>(inject(key))\nexpectType<number>(inject(key, 1))\nexpectType<number>(inject(key, () => 1, true /* treatDefaultAsFactory */))\n\nexpectType<() => number>(inject('foo', () => 1))\nexpectType<() => number>(inject('foo', () => 1, false))\nexpectType<number>(inject('foo', () => 1, true))\n\n// #8201\ntype Cube = {\n  size: number\n}\n\nconst injectionKeyRef = Symbol('key') as InjectionKey<Ref<Cube>>\n\n// @ts-expect-error\nprovide(injectionKeyRef, ref({}))\n\n// naive-ui: explicit provide type parameter\nprovide<Cube>('cube', { size: 123 })\nprovide<Cube>(123, { size: 123 })\nprovide<Cube>(injectionKeyRef, { size: 123 })\n\n// @ts-expect-error\nprovide<Cube>('cube', { size: 'foo' })\n// @ts-expect-error\nprovide<Cube>(123, { size: 'foo' })\n\n// #10602\nconst app = createApp({})\n// @ts-expect-error\napp.provide(injectionKeyRef, ref({}))\n\ndefineComponent({\n  provide: {\n    [injectionKeyRef]: { size: 'foo' },\n  },\n})\n"
  },
  {
    "path": "packages-private/dts-test/package.json",
    "content": "{\n  \"name\": \"dts-test\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"dependencies\": {\n    \"vue\": \"workspace:*\",\n    \"dts-built-test\": \"workspace:*\"\n  }\n}\n"
  },
  {
    "path": "packages-private/dts-test/reactivity.test-d.ts",
    "content": "import {\n  type Ref,\n  markRaw,\n  reactive,\n  readonly,\n  ref,\n  shallowReadonly,\n} from 'vue'\nimport { describe, expectType } from './utils'\n\ndescribe('should support DeepReadonly', () => {\n  const r = readonly({ obj: { k: 'v' } })\n  // @ts-expect-error\n  r.obj = {}\n  // @ts-expect-error\n  r.obj.k = 'x'\n})\n\n// #4180\ndescribe('readonly ref', () => {\n  const r = readonly(ref({ count: 1 }))\n  expectType<Ref>(r)\n})\n\ndescribe('should support markRaw', () => {\n  class Test<T> {\n    item = {} as Ref<T>\n  }\n  const test = new Test<number>()\n  const plain = {\n    ref: ref(1),\n  }\n\n  const r = reactive({\n    class: {\n      raw: markRaw(test),\n      reactive: test,\n    },\n    plain: {\n      raw: markRaw(plain),\n      reactive: plain,\n    },\n  })\n\n  expectType<Test<number>>(r.class.raw)\n  // @ts-expect-error it should unwrap\n  expectType<Test<number>>(r.class.reactive)\n\n  expectType<Ref<number>>(r.plain.raw.ref)\n  // @ts-expect-error it should unwrap\n  expectType<Ref<number>>(r.plain.reactive.ref)\n})\n\ndescribe('shallowReadonly ref unwrap', () => {\n  const r = shallowReadonly({ count: { n: ref(1) } })\n  // @ts-expect-error\n  r.count = 2\n  expectType<Ref>(r.count.n)\n  r.count.n.value = 123\n})\n\n// #3819\ndescribe('should unwrap tuple correctly', () => {\n  const readonlyTuple = [ref(0)] as const\n  const reactiveReadonlyTuple = reactive(readonlyTuple)\n  expectType<Ref<number>>(reactiveReadonlyTuple[0])\n\n  const tuple: [Ref<number>] = [ref(0)]\n  const reactiveTuple = reactive(tuple)\n  expectType<Ref<number>>(reactiveTuple[0])\n})\n\ndescribe('should unwrap Map correctly', () => {\n  const map = reactive(new Map<string, Ref<number>>())\n  expectType<Ref<number>>(map.get('a')!)\n\n  const map2 = reactive(new Map<string, { wrap: Ref<number> }>())\n  expectType<number>(map2.get('a')!.wrap)\n\n  const wm = reactive(new WeakMap<object, Ref<number>>())\n  expectType<Ref<number>>(wm.get({})!)\n\n  const wm2 = reactive(new WeakMap<object, { wrap: Ref<number> }>())\n  expectType<number>(wm2.get({})!.wrap)\n})\n\ndescribe('should unwrap extended Map correctly', () => {\n  class ExtendendMap1 extends Map<string, { wrap: Ref<number> }> {\n    foo = ref('foo')\n    bar = 1\n  }\n\n  const emap1 = reactive(new ExtendendMap1())\n  expectType<string>(emap1.foo)\n  expectType<number>(emap1.bar)\n  expectType<number>(emap1.get('a')!.wrap)\n})\n\ndescribe('should unwrap Set correctly', () => {\n  const set = reactive(new Set<Ref<number>>())\n  expectType<Set<Ref<number>>>(set)\n\n  const set2 = reactive(new Set<{ wrap: Ref<number> }>())\n  expectType<Set<{ wrap: number }>>(set2)\n\n  const ws = reactive(new WeakSet<Ref<number>>())\n  expectType<WeakSet<Ref<number>>>(ws)\n\n  const ws2 = reactive(new WeakSet<{ wrap: Ref<number> }>())\n  expectType<WeakSet<{ wrap: number }>>(ws2)\n})\n\ndescribe('should unwrap extended Set correctly', () => {\n  class ExtendendSet1 extends Set<{ wrap: Ref<number> }> {\n    foo = ref('foo')\n    bar = 1\n  }\n\n  const eset1 = reactive(new ExtendendSet1())\n  expectType<string>(eset1.foo)\n  expectType<number>(eset1.bar)\n})\n\ndescribe('should not error when assignment', () => {\n  const arr = reactive([''])\n  let record: Record<number, string>\n  record = arr\n  expectType<string>(record[0])\n  let record2: { [key: number]: string }\n  record2 = arr\n  expectType<string>(record2[0])\n})\n"
  },
  {
    "path": "packages-private/dts-test/ref.test-d.ts",
    "content": "import {\n  type ComputedRef,\n  type MaybeRef,\n  type MaybeRefOrGetter,\n  type Ref,\n  type ShallowRef,\n  type TemplateRef,\n  type ToRefs,\n  type WritableComputedRef,\n  computed,\n  isRef,\n  proxyRefs,\n  reactive,\n  readonly,\n  ref,\n  shallowReactive,\n  shallowRef,\n  toRef,\n  toRefs,\n  toValue,\n  unref,\n  useTemplateRef,\n} from 'vue'\nimport { type IsAny, type IsUnion, describe, expectType } from './utils'\n\nfunction plainType(arg: number | Ref<number>) {\n  // ref coercing\n  const coerced = ref(arg)\n  expectType<Ref<number>>(coerced)\n\n  // isRef as type guard\n  if (isRef(arg)) {\n    expectType<Ref<number>>(arg)\n  }\n\n  // ref unwrapping\n  expectType<number>(unref(arg))\n  expectType<number>(toValue(arg))\n  expectType<number>(toValue(() => 123))\n\n  // ref inner type should be unwrapped\n  const nestedRef = ref({\n    foo: ref(1),\n  })\n  expectType<{ foo: number }>(nestedRef.value)\n\n  // ref boolean\n  const falseRef = ref(false)\n  expectType<Ref<boolean>>(falseRef)\n  expectType<boolean>(falseRef.value)\n\n  // ref true\n  const trueRef = ref<true>(true)\n  expectType<Ref<true>>(trueRef)\n  expectType<true>(trueRef.value)\n\n  // tuple\n  expectType<[number, string]>(unref(ref([1, '1'])))\n\n  interface IteratorFoo {\n    [Symbol.iterator]: any\n  }\n\n  // with symbol\n  expectType<Ref<IteratorFoo | null | undefined>>(\n    ref<IteratorFoo | null | undefined>(),\n  )\n\n  // should not unwrap ref inside arrays\n  const arr = ref([1, new Map<string, any>(), ref('1')]).value\n  const value = arr[0]\n  if (isRef(value)) {\n    expectType<Ref>(value)\n  } else if (typeof value === 'number') {\n    expectType<number>(value)\n  } else {\n    // should narrow down to Map type\n    // and not contain any Ref type\n    expectType<Map<string, any>>(value)\n  }\n\n  // should still unwrap in objects nested in arrays\n  const arr2 = ref([{ a: ref(1) }]).value\n  expectType<number>(arr2[0].a)\n\n  // any value should return Ref<any>, not any\n  const a = ref(1 as any)\n  expectType<IsAny<typeof a>>(false)\n}\n\nplainType(1)\n\nfunction bailType(arg: HTMLElement | Ref<HTMLElement>) {\n  // ref coercing\n  const coerced = ref(arg)\n  expectType<Ref<HTMLElement>>(coerced)\n\n  // isRef as type guard\n  if (isRef(arg)) {\n    expectType<Ref<HTMLElement>>(arg)\n  }\n\n  // ref unwrapping\n  expectType<HTMLElement>(unref(arg))\n\n  // ref inner type should be unwrapped\n  const nestedRef = ref({ foo: ref(document.createElement('DIV')) })\n\n  expectType<Ref<{ foo: HTMLElement }>>(nestedRef)\n  expectType<{ foo: HTMLElement }>(nestedRef.value)\n}\nconst el = document.createElement('DIV')\nbailType(el)\n\nfunction withSymbol() {\n  const customSymbol = Symbol()\n  const obj = {\n    [Symbol.asyncIterator]: ref(1),\n    [Symbol.hasInstance]: { a: ref('a') },\n    [Symbol.isConcatSpreadable]: { b: ref(true) },\n    [Symbol.iterator]: [ref(1)],\n    [Symbol.match]: new Set<Ref<number>>(),\n    [Symbol.matchAll]: new Map<number, Ref<string>>(),\n    [Symbol.replace]: { arr: [ref('a')] },\n    [Symbol.search]: { set: new Set<Ref<number>>() },\n    [Symbol.species]: { map: new Map<number, Ref<string>>() },\n    [Symbol.split]: new WeakSet<Ref<boolean>>(),\n    [Symbol.toPrimitive]: new WeakMap<Ref<boolean>, string>(),\n    [Symbol.toStringTag]: { weakSet: new WeakSet<Ref<boolean>>() },\n    [Symbol.unscopables]: { weakMap: new WeakMap<Ref<boolean>, string>() },\n    [customSymbol]: { arr: [ref(1)] },\n  }\n\n  const objRef = ref(obj)\n\n  expectType<Ref<number>>(objRef.value[Symbol.asyncIterator])\n  expectType<{ a: Ref<string> }>(objRef.value[Symbol.hasInstance])\n  expectType<{ b: Ref<boolean> }>(objRef.value[Symbol.isConcatSpreadable])\n  expectType<Ref<number>[]>(objRef.value[Symbol.iterator])\n  expectType<Set<Ref<number>>>(objRef.value[Symbol.match])\n  expectType<Map<number, Ref<string>>>(objRef.value[Symbol.matchAll])\n  expectType<{ arr: Ref<string>[] }>(objRef.value[Symbol.replace])\n  expectType<{ set: Set<Ref<number>> }>(objRef.value[Symbol.search])\n  expectType<{ map: Map<number, Ref<string>> }>(objRef.value[Symbol.species])\n  expectType<WeakSet<Ref<boolean>>>(objRef.value[Symbol.split])\n  expectType<WeakMap<Ref<boolean>, string>>(objRef.value[Symbol.toPrimitive])\n  expectType<{ weakSet: WeakSet<Ref<boolean>> }>(\n    objRef.value[Symbol.toStringTag],\n  )\n  expectType<{ weakMap: WeakMap<Ref<boolean>, string> }>(\n    objRef.value[Symbol.unscopables],\n  )\n  expectType<{ arr: Ref<number>[] }>(objRef.value[customSymbol])\n}\n\nwithSymbol()\n\nconst state = reactive({\n  foo: {\n    value: 1,\n    label: 'bar',\n  },\n})\n\nexpectType<string>(state.foo.label)\n\ndescribe('ref with generic', <T extends { name: string }>() => {\n  const r = {} as T\n  const s = ref(r)\n  expectType<string>(s.value.name)\n\n  const rr = {} as MaybeRef<T>\n  // should at least allow casting\n  const ss = ref(rr) as Ref<T>\n  expectType<string>(ss.value.name)\n})\n\ndescribe('allow getter and setter types to be unrelated', <T>() => {\n  const a = { b: ref(0) }\n  const c = ref(a)\n  c.value = a\n\n  const d = {} as T\n  const e = ref(d)\n  e.value = d\n\n  const f = ref(ref(0))\n  expectType<number>(f.value)\n  // @ts-expect-error\n  f.value = ref(1)\n})\n\ndescribe('correctly unwraps nested refs', () => {\n  const obj = {\n    n: 24,\n    ref: ref(24),\n    nestedRef: ref({ n: ref(0) }),\n  }\n\n  const a = ref(obj)\n  expectType<number>(a.value.n)\n  expectType<number>(a.value.ref)\n  expectType<number>(a.value.nestedRef.n)\n\n  const b = reactive({ a })\n  expectType<number>(b.a.n)\n  expectType<number>(b.a.ref)\n  expectType<number>(b.a.nestedRef.n)\n})\n\n// computed\ndescribe('allow computed getter and setter types to be unrelated', () => {\n  const obj = ref({\n    name: 'foo',\n  })\n\n  const c = computed({\n    get() {\n      return JSON.stringify(obj.value)\n    },\n    set(val: typeof obj.value) {\n      obj.value = val\n    },\n  })\n\n  c.value = { name: 'bar' } // object\n\n  expectType<string>(c.value)\n})\n\ndescribe('Type safety for `WritableComputedRef` and `ComputedRef`', () => {\n  // @ts-expect-error\n  const writableComputed: WritableComputedRef<string> = computed(() => '')\n  // should allow\n  const immutableComputed: ComputedRef<string> = writableComputed\n  expectType<ComputedRef<string>>(immutableComputed)\n})\n\n// shallowRef\ntype Status = 'initial' | 'ready' | 'invalidating'\nconst shallowStatus = shallowRef<Status>('initial')\nif (shallowStatus.value === 'initial') {\n  expectType<Ref<Status>>(shallowStatus)\n  expectType<Status>(shallowStatus.value)\n  shallowStatus.value = 'invalidating'\n}\n\nconst refStatus = ref<Status>('initial')\nif (refStatus.value === 'initial') {\n  expectType<Ref<Status>>(shallowStatus)\n  expectType<Status>(shallowStatus.value)\n  refStatus.value = 'invalidating'\n}\n\n{\n  const shallow = shallowRef(1)\n  expectType<Ref<number>>(shallow)\n  expectType<ShallowRef<number>>(shallow)\n}\n\n{\n  //#7852\n  type Steps = { step: '1' } | { step: '2' }\n  const shallowUnionGenParam = shallowRef<Steps>({ step: '1' })\n  const shallowUnionAsCast = shallowRef({ step: '1' } as Steps)\n\n  expectType<IsUnion<typeof shallowUnionGenParam>>(false)\n  expectType<IsUnion<typeof shallowUnionAsCast>>(false)\n}\n\n{\n  // any value should return Ref<any>, not any\n  const a = shallowRef(1 as any)\n  expectType<IsAny<typeof a>>(false)\n}\n\ndescribe('shallowRef with generic', <T extends { name: string }>() => {\n  const r = {} as T\n  const s = shallowRef(r)\n  expectType<string>(s.value.name)\n  expectType<ShallowRef<T>>(shallowRef(r))\n\n  const rr = {} as MaybeRef<T>\n  // should at least allow casting\n  const ss = shallowRef(rr) as Ref<T> | ShallowRef<T>\n  expectType<string>(ss.value.name)\n})\n\n{\n  // should return ShallowRef<T> | Ref<T>, not ShallowRef<T | Ref<T>>\n  expectType<ShallowRef<{ name: string }> | Ref<{ name: string }>>(\n    shallowRef({} as MaybeRef<{ name: string }>),\n  )\n  expectType<ShallowRef<number> | Ref<string[]> | ShallowRef<string>>(\n    shallowRef('' as Ref<string[]> | string | number),\n  )\n}\n\n// proxyRefs: should return `reactive` directly\nconst r1 = reactive({\n  k: 'v',\n})\nconst p1 = proxyRefs(r1)\nexpectType<typeof r1>(p1)\n\n// proxyRefs: `ShallowUnwrapRef`\nconst r2 = {\n  a: ref(1),\n  c: computed(() => 1),\n  u: undefined,\n  obj: {\n    k: ref('foo'),\n  },\n  union: Math.random() > 0 - 5 ? ref({ name: 'yo' }) : null,\n}\nconst p2 = proxyRefs(r2)\nexpectType<number>(p2.a)\nexpectType<number>(p2.c)\nexpectType<undefined>(p2.u)\nexpectType<Ref<string>>(p2.obj.k)\nexpectType<{ name: string } | null>(p2.union)\n\n// toRef and toRefs\n{\n  const obj: {\n    a: number\n    b: Ref<number>\n    c: number | string\n  } = {\n    a: 1,\n    b: ref(1),\n    c: 1,\n  }\n\n  // toRef\n  expectType<Ref<number>>(toRef(obj, 'a'))\n  expectType<Ref<number>>(toRef(obj, 'b'))\n  // Should not distribute Refs over union\n  expectType<Ref<number | string>>(toRef(obj, 'c'))\n\n  expectType<Ref<number>>(toRef(() => 123))\n  expectType<Ref<number | string>>(toRef(() => obj.c))\n\n  const r = toRef(() => 123)\n  // @ts-expect-error\n  r.value = 234\n\n  // toRefs\n  expectType<{\n    a: Ref<number>\n    b: Ref<number>\n    // Should not distribute Refs over union\n    c: Ref<number | string>\n  }>(toRefs(obj))\n\n  // Both should not do any unwrapping\n  const someReactive = shallowReactive({\n    a: {\n      b: ref(42),\n    },\n  })\n\n  const toRefResult = toRef(someReactive, 'a')\n  const toRefsResult = toRefs(someReactive)\n\n  expectType<Ref<number>>(toRefResult.value.b)\n  expectType<Ref<number>>(toRefsResult.a.value.b)\n\n  // #5188\n  const props = { foo: 1 } as { foo: any }\n  const { foo } = toRefs(props)\n  expectType<Ref<any>>(foo)\n}\n\n// toRef default value\n{\n  const obj: { x?: number } = {}\n  const x = toRef(obj, 'x', 1)\n  expectType<Ref<number>>(x)\n}\n\n// readonly() + ref()\nexpectType<Readonly<Ref<number>>>(readonly(ref(1)))\n\n// #2687\ninterface AppData {\n  state: 'state1' | 'state2' | 'state3'\n}\n\nconst data: ToRefs<AppData> = toRefs(\n  reactive({\n    state: 'state1',\n  }),\n)\n\nswitch (data.state.value) {\n  case 'state1':\n    data.state.value = 'state2'\n    break\n  case 'state2':\n    data.state.value = 'state3'\n    break\n  case 'state3':\n    data.state.value = 'state1'\n    break\n}\n\n// #3954\nfunction testUnrefGenerics<T>(p: T | Ref<T>) {\n  expectType<T>(unref(p))\n}\n\ntestUnrefGenerics(1)\n\n// #4771\ndescribe('shallow reactive in reactive', () => {\n  const baz = reactive({\n    foo: shallowReactive({\n      a: {\n        b: ref(42),\n      },\n    }),\n  })\n\n  const foo = toRef(baz, 'foo')\n\n  expectType<Ref<number>>(foo.value.a.b)\n  expectType<number>(foo.value.a.b.value)\n})\n\ndescribe('shallow ref in reactive', () => {\n  const x = reactive({\n    foo: shallowRef({\n      bar: {\n        baz: ref(123),\n        qux: reactive({\n          z: ref(123),\n        }),\n      },\n    }),\n  })\n\n  expectType<Ref<number>>(x.foo.bar.baz)\n  expectType<number>(x.foo.bar.qux.z)\n})\n\ndescribe('ref in shallow ref', () => {\n  const x = shallowRef({\n    a: ref(123),\n  })\n\n  expectType<Ref<number>>(x.value.a)\n})\n\ndescribe('reactive in shallow ref', () => {\n  const x = shallowRef({\n    a: reactive({\n      b: ref(0),\n    }),\n  })\n\n  expectType<number>(x.value.a.b)\n})\n\ndescribe('toRef <-> toValue', () => {\n  function foo(\n    a: MaybeRef<string>,\n    b: () => string,\n    c: MaybeRefOrGetter<string>,\n    d: ComputedRef<string>,\n  ) {\n    const r = toRef(a)\n    expectType<Ref<string>>(r)\n    // writable\n    r.value = 'foo'\n\n    const rb = toRef(b)\n    expectType<Readonly<Ref<string>>>(rb)\n    // @ts-expect-error ref created from getter should be readonly\n    rb.value = 'foo'\n\n    const rc = toRef(c)\n    expectType<Readonly<Ref<string> | Ref<string>>>(rc)\n    // @ts-expect-error ref created from MaybeReadonlyRef should be readonly\n    rc.value = 'foo'\n\n    const rd = toRef(d)\n    expectType<ComputedRef<string>>(rd)\n    // @ts-expect-error ref created from computed ref should be readonly\n    rd.value = 'foo'\n\n    expectType<string>(toValue(a))\n    expectType<string>(toValue(b))\n    expectType<string>(toValue(c))\n    expectType<string>(toValue(d))\n\n    return {\n      r: toValue(r),\n      rb: toValue(rb),\n      rc: toValue(rc),\n      rd: toValue(rd),\n    }\n  }\n\n  expectType<{\n    r: string\n    rb: string\n    rc: string\n    rd: string\n  }>(\n    foo(\n      'foo',\n      () => 'bar',\n      ref('baz'),\n      computed(() => 'hi'),\n    ),\n  )\n})\n\n// unref\n// #8747\ndeclare const unref1: number | Ref<number> | ComputedRef<number>\nexpectType<number>(unref(unref1))\n\n// #11356\ndeclare const unref2:\n  | MaybeRef<string>\n  | ShallowRef<string>\n  | ComputedRef<string>\n  | WritableComputedRef<string>\nexpectType<string>(unref(unref2))\n\n// toValue\nexpectType<number>(toValue(unref1))\nexpectType<string>(toValue(unref2))\n\n// useTemplateRef\nconst tRef = useTemplateRef('foo')\nexpectType<TemplateRef>(tRef)\n\nconst tRef2 = useTemplateRef<HTMLElement>('bar')\nexpectType<TemplateRef<HTMLElement>>(tRef2)\n"
  },
  {
    "path": "packages-private/dts-test/scheduler.test-d.ts",
    "content": "import { nextTick } from 'vue'\nimport { describe, expectType } from './utils'\n\ndescribe('nextTick', async () => {\n  expectType<Promise<void>>(nextTick())\n  expectType<Promise<string>>(nextTick(() => 'foo'))\n  expectType<Promise<string>>(nextTick(() => Promise.resolve('foo')))\n  expectType<Promise<string>>(\n    nextTick(() => Promise.resolve(Promise.resolve('foo'))),\n  )\n\n  expectType<void>(await nextTick())\n  expectType<string>(await nextTick(() => 'foo'))\n  expectType<string>(await nextTick(() => Promise.resolve('foo')))\n  expectType<string>(\n    await nextTick(() => Promise.resolve(Promise.resolve('foo'))),\n  )\n\n  nextTick().then(value => {\n    expectType<void>(value)\n  })\n  nextTick(() => 'foo').then(value => {\n    expectType<string>(value)\n  })\n  nextTick(() => Promise.resolve('foo')).then(value => {\n    expectType<string>(value)\n  })\n  nextTick(() => Promise.resolve(Promise.resolve('foo'))).then(value => {\n    expectType<string>(value)\n  })\n})\n"
  },
  {
    "path": "packages-private/dts-test/setupHelpers.test-d.ts",
    "content": "import {\n  type Ref,\n  type Slots,\n  type VNode,\n  defineComponent,\n  defineEmits,\n  defineModel,\n  defineOptions,\n  defineProps,\n  defineSlots,\n  toRefs,\n  useAttrs,\n  useModel,\n  useSlots,\n  withDefaults,\n} from 'vue'\nimport { describe, expectType } from './utils'\n\ndescribe('defineProps w/ type declaration', () => {\n  // type declaration\n  const props = defineProps<{\n    foo: string\n    bool?: boolean\n    boolAndUndefined: boolean | undefined\n    file?: File | File[]\n  }>()\n  // explicitly declared type should be refined\n  expectType<string>(props.foo)\n  // @ts-expect-error\n  props.bar\n\n  expectType<boolean>(props.bool)\n  expectType<boolean>(props.boolAndUndefined)\n})\n\ndescribe('defineProps w/ never prop', () => {\n  const props = defineProps<{\n    foo?: never\n    bar: number\n  }>()\n\n  expectType<never | undefined>(props.foo)\n  expectType<number>(props.bar)\n})\n\ndescribe('defineProps w/ generics', () => {\n  function test<T extends boolean>() {\n    const props = defineProps<{ foo: T; bar: string; x?: boolean }>()\n    expectType<T>(props.foo)\n    expectType<string>(props.bar)\n    expectType<boolean>(props.x)\n  }\n  test()\n})\n\ndescribe('defineProps w/ type declaration + withDefaults', <T extends\n  string>() => {\n  const res = withDefaults(\n    defineProps<{\n      number?: number\n      arr?: string[]\n      obj?: { x: number }\n      fn?: (e: string) => void\n      genStr?: string\n      x?: string\n      y?: string\n      z?: string\n      bool?: boolean\n      boolAndUndefined: boolean | undefined\n      foo?: T\n    }>(),\n    {\n      number: 123,\n      arr: () => [],\n      obj: () => ({ x: 123 }),\n      fn: () => {},\n      genStr: () => '',\n      y: undefined,\n      z: 'string',\n      foo: '' as any,\n    },\n  )\n\n  res.number + 1\n  res.arr.push('hi')\n  res.obj.x\n  res.fn('hi')\n  res.genStr.slice()\n  // @ts-expect-error\n  res.x.slice()\n  // @ts-expect-error\n  res.y.slice()\n\n  expectType<string | undefined>(res.x)\n  expectType<string | undefined>(res.y)\n  expectType<string>(res.z)\n  expectType<T>(res.foo)\n\n  expectType<boolean>(res.bool)\n  expectType<boolean>(res.boolAndUndefined)\n})\n\ndescribe('defineProps w/ union type declaration + withDefaults', () => {\n  withDefaults(\n    defineProps<{\n      union1?: number | number[] | { x: number }\n      union2?: number | number[] | { x: number }\n      union3?: number | number[] | { x: number }\n      union4?: number | number[] | { x: number }\n    }>(),\n    {\n      union1: 123,\n      union2: () => [123],\n      union3: () => ({ x: 123 }),\n      union4: () => 123,\n    },\n  )\n})\n\ndescribe('defineProps w/ object union + withDefaults', () => {\n  const props = withDefaults(\n    defineProps<\n      {\n        foo: string\n      } & (\n        | {\n            type: 'hello'\n            bar: string\n          }\n        | {\n            type: 'world'\n            bar: number\n          }\n      )\n    >(),\n    {\n      foo: 'default value!',\n    },\n  )\n\n  expectType<\n    | {\n        readonly type: 'hello'\n        readonly bar: string\n        readonly foo: string\n      }\n    | {\n        readonly type: 'world'\n        readonly bar: number\n        readonly foo: string\n      }\n  >(props)\n})\n\ndescribe('defineProps w/ generic discriminate union + withDefaults', () => {\n  interface B {\n    b?: string\n  }\n  interface S<T> extends B {\n    mode: 'single'\n    v: T\n  }\n  interface M<T> extends B {\n    mode: 'multiple'\n    v: T[]\n  }\n  type Props = S<string> | M<string>\n  const props = withDefaults(defineProps<Props>(), {\n    b: 'b',\n  })\n\n  if (props.mode === 'single') {\n    expectType<string>(props.v)\n  }\n  if (props.mode === 'multiple') {\n    expectType<string[]>(props.v)\n  }\n})\n\ndescribe('defineProps w/ generic type declaration + withDefaults', <T extends\n  number, TA extends {\n  a: string\n}, TString extends string>() => {\n  const res = withDefaults(\n    defineProps<{\n      n?: number\n      bool?: boolean\n      s?: string\n\n      generic1?: T[] | { x: T }\n      generic2?: { x: T }\n      generic3?: TString\n      generic4?: TA\n    }>(),\n    {\n      n: 123,\n\n      generic1: () => [123, 33] as T[],\n      generic2: () => ({ x: 123 }) as { x: T },\n\n      generic3: () => 'test' as TString,\n      generic4: () => ({ a: 'test' }) as TA,\n    },\n  )\n\n  res.n + 1\n  // @ts-expect-error should be readonly\n  res.n++\n  // @ts-expect-error should be readonly\n  res.s = ''\n\n  expectType<T[] | { x: T }>(res.generic1)\n  expectType<{ x: T }>(res.generic2)\n  expectType<TString>(res.generic3)\n  expectType<TA>(res.generic4)\n\n  expectType<boolean>(res.bool)\n})\n\ndescribe('withDefaults w/ boolean type', () => {\n  const res1 = withDefaults(\n    defineProps<{\n      bool?: boolean\n    }>(),\n    { bool: false },\n  )\n  expectType<boolean>(res1.bool)\n\n  const res2 = withDefaults(\n    defineProps<{\n      bool?: boolean\n    }>(),\n    {\n      bool: undefined,\n    },\n  )\n  expectType<boolean | undefined>(res2.bool)\n})\n\ndescribe('withDefaults w/ defineProp type is different from the defaults type', () => {\n  const res1 = withDefaults(\n    defineProps<{\n      bool?: boolean\n    }>(),\n    { bool: false, value: false },\n  )\n  expectType<boolean>(res1.bool)\n\n  // @ts-expect-error\n  res1.value\n})\n\ndescribe('withDefaults w/ defineProp discriminate union type', () => {\n  const props = withDefaults(\n    defineProps<\n      { type: 'button'; buttonType?: 'submit' } | { type: 'link'; href: string }\n    >(),\n    {\n      type: 'button',\n    },\n  )\n  if (props.type === 'button') {\n    expectType<'submit' | undefined>(props.buttonType)\n  }\n  if (props.type === 'link') {\n    expectType<string>(props.href)\n  }\n})\n\ndescribe('defineProps w/ runtime declaration', () => {\n  // runtime declaration\n  const props = defineProps({\n    foo: String,\n    bar: {\n      type: Number,\n      default: 1,\n    },\n    baz: {\n      type: Array,\n      required: true,\n    },\n  })\n  expectType<{\n    foo?: string\n    bar: number\n    baz: unknown[]\n  }>(props)\n\n  props.foo && props.foo + 'bar'\n  props.bar + 1\n  // @ts-expect-error should be readonly\n  props.bar++\n  props.baz.push(1)\n\n  const props2 = defineProps(['foo', 'bar'])\n  props2.foo + props2.bar\n  // @ts-expect-error\n  props2.baz\n})\n\ndescribe('defineEmits w/ type declaration', () => {\n  const emit = defineEmits<(e: 'change') => void>()\n  emit('change')\n  // @ts-expect-error\n  emit()\n  // @ts-expect-error\n  emit('bar')\n\n  type Emits = { (e: 'foo' | 'bar'): void; (e: 'baz', id: number): void }\n  const emit2 = defineEmits<Emits>()\n\n  emit2('foo')\n  emit2('bar')\n  emit2('baz', 123)\n  // @ts-expect-error\n  emit2('baz')\n})\n\ndescribe('defineEmits w/ interface declaration', () => {\n  interface Emits {\n    foo: [value: string]\n  }\n  const emit = defineEmits<Emits>()\n  emit('foo', 'hi')\n})\n\ndescribe('defineEmits w/ alt type declaration', () => {\n  const emit = defineEmits<{\n    foo: [id: string]\n    bar: any[]\n    baz: []\n  }>()\n\n  emit('foo', 'hi')\n  // @ts-expect-error\n  emit('foo')\n\n  emit('bar')\n  emit('bar', 1, 2, 3)\n\n  emit('baz')\n  // @ts-expect-error\n  emit('baz', 1)\n})\n\ndescribe('defineEmits w/ runtime declaration', () => {\n  const emit = defineEmits({\n    foo: () => {},\n    bar: null,\n  })\n  emit('foo')\n  emit('bar', 123)\n  // @ts-expect-error\n  emit('baz')\n\n  const emit2 = defineEmits(['foo', 'bar'])\n  emit2('foo')\n  emit2('bar', 123)\n  // @ts-expect-error\n  emit2('baz')\n})\n\ndescribe('defineSlots', () => {\n  // literal fn syntax (allow for specifying return type)\n  const fnSlots = defineSlots<{\n    default(props: { foo: string; bar: number }): any\n    optional?(props: string): any\n  }>()\n  expectType<(scope: { foo: string; bar: number }) => VNode[]>(fnSlots.default)\n  expectType<undefined | ((scope: string) => VNode[])>(fnSlots.optional)\n\n  const slotsUntype = defineSlots()\n  expectType<Slots>(slotsUntype)\n})\n\ndescribe('defineSlots generic', <T extends Record<string, any>>() => {\n  const props = defineProps<{\n    item: T\n  }>()\n\n  const slots = defineSlots<\n    {\n      [K in keyof T as `slot-${K & string}`]?: (props: { item: T }) => any\n    } & {\n      label?: (props: { item: T }) => any\n    }\n  >()\n\n  for (const key of Object.keys(props.item) as (keyof T & string)[]) {\n    slots[`slot-${String(key)}`]?.({\n      item: props.item,\n    })\n  }\n  slots.label?.({ item: props.item })\n\n  // @ts-expect-error calling wrong slot\n  slots.foo({})\n})\n\ndescribe('defineModel', () => {\n  // overload 1\n  const modelValueRequired = defineModel<boolean>({ required: true })\n  expectType<Ref<boolean>>(modelValueRequired)\n\n  // overload 2\n  const modelValue = defineModel<string>()\n  expectType<Ref<string | undefined>>(modelValue)\n  modelValue.value = 'new value'\n\n  const modelValueDefault = defineModel<boolean>({ default: true })\n  expectType<Ref<boolean>>(modelValueDefault)\n\n  // overload 3\n  const countRequired = defineModel<number>('count', { required: false })\n  expectType<Ref<number | undefined>>(countRequired)\n\n  // overload 4\n  const count = defineModel<number>('count')\n  expectType<Ref<number | undefined>>(count)\n\n  const countDefault = defineModel<number>('count', { default: 1 })\n  expectType<Ref<number>>(countDefault)\n\n  // infer type from default\n  const inferred = defineModel({ default: 123 })\n  expectType<Ref<number | undefined>>(inferred)\n  const inferredRequired = defineModel({ default: 123, required: true })\n  expectType<Ref<number>>(inferredRequired)\n\n  // modifiers\n  const [_, modifiers] = defineModel<string>()\n  expectType<true | undefined>(modifiers.foo)\n\n  // limit supported modifiers\n  const [__, typedModifiers] = defineModel<string, 'trim' | 'capitalize'>()\n  expectType<true | undefined>(typedModifiers.trim)\n  expectType<true | undefined>(typedModifiers.capitalize)\n  // @ts-expect-error\n  typedModifiers.foo\n\n  // transformers with type\n  defineModel<string>({\n    get(val) {\n      return val.toLowerCase()\n    },\n    set(val) {\n      return val.toUpperCase()\n    },\n  })\n  // transformers with runtime type\n  defineModel({\n    type: String,\n    get(val) {\n      return val.toLowerCase()\n    },\n    set(val) {\n      return val.toUpperCase()\n    },\n  })\n\n  // @ts-expect-error type / default mismatch\n  defineModel<string>({ default: 123 })\n  // @ts-expect-error unknown props option\n  defineModel({ foo: 123 })\n\n  // unrelated getter and setter types\n  {\n    const modelVal = defineModel({\n      get(_: string[]): string {\n        return ''\n      },\n      set(_: number) {\n        return 1\n      },\n    })\n    expectType<string | undefined>(modelVal.value)\n    modelVal.value = 1\n    modelVal.value = undefined\n    // @ts-expect-error\n    modelVal.value = 'foo'\n\n    const [modelVal2] = modelVal\n    expectType<string | undefined>(modelVal2.value)\n    modelVal2.value = 1\n    modelVal2.value = undefined\n    // @ts-expect-error\n    modelVal.value = 'foo'\n\n    const count = defineModel('count', {\n      get(_: string[]): string {\n        return ''\n      },\n      set(_: number) {\n        return ''\n      },\n    })\n    expectType<string | undefined>(count.value)\n    count.value = 1\n    count.value = undefined\n    // @ts-expect-error\n    count.value = 'foo'\n\n    const [count2] = count\n    expectType<string | undefined>(count2.value)\n    count2.value = 1\n    count2.value = undefined\n    // @ts-expect-error\n    count2.value = 'foo'\n  }\n})\n\ndescribe('useModel', () => {\n  defineComponent({\n    props: ['foo'],\n    setup(props) {\n      const r = useModel(props, 'foo')\n      expectType<Ref<any>>(r)\n\n      // @ts-expect-error\n      useModel(props, 'bar')\n    },\n  })\n\n  defineComponent({\n    props: {\n      foo: String,\n      bar: { type: Number, required: true },\n      baz: { type: Boolean },\n    },\n    setup(props) {\n      expectType<Ref<string | undefined>>(useModel(props, 'foo'))\n      expectType<Ref<number>>(useModel(props, 'bar'))\n      expectType<Ref<boolean>>(useModel(props, 'baz'))\n    },\n  })\n})\n\ndescribe('useAttrs', () => {\n  const attrs = useAttrs()\n  expectType<Record<string, unknown>>(attrs)\n})\n\ndescribe('useSlots', () => {\n  const slots = useSlots()\n  expectType<Slots>(slots)\n})\n\ndescribe('defineSlots generic', <T extends Record<string, any>>() => {\n  const props = defineProps<{\n    item: T\n  }>()\n\n  const slots = defineSlots<\n    {\n      [K in keyof T as `slot-${K & string}`]?: (props: { item: T }) => any\n    } & {\n      label?: (props: { item: T }) => any\n    }\n  >()\n\n  // @ts-expect-error slots should be readonly\n  slots.label = () => {}\n\n  // @ts-expect-error non existing slot\n  slots['foo-asdas']?.({\n    item: props.item,\n  })\n  for (const key in props.item) {\n    slots[`slot-${String(key)}`]?.({\n      item: props.item,\n    })\n    slots[`slot-${String(key as keyof T)}`]?.({\n      item: props.item,\n    })\n  }\n\n  for (const key of Object.keys(props.item) as (keyof T)[]) {\n    slots[`slot-${String(key)}`]?.({\n      item: props.item,\n    })\n  }\n  slots.label?.({ item: props.item })\n\n  // @ts-expect-error calling wrong slot\n  slots.foo({})\n})\n\ndescribe('defineSlots generic strict', <T extends {\n  foo: 'foo'\n  bar: 'bar'\n}>() => {\n  const props = defineProps<{\n    item: T\n  }>()\n\n  const slots = defineSlots<\n    {\n      [K in keyof T as `slot-${K & string}`]?: (props: { item: T }) => any\n    } & {\n      label?: (props: { item: T }) => any\n    }\n  >()\n\n  // slot-bar/foo should be automatically inferred\n  slots['slot-bar']?.({ item: props.item })\n  slots['slot-foo']?.({ item: props.item })\n\n  slots.label?.({ item: props.item })\n\n  // @ts-expect-error not part of the extends\n  slots['slot-RANDOM']?.({ item: props.item })\n\n  // @ts-expect-error slots should be readonly\n  slots.label = () => {}\n\n  // @ts-expect-error calling wrong slot\n  slots.foo({})\n})\n\n// #6420\ndescribe('toRefs w/ type declaration', () => {\n  const props = defineProps<{\n    file?: File | File[]\n  }>()\n  expectType<Ref<File | File[] | undefined>>(toRefs(props).file)\n})\n\ndescribe('defineOptions', () => {\n  defineOptions({\n    name: 'MyComponent',\n    inheritAttrs: true,\n  })\n\n  defineOptions({\n    // @ts-expect-error props should be defined via defineProps()\n    props: ['props'],\n    // @ts-expect-error emits should be defined via defineEmits()\n    emits: ['emits'],\n    // @ts-expect-error slots should be defined via defineSlots()\n    slots: { default: 'default' },\n    // @ts-expect-error expose should be defined via defineExpose()\n    expose: ['expose'],\n  })\n})\n"
  },
  {
    "path": "packages-private/dts-test/tsconfig.test.json",
    "content": "{\n  \"compilerOptions\": {\n    \"noEmit\": true,\n    \"jsx\": \"preserve\",\n    \"module\": \"esnext\",\n    \"strict\": true,\n    \"moduleResolution\": \"node\",\n    \"lib\": [\"esnext\", \"dom\"]\n  },\n  \"include\": [\"./*\"]\n}\n"
  },
  {
    "path": "packages-private/dts-test/tsx.test-d.tsx",
    "content": "// TSX w/ defineComponent is tested in defineComponent.test-d.tsx\nimport {\n  Fragment,\n  KeepAlive,\n  Suspense,\n  Teleport,\n  type VNode,\n  useAttrs,\n} from 'vue'\nimport { expectType } from './utils'\n\nexpectType<VNode>(<div />)\nexpectType<JSX.Element>(<div />)\nexpectType<JSX.Element>(<div id=\"foo\" />)\nexpectType<JSX.Element>(<div>hello</div>)\nexpectType<JSX.Element>(<input value=\"foo\" />)\nexpectType<JSX.Element>(<textarea value={null} />)\n\n// @ts-expect-error style css property validation\n;<div style={{ unknown: 123 }} />\n\n// allow array styles and nested array styles\nexpectType<JSX.Element>(<div style={[{ color: 'red' }]} />)\nexpectType<JSX.Element>(\n  <div style={[{ color: 'red' }, [{ fontSize: '1em' }]]} />,\n)\n\n// allow undefined, string, object, array and nested array classes\nexpectType<JSX.Element>(<div class={undefined} />)\nexpectType<JSX.Element>(<div class={'foo'} />)\nexpectType<JSX.Element>(<div class={['foo', undefined, 'bar']} />)\nexpectType<JSX.Element>(<div class={[]} />)\nexpectType<JSX.Element>(<div class={['foo', ['bar'], [['baz']]]} />)\nexpectType<JSX.Element>(<div class={{ foo: true, bar: false, baz: true }} />)\nexpectType<JSX.Element>(<div class={{}} />)\nexpectType<JSX.Element>(\n  <div class={['foo', ['bar'], { baz: true }, [{ qux: true }]]} />,\n)\nexpectType<JSX.Element>(\n  <div\n    class={[\n      { foo: false },\n      { bar: 0 },\n      { baz: -0 },\n      { qux: '' },\n      { quux: null },\n      { corge: undefined },\n      { grault: NaN },\n    ]}\n  />,\n)\nexpectType<JSX.Element>(\n  <div\n    class={[\n      { foo: true },\n      { bar: 'not-empty' },\n      { baz: 1 },\n      { qux: {} },\n      { quux: [] },\n    ]}\n  />,\n)\n\n// allow class/style passthrough from attrs\nconst attrs = useAttrs()\nexpectType<JSX.Element>(<div class={attrs.class} />)\nexpectType<JSX.Element>(<div style={attrs.style} />)\n\n// @ts-expect-error invalid class value\n;<div class={0} />\n\n// #7955\nexpectType<JSX.Element>(<div style={[undefined, '', null, false]} />)\n\nexpectType<JSX.Element>(<div style={undefined} />)\n\nexpectType<JSX.Element>(<div style={null} />)\n\nexpectType<JSX.Element>(<div style={''} />)\n\nexpectType<JSX.Element>(<div style={false} />)\n\n// @ts-expect-error\n;<div style={[0]} />\n\n// @ts-expect-error\n;<div style={0} />\n\n// @ts-expect-error unknown prop\n;<div foo=\"bar\" />\n\n// allow key/ref on arbitrary element\nexpectType<JSX.Element>(<div key=\"foo\" />)\nexpectType<JSX.Element>(<div ref=\"bar\" />)\n\nexpectType<JSX.Element>(\n  <input\n    onInput={e => {\n      // infer correct event type\n      expectType<EventTarget | null>(e.target)\n    }}\n  />,\n)\n\n// built-in types\nexpectType<JSX.Element>(<Fragment />)\nexpectType<JSX.Element>(<Fragment key=\"1\" />)\n\nexpectType<JSX.Element>(<Teleport to=\"#foo\" />)\nexpectType<JSX.Element>(<Teleport to=\"#foo\" key=\"1\" />)\n\n// @ts-expect-error\n;<Teleport />\n// @ts-expect-error\n;<Teleport to={1} />\n\n// KeepAlive\nexpectType<JSX.Element>(<KeepAlive include=\"foo\" exclude={['a']} />)\nexpectType<JSX.Element>(<KeepAlive key=\"1\" />)\n// @ts-expect-error\n;<KeepAlive include={123} />\n\n// Suspense\nexpectType<JSX.Element>(<Suspense />)\nexpectType<JSX.Element>(<Suspense key=\"1\" />)\nexpectType<JSX.Element>(\n  <Suspense onResolve={() => {}} onFallback={() => {}} onPending={() => {}} />,\n)\n// @ts-expect-error\n;<Suspense onResolve={123} />\n\n// svg\nexpectType<JSX.Element>(\n  <svg\n    xmlnsXlink=\"http://www.w3.org/1999/xlink\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n  />,\n)\n// details\nexpectType<JSX.Element>(<details name=\"details\" />)\n"
  },
  {
    "path": "packages-private/dts-test/utils.d.ts",
    "content": "// This directory contains a number of d.ts assertions\n// use \\@ts-expect-error where errors are expected.\n\n// register global JSX\nimport 'vue/jsx'\n\nexport function describe(_name: string, _fn: () => void): void\nexport function test(_name: string, _fn: () => any): void\n\nexport function expectType<T>(value: T): void\nexport function expectAssignable<T, T2 extends T = T>(value: T2): void\n\nexport type IsUnion<T, U extends T = T> = (\n  T extends any ? (U extends T ? false : true) : never\n) extends false\n  ? false\n  : true\n\nexport type IsAny<T> = 0 extends 1 & T ? true : false\n\nexport type Prettify<T> = { [K in keyof T]: T[K] } & {}\n"
  },
  {
    "path": "packages-private/dts-test/watch.test-d.ts",
    "content": "import {\n  type ComputedRef,\n  type MaybeRef,\n  type Ref,\n  computed,\n  defineComponent,\n  defineModel,\n  reactive,\n  ref,\n  shallowRef,\n  watch,\n} from 'vue'\nimport { expectType } from './utils'\n\nconst source = ref('foo')\nconst source2 = computed(() => source.value)\nconst source3 = () => 1\n\ntype Bar = Ref<string> | ComputedRef<string> | (() => number)\ntype Foo = readonly [Ref<string>, ComputedRef<string>, () => number]\ntype OnCleanup = (fn: () => void) => void\n\nconst readonlyArr: Foo = [source, source2, source3]\n\n// lazy watcher will have consistent types for oldValue.\nwatch(source, (value, oldValue, onCleanup) => {\n  expectType<string>(value)\n  expectType<string>(oldValue)\n  expectType<OnCleanup>(onCleanup)\n})\n\nwatch([source, source2, source3], (values, oldValues) => {\n  expectType<[string, string, number]>(values)\n  expectType<[string, string, number]>(oldValues)\n})\n\n// const array\nwatch([source, source2, source3] as const, (values, oldValues) => {\n  expectType<Readonly<[string, string, number]>>(values)\n  expectType<Readonly<[string, string, number]>>(oldValues)\n})\n\n// reactive array\nwatch(reactive([source, source2, source3]), (value, oldValues) => {\n  expectType<Bar[]>(value)\n  expectType<Bar[]>(oldValues)\n})\n\n// reactive w/ readonly tuple\nwatch(reactive([source, source2, source3] as const), (value, oldValues) => {\n  expectType<Foo>(value)\n  expectType<Foo>(oldValues)\n})\n\n// readonly array\nwatch(readonlyArr, (values, oldValues) => {\n  expectType<Readonly<[string, string, number]>>(values)\n  expectType<Readonly<[string, string, number]>>(oldValues)\n})\n\n// no type error, case from vueuse\ndeclare const aAny: any\nwatch(aAny, (v, ov) => {})\nwatch(aAny, (v, ov) => {}, { immediate: true })\n\n// immediate watcher's oldValue will be undefined on first run.\nwatch(\n  source,\n  (value, oldValue) => {\n    expectType<string>(value)\n    expectType<string | undefined>(oldValue)\n  },\n  { immediate: true },\n)\n\nwatch(\n  [source, source2, source3],\n  (values, oldValues) => {\n    expectType<[string, string, number]>(values)\n    expectType<[string | undefined, string | undefined, number | undefined]>(\n      oldValues,\n    )\n  },\n  { immediate: true },\n)\n\n// const array\nwatch(\n  [source, source2, source3] as const,\n  (values, oldValues) => {\n    expectType<Readonly<[string, string, number]>>(values)\n    expectType<\n      Readonly<[string | undefined, string | undefined, number | undefined]>\n    >(oldValues)\n  },\n  { immediate: true },\n)\n\n// reactive array\nwatch(\n  reactive([source, source2, source3]),\n  (value, oldVals) => {\n    expectType<Bar[]>(value)\n    expectType<Bar[] | undefined>(oldVals)\n  },\n  { immediate: true },\n)\n\n// reactive w/ readonly tuple\nwatch(reactive([source, source2, source3] as const), (value, oldVals) => {\n  expectType<Foo>(value)\n  expectType<Foo | undefined>(oldVals)\n})\n\n// readonly array\nwatch(\n  readonlyArr,\n  (values, oldValues) => {\n    expectType<Readonly<[string, string, number]>>(values)\n    expectType<\n      Readonly<[string | undefined, string | undefined, number | undefined]>\n    >(oldValues)\n  },\n  { immediate: true },\n)\n\n// should provide correct ref.value inner type to callbacks\nconst nestedRefSource = ref({\n  foo: ref(1),\n})\n\nwatch(nestedRefSource, (v, ov) => {\n  expectType<{ foo: number }>(v)\n  expectType<{ foo: number }>(ov)\n})\n\nconst someRef = ref({ test: 'test' })\nconst otherRef = ref({ a: 'b' })\nwatch([someRef, otherRef], values => {\n  const value1 = values[0]\n  // no type error\n  console.log(value1.test)\n\n  const value2 = values[1]\n  // no type error\n  console.log(value2.a)\n})\n\n// #6135\ndefineComponent({\n  data() {\n    return { a: 1 }\n  },\n  created() {\n    this.$watch(\n      () => this.a,\n      (v, ov, onCleanup) => {\n        expectType<number>(v)\n        expectType<number>(ov)\n        expectType<OnCleanup>(onCleanup)\n      },\n    )\n  },\n})\n\n{\n  //#7852\n  type Steps = { step: '1' } | { step: '2' }\n  const shallowUnionGenParam = shallowRef<Steps>({ step: '1' })\n  const shallowUnionAsCast = shallowRef({ step: '1' } as Steps)\n\n  watch(shallowUnionGenParam, value => {\n    expectType<Steps>(value)\n  })\n  watch(shallowUnionAsCast, value => {\n    expectType<Steps>(value)\n  })\n}\n\n{\n  // defineModel\n  const bool = defineModel({ default: false })\n  watch(bool, value => {\n    expectType<boolean>(value)\n  })\n\n  const bool1 = defineModel<boolean>()\n  watch(bool1, value => {\n    expectType<boolean | undefined>(value)\n  })\n\n  const msg = defineModel<string>({ required: true })\n  watch(msg, value => {\n    expectType<string>(value)\n  })\n\n  const arr = defineModel<string[]>({ required: true })\n  watch(arr, value => {\n    expectType<string[]>(value)\n  })\n\n  const obj = defineModel<{ foo: string }>({ required: true })\n  watch(obj, value => {\n    expectType<{ foo: string }>(value)\n  })\n}\n\n{\n  const css: MaybeRef<string> = ''\n  watch(ref(css), value => {\n    expectType<string>(value)\n  })\n}\n"
  },
  {
    "path": "packages-private/global.d.ts",
    "content": "/// <reference types=\"vite/client\" />\n\n// Global compile-time constants\ndeclare var __COMMIT__: string\n\ndeclare module 'file-saver' {\n  export function saveAs(blob: any, name: any): void\n}\n"
  },
  {
    "path": "packages-private/sfc-playground/README.md",
    "content": "# SFC Playground\n\nThis is continuously deployed at [https://play.vuejs.org](https://play.vuejs.org).\n\n## Run Locally in Dev\n\nIn repo root:\n\n```sh\npnpm dev-sfc\n```\n\n## Build for Prod\n\nIn repo root\n\n```sh\npnpm build-sfc-playground\n```\n"
  },
  {
    "path": "packages-private/sfc-playground/index.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    <link rel=\"icon\" type=\"image/svg\" href=\"/logo.svg\" />\n    <title>Vue SFC Playground</title>\n    <script>\n      const savedPreferDark = localStorage.getItem(\n        'vue-sfc-playground-prefer-dark',\n      )\n      if (\n        savedPreferDark === 'true' ||\n        (!savedPreferDark &&\n          window.matchMedia('(prefers-color-scheme: dark)').matches)\n      ) {\n        document.documentElement.classList.add('dark')\n      }\n    </script>\n    <script type=\"module\" src=\"/src/main.ts\"></script>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n  </body>\n</html>\n"
  },
  {
    "path": "packages-private/sfc-playground/package.json",
    "content": "{\n  \"name\": \"@vue/sfc-playground\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"serve\": \"vite preview\"\n  },\n  \"devDependencies\": {\n    \"@vitejs/plugin-vue\": \"catalog:\",\n    \"vite\": \"catalog:\"\n  },\n  \"dependencies\": {\n    \"@vue/repl\": \"^4.7.1\",\n    \"file-saver\": \"^2.0.5\",\n    \"jszip\": \"^3.10.1\",\n    \"vue\": \"workspace:*\"\n  }\n}\n"
  },
  {
    "path": "packages-private/sfc-playground/src/App.vue",
    "content": "<script setup lang=\"ts\">\nimport Header from './Header.vue'\nimport { Repl, useStore, SFCOptions, useVueImportMap } from '@vue/repl'\nimport Monaco from '@vue/repl/monaco-editor'\nimport { ref, watchEffect, onMounted, computed, watch } from 'vue'\n\nconst replRef = ref<InstanceType<typeof Repl>>()\n\nconst setVH = () => {\n  document.documentElement.style.setProperty('--vh', window.innerHeight + `px`)\n}\nwindow.addEventListener('resize', setVH)\nsetVH()\n\nconst useSSRMode = ref(false)\n\nconst AUTO_SAVE_STORAGE_KEY = 'vue-sfc-playground-auto-save'\nconst initAutoSave: boolean = JSON.parse(\n  localStorage.getItem(AUTO_SAVE_STORAGE_KEY) ?? 'true',\n)\nconst autoSave = ref(initAutoSave)\n\nconst { productionMode, vueVersion, importMap } = useVueImportMap({\n  runtimeDev: import.meta.env.PROD\n    ? `${location.origin}/vue.runtime.esm-browser.js`\n    : `${location.origin}/src/vue-dev-proxy`,\n  runtimeProd: import.meta.env.PROD\n    ? `${location.origin}/vue.runtime.esm-browser.prod.js`\n    : `${location.origin}/src/vue-dev-proxy-prod`,\n  serverRenderer: import.meta.env.PROD\n    ? `${location.origin}/server-renderer.esm-browser.js`\n    : `${location.origin}/src/vue-server-renderer-dev-proxy`,\n})\n\nlet hash = location.hash.slice(1)\nif (hash.startsWith('__DEV__')) {\n  hash = hash.slice(7)\n  productionMode.value = false\n}\nif (hash.startsWith('__PROD__')) {\n  hash = hash.slice(8)\n  productionMode.value = true\n}\nif (hash.startsWith('__SSR__')) {\n  hash = hash.slice(7)\n  useSSRMode.value = true\n}\n\n// enable experimental features\nconst sfcOptions = computed(\n  (): SFCOptions => ({\n    script: {\n      inlineTemplate: productionMode.value,\n      isProd: productionMode.value,\n      propsDestructure: true,\n    },\n    style: {\n      isProd: productionMode.value,\n    },\n    template: {\n      isProd: productionMode.value,\n      compilerOptions: {\n        isCustomElement: (tag: string) =>\n          tag === 'mjx-container' || tag.startsWith('custom-'),\n      },\n    },\n  }),\n)\n\nconst store = useStore(\n  {\n    builtinImportMap: importMap,\n    vueVersion,\n    sfcOptions,\n  },\n  hash,\n)\n// @ts-expect-error\nglobalThis.store = store\n\n// persist state\nwatchEffect(() => {\n  const newHash = store\n    .serialize()\n    .replace(/^#/, useSSRMode.value ? `#__SSR__` : `#`)\n    .replace(/^#/, productionMode.value ? `#__PROD__` : `#`)\n  history.replaceState({}, '', newHash)\n})\n\nfunction toggleProdMode() {\n  productionMode.value = !productionMode.value\n}\n\nfunction toggleSSR() {\n  useSSRMode.value = !useSSRMode.value\n}\n\nfunction toggleAutoSave() {\n  autoSave.value = !autoSave.value\n  localStorage.setItem(AUTO_SAVE_STORAGE_KEY, String(autoSave.value))\n}\n\nfunction reloadPage() {\n  replRef.value?.reload()\n}\n\nconst theme = ref<'dark' | 'light'>('dark')\nfunction toggleTheme(isDark: boolean) {\n  theme.value = isDark ? 'dark' : 'light'\n}\nonMounted(() => {\n  const cls = document.documentElement.classList\n  toggleTheme(cls.contains('dark'))\n\n  // @ts-expect-error process shim for old versions of @vue/compiler-sfc dependency\n  window.process = { env: {} }\n})\n\nconst isVaporSupported = ref(false)\nwatch(\n  () => store.vueVersion,\n  (version, oldVersion) => {\n    const [major, minor] = (version || store.compiler.version)\n      .split('.')\n      .map((v: string) => parseInt(v, 10))\n    isVaporSupported.value = major > 3 || (major === 3 && minor >= 6)\n    if (oldVersion) reloadPage()\n  },\n  { immediate: true, flush: 'pre' },\n)\n\nconst previewOptions = computed(() => ({\n  customCode: {\n    importCode: `import { initCustomFormatter${isVaporSupported.value ? ', vaporInteropPlugin' : ''} } from 'vue'`,\n    useCode: `\n      ${isVaporSupported.value ? 'app.use(vaporInteropPlugin)' : ''}\n      if (window.devtoolsFormatters) {\n        const index = window.devtoolsFormatters.findIndex((v) => v.__vue_custom_formatter)\n        window.devtoolsFormatters.splice(index, 1)\n        initCustomFormatter()\n      } else {\n        initCustomFormatter()\n      }`,\n  },\n}))\n</script>\n\n<template>\n  <Header\n    :store=\"store\"\n    :prod=\"productionMode\"\n    :ssr=\"useSSRMode\"\n    :autoSave=\"autoSave\"\n    :theme=\"theme\"\n    @toggle-theme=\"toggleTheme\"\n    @toggle-prod=\"toggleProdMode\"\n    @toggle-ssr=\"toggleSSR\"\n    @toggle-autosave=\"toggleAutoSave\"\n    @reload-page=\"reloadPage\"\n  />\n  <Repl\n    ref=\"replRef\"\n    :theme=\"theme\"\n    :editor=\"Monaco\"\n    @keydown.ctrl.s.prevent\n    @keydown.meta.s.prevent\n    :ssr=\"useSSRMode\"\n    :model-value=\"autoSave\"\n    :editorOptions=\"{ autoSaveText: false }\"\n    :store=\"store\"\n    :showCompileOutput=\"true\"\n    :showSsrOutput=\"useSSRMode\"\n    :showOpenSourceMap=\"true\"\n    :autoResize=\"true\"\n    :clearConsole=\"false\"\n    :preview-options=\"previewOptions\"\n  />\n</template>\n\n<style>\n.dark {\n  color-scheme: dark;\n}\n\nbody {\n  font-size: 13px;\n  font-family:\n    -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu,\n    Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;\n  margin: 0;\n  --base: #444;\n  --nav-height: 50px;\n}\n\n.vue-repl {\n  height: calc(var(--vh) - var(--nav-height)) !important;\n}\n\nbutton {\n  border: none;\n  outline: none;\n  cursor: pointer;\n  margin: 0;\n  background-color: transparent;\n}\n</style>\n"
  },
  {
    "path": "packages-private/sfc-playground/src/Header.vue",
    "content": "<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport type { ReplStore } from '@vue/repl'\nimport { downloadProject } from './download/download'\nimport Sun from './icons/Sun.vue'\nimport Moon from './icons/Moon.vue'\nimport Share from './icons/Share.vue'\nimport Download from './icons/Download.vue'\nimport GitHub from './icons/GitHub.vue'\nimport Reload from './icons/Reload.vue'\nimport VersionSelect from './VersionSelect.vue'\n\nconst props = defineProps<{\n  store: ReplStore\n  prod: boolean\n  ssr: boolean\n  autoSave: boolean\n  theme: 'dark' | 'light'\n}>()\nconst emit = defineEmits([\n  'toggle-theme',\n  'toggle-ssr',\n  'toggle-prod',\n  'toggle-autosave',\n  'reload-page',\n])\n\nconst { store } = props\n\nconst currentCommit = __COMMIT__\n\nconst vueVersion = computed(() => {\n  if (store.loading) {\n    return 'loading...'\n  }\n  return store.vueVersion || `@${__COMMIT__}`\n})\n\nasync function setVueVersion(v: string) {\n  store.vueVersion = v\n}\n\nfunction resetVueVersion() {\n  store.vueVersion = null\n}\n\nasync function copyLink(e: MouseEvent) {\n  if (e.metaKey) {\n    resetVueVersion()\n    // hidden logic for going to local debug from play.vuejs.org\n    window.location.href = 'http://localhost:5173/' + window.location.hash\n    return\n  }\n  await navigator.clipboard.writeText(location.href)\n  alert('Sharable URL has been copied to clipboard.')\n}\n\nfunction toggleDark() {\n  const cls = document.documentElement.classList\n  cls.toggle('dark')\n  localStorage.setItem(\n    'vue-sfc-playground-prefer-dark',\n    String(cls.contains('dark')),\n  )\n  emit('toggle-theme', cls.contains('dark'))\n}\n</script>\n\n<template>\n  <nav>\n    <h1>\n      <img alt=\"logo\" src=\"/logo.svg\" />\n      <span>Vue SFC Playground</span>\n    </h1>\n    <div class=\"links\">\n      <VersionSelect\n        v-model=\"store.typescriptVersion\"\n        pkg=\"typescript\"\n        label=\"TypeScript Version\"\n      />\n      <VersionSelect\n        :model-value=\"vueVersion\"\n        @update:model-value=\"setVueVersion\"\n        pkg=\"vue\"\n        label=\"Vue Version\"\n      >\n        <li :class=\"{ active: vueVersion === `@${currentCommit}` }\">\n          <a @click=\"resetVueVersion\">This Commit ({{ currentCommit }})</a>\n        </li>\n        <li>\n          <a\n            href=\"https://app.netlify.com/sites/vue-sfc-playground/deploys\"\n            target=\"_blank\"\n            >Commits History</a\n          >\n        </li>\n      </VersionSelect>\n      <button\n        title=\"Toggle development production mode\"\n        class=\"toggle-prod\"\n        :class=\"{ prod }\"\n        @click=\"$emit('toggle-prod')\"\n      >\n        <span>{{ prod ? 'PROD' : 'DEV' }}</span>\n      </button>\n      <button\n        title=\"Toggle server rendering mode\"\n        class=\"toggle-ssr\"\n        :class=\"{ enabled: ssr }\"\n        @click=\"$emit('toggle-ssr')\"\n      >\n        <span>{{ ssr ? 'SSR ON' : 'SSR OFF' }}</span>\n      </button>\n      <button\n        title=\"Toggle editor auto save mode\"\n        class=\"toggle-autosave\"\n        :class=\"{ enabled: autoSave }\"\n        @click=\"$emit('toggle-autosave')\"\n      >\n        <span>{{ autoSave ? 'AutoSave ON' : 'AutoSave OFF' }}</span>\n      </button>\n      <button\n        :title=\"`Switch to ${theme === 'dark' ? 'light' : 'dark'} theme`\"\n        class=\"toggle-dark\"\n        @click=\"toggleDark\"\n      >\n        <Sun class=\"light\" />\n        <Moon class=\"dark\" />\n      </button>\n      <button title=\"Copy sharable URL\" class=\"share\" @click=\"copyLink\">\n        <Share />\n      </button>\n      <button title=\"Reload page\" class=\"reload\" @click=\"$emit('reload-page')\">\n        <Reload />\n      </button>\n      <button\n        title=\"Download project files\"\n        class=\"download\"\n        @click=\"downloadProject(store)\"\n      >\n        <Download />\n      </button>\n      <a\n        href=\"https://github.com/vuejs/core/tree/main/packages-private/sfc-playground\"\n        target=\"_blank\"\n        title=\"View on GitHub\"\n        class=\"github\"\n      >\n        <GitHub />\n      </a>\n    </div>\n  </nav>\n</template>\n\n<style>\nnav {\n  --bg: #fff;\n  --bg-light: #fff;\n  --border: #ddd;\n  --btn: #666;\n  --highlight: #333;\n  --green: #3ca877;\n  --purple: #904cbc;\n  --btn-bg: #eee;\n\n  color: var(--base);\n  height: var(--nav-height);\n  box-sizing: border-box;\n  padding: 0 1em;\n  background-color: var(--bg);\n  box-shadow: 0 0 4px rgba(0, 0, 0, 0.33);\n  position: relative;\n  display: flex;\n  justify-content: space-between;\n}\n\n.dark nav {\n  --base: #ddd;\n  --bg: #1a1a1a;\n  --bg-light: #242424;\n  --border: #383838;\n  --highlight: #fff;\n  --btn-bg: #333;\n\n  box-shadow: none;\n  border-bottom: 1px solid var(--border);\n}\n\nh1 {\n  font-weight: 500;\n  display: inline-flex;\n  place-items: center;\n}\n\nh1 img {\n  height: 24px;\n  margin-right: 10px;\n}\n\n@media (max-width: 560px) {\n  h1 span {\n    font-size: 0.9em;\n  }\n}\n\n@media (max-width: 520px) {\n  h1 span {\n    display: none;\n  }\n}\n\n.links {\n  display: flex;\n}\n\n.toggle-prod span,\n.toggle-ssr span,\n.toggle-autosave span {\n  font-size: 12px;\n  border-radius: 4px;\n  padding: 4px 6px;\n}\n\n.toggle-prod span {\n  background: var(--green);\n  color: #fff;\n}\n\n.toggle-prod.prod span {\n  background: var(--purple);\n}\n\n.toggle-ssr span,\n.toggle-autosave span {\n  background-color: var(--btn-bg);\n}\n\n.toggle-ssr.enabled span,\n.toggle-autosave.enabled span {\n  color: #fff;\n  background-color: var(--green);\n}\n\n.toggle-dark svg {\n  width: 18px;\n  height: 18px;\n}\n\n.toggle-dark .dark,\n.dark .toggle-dark .light {\n  display: none;\n}\n\n.dark .toggle-dark .dark {\n  display: inline-block;\n}\n\n.links button,\n.links .github {\n  padding: 1px 6px;\n  color: var(--btn);\n}\n\n.links button:hover,\n.links .github:hover {\n  color: var(--highlight);\n}\n\n.version:hover .active-version::after {\n  border-top-color: var(--btn);\n}\n\n.dark .version:hover .active-version::after {\n  border-top-color: var(--highlight);\n}\n\n.versions {\n  display: none;\n  position: absolute;\n  left: 0;\n  top: 40px;\n  background-color: var(--bg-light);\n  border: 1px solid var(--border);\n  border-radius: 4px;\n  list-style-type: none;\n  padding: 8px;\n  margin: 0;\n  width: 200px;\n  max-height: calc(100vh - 70px);\n  overflow: scroll;\n}\n\n.versions a {\n  display: block;\n  padding: 6px 12px;\n  text-decoration: none;\n  cursor: pointer;\n  color: var(--base);\n}\n\n.versions a:hover {\n  color: var(--green);\n}\n\n.versions.expanded {\n  display: block;\n}\n\n.links > * {\n  display: flex;\n  align-items: center;\n}\n\n.links > * + * {\n  margin-left: 4px;\n}\n</style>\n"
  },
  {
    "path": "packages-private/sfc-playground/src/VersionSelect.vue",
    "content": "<script setup lang=\"ts\">\nimport { onMounted, ref } from 'vue'\nimport Copy from './icons/Copy.vue'\n\nconst expanded = ref(false)\nconst versions = ref<string[]>()\n\nconst version = defineModel()\nconst props = defineProps<{\n  pkg: string\n  label: string\n}>()\n\nasync function toggle() {\n  expanded.value = !expanded.value\n  if (!versions.value) {\n    versions.value = await fetchVersions()\n  }\n}\n\nasync function fetchVersions(): Promise<string[]> {\n  const res = await fetch(\n    `https://data.jsdelivr.com/v1/package/npm/${props.pkg}`,\n  )\n  const { versions } = (await res.json()) as { versions: string[] }\n\n  if (props.pkg === 'vue') {\n    // if the latest version is a pre-release, list all current pre-releases\n    // otherwise filter out pre-releases\n    let isInPreRelease = versions[0].includes('-')\n    const filteredVersions: string[] = []\n    for (const v of versions) {\n      if (v.includes('-')) {\n        if (isInPreRelease) {\n          filteredVersions.push(v)\n        }\n      } else {\n        filteredVersions.push(v)\n        isInPreRelease = false\n      }\n      if (filteredVersions.length >= 30 || v === '3.0.10') {\n        break\n      }\n    }\n    return filteredVersions\n  } else if (props.pkg === 'typescript') {\n    return versions.filter(v => !v.includes('dev') && !v.includes('insiders'))\n  }\n  return versions\n}\n\nfunction setVersion(v: string) {\n  version.value = v\n  expanded.value = false\n}\n\nfunction copyVersion(v: string) {\n  window.navigator.clipboard.writeText(v).then(() => {\n    alert('Vue version has been copied to clipboard.')\n  })\n}\n\nonMounted(() => {\n  window.addEventListener('click', () => {\n    expanded.value = false\n  })\n  window.addEventListener('blur', () => {\n    if (document.activeElement?.tagName === 'IFRAME') {\n      expanded.value = false\n    }\n  })\n})\n</script>\n\n<template>\n  <div class=\"version\" @click.stop>\n    <span class=\"active-version\" @click=\"toggle\">\n      {{ label }}\n      <span class=\"number\">{{ version }}</span>\n    </span>\n\n    <ul class=\"versions\" :class=\"{ expanded }\">\n      <li v-if=\"!versions\"><a>loading versions...</a></li>\n      <li\n        v-for=\"(ver, index) of versions\"\n        class=\"versions-item\"\n        :class=\"{\n          active: ver === version || (version === 'latest' && index === 0),\n        }\"\n      >\n        <a @click=\"setVersion(ver)\">v{{ ver }}</a>\n        <button\n          title=\"Copy Version\"\n          class=\"version-copy\"\n          @click=\"copyVersion(`v${ver}`)\"\n        >\n          <Copy />\n        </button>\n      </li>\n      <div @click=\"expanded = false\">\n        <slot />\n      </div>\n    </ul>\n  </div>\n</template>\n\n<style>\n.version {\n  z-index: 1;\n  margin-right: 12px;\n  position: relative;\n}\n\n.active-version {\n  cursor: pointer;\n  position: relative;\n  display: inline-flex;\n  place-items: center;\n}\n\n.active-version .number {\n  color: var(--green);\n  margin-left: 4px;\n}\n\n.active-version::after {\n  content: '';\n  width: 0;\n  height: 0;\n  border-left: 4px solid transparent;\n  border-right: 4px solid transparent;\n  border-top: 6px solid #aaa;\n  margin-left: 8px;\n}\n\n.versions .active a {\n  color: var(--green);\n}\n\n.versions .versions-item {\n  display: flex;\n  justify-content: space-between;\n}\n\n.versions .versions-item .version-copy {\n  display: none;\n}\n\n.versions .versions-item:hover .version-copy {\n  display: block;\n}\n</style>\n"
  },
  {
    "path": "packages-private/sfc-playground/src/download/download.ts",
    "content": "import { saveAs } from 'file-saver'\n\nimport index from './template/index.html?raw'\nimport main from './template/main.js?raw'\nimport pkg from './template/package.json?raw'\nimport config from './template/vite.config.js?raw'\nimport readme from './template/README.md?raw'\nimport type { ReplStore } from '@vue/repl'\n\nexport async function downloadProject(store: ReplStore) {\n  if (!confirm('Download project files?')) {\n    return\n  }\n\n  const { default: JSZip } = await import('jszip')\n  const zip = new JSZip()\n\n  // basic structure\n  zip.file('index.html', index)\n  zip.file(\n    'package.json',\n    pkg.replace(`\"vue\": \"latest\"`, `\"vue\": \"${store.vueVersion || 'latest'}\"`),\n  )\n  zip.file('vite.config.js', config)\n  zip.file('README.md', readme)\n\n  // project src\n  const src = zip.folder('src')!\n  src.file('main.js', main)\n\n  const files = store.getFiles()\n  for (const file in files) {\n    if (file !== 'import-map.json' && file !== 'tsconfig.json') {\n      src.file(file, files[file])\n    } else {\n      zip.file(file, files[file])\n    }\n  }\n\n  const blob = await zip.generateAsync({ type: 'blob' })\n  saveAs(blob, 'vue-project.zip')\n}\n"
  },
  {
    "path": "packages-private/sfc-playground/src/download/template/README.md",
    "content": "# Vite Vue Starter\n\nThis is a project template using [Vite](https://vitejs.dev/). It requires [Node.js](https://nodejs.org) version 18+ or 20+.\n\nTo start:\n\n```sh\nnpm install\nnpm run dev\n\n# if using yarn:\nyarn\nyarn dev\n\n# if using pnpm:\npnpm install\npnpm run dev\n```\n"
  },
  {
    "path": "packages-private/sfc-playground/src/download/template/index.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>Vite App</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-private/sfc-playground/src/download/template/main.js",
    "content": "import { createApp } from 'vue'\nimport App from './App.vue'\n\ncreateApp(App).mount('#app')\n"
  },
  {
    "path": "packages-private/sfc-playground/src/download/template/package.json",
    "content": "{\n  \"name\": \"vite-vue-starter\",\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"serve\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"vue\": \"latest\"\n  },\n  \"devDependencies\": {\n    \"@vitejs/plugin-vue\": \"^6.0.4\",\n    \"vite\": \"^7.3.1\"\n  }\n}\n"
  },
  {
    "path": "packages-private/sfc-playground/src/download/template/vite.config.js",
    "content": "import { defineConfig } from 'vite'\nimport vue from '@vitejs/plugin-vue'\n\n// https://vitejs.dev/config/\nexport default defineConfig({\n  plugins: [vue()],\n})\n"
  },
  {
    "path": "packages-private/sfc-playground/src/icons/Copy.vue",
    "content": "<template>\n  <svg\n    xmlns=\"http://www.w3.org/2000/svg\"\n    width=\"1.3em\"\n    height=\"1.3em\"\n    viewBox=\"0 0 24 24\"\n  >\n    <path fill=\"currentColor\" d=\"M8 7h11v14H8z\" opacity=\".3\" />\n    <path\n      fill=\"currentColor\"\n      d=\"M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2m0 16H8V7h11z\"\n    />\n  </svg>\n</template>\n"
  },
  {
    "path": "packages-private/sfc-playground/src/icons/Download.vue",
    "content": "<template>\n  <svg width=\"1.7em\" height=\"1.7em\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n    <g>\n      <rect x=\"4\" y=\"18\" width=\"16\" height=\"2\" rx=\"1\" ry=\"1\" />\n      <rect\n        x=\"3\"\n        y=\"17\"\n        width=\"4\"\n        height=\"2\"\n        rx=\"1\"\n        ry=\"1\"\n        transform=\"rotate(-90 5 18)\"\n      />\n      <rect\n        x=\"17\"\n        y=\"17\"\n        width=\"4\"\n        height=\"2\"\n        rx=\"1\"\n        ry=\"1\"\n        transform=\"rotate(-90 19 18)\"\n      />\n      <path\n        d=\"M12 15a1 1 0 0 1-.58-.18l-4-2.82a1 1 0 0 1-.24-1.39a1 1 0 0 1 1.4-.24L12 12.76l3.4-2.56a1 1 0 0 1 1.2 1.6l-4 3a1 1 0 0 1-.6.2z\"\n      />\n      <path d=\"M12 13a1 1 0 0 1-1-1V4a1 1 0 0 1 2 0v8a1 1 0 0 1-1 1z\" />\n    </g>\n  </svg>\n</template>\n"
  },
  {
    "path": "packages-private/sfc-playground/src/icons/GitHub.vue",
    "content": "<template>\n  <svg width=\"1.7em\" height=\"1.7em\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n    <path\n      d=\"M10.9,2.1c-4.6,0.5-8.3,4.2-8.8,8.7c-0.5,4.7,2.2,8.9,6.3,10.5C8.7,21.4,9,21.2,9,20.8v-1.6c0,0-0.4,0.1-0.9,0.1 c-1.4,0-2-1.2-2.1-1.9c-0.1-0.4-0.3-0.7-0.6-1C5.1,16.3,5,16.3,5,16.2C5,16,5.3,16,5.4,16c0.6,0,1.1,0.7,1.3,1c0.5,0.8,1.1,1,1.4,1 c0.4,0,0.7-0.1,0.9-0.2c0.1-0.7,0.4-1.4,1-1.8c-2.3-0.5-4-1.8-4-4c0-1.1,0.5-2.2,1.2-3C7.1,8.8,7,8.3,7,7.6C7,7.2,7,6.6,7.3,6 c0,0,1.4,0,2.8,1.3C10.6,7.1,11.3,7,12,7s1.4,0.1,2,0.3C15.3,6,16.8,6,16.8,6C17,6.6,17,7.2,17,7.6c0,0.8-0.1,1.2-0.2,1.4 c0.7,0.8,1.2,1.8,1.2,3c0,2.2-1.7,3.5-4,4c0.6,0.5,1,1.4,1,2.3v2.6c0,0.3,0.3,0.6,0.7,0.5c3.7-1.5,6.3-5.1,6.3-9.3 C22,6.1,16.9,1.4,10.9,2.1z\"\n    />\n  </svg>\n</template>\n"
  },
  {
    "path": "packages-private/sfc-playground/src/icons/Moon.vue",
    "content": "<template>\n  <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\">\n    <path\n      fill=\"currentColor\"\n      d=\"M12.1,22c-0.3,0-0.6,0-0.9,0c-5.5-0.5-9.5-5.4-9-10.9c0.4-4.8,4.2-8.6,9-9c0.4,0,0.8,0.2,1,0.5c0.2,0.3,0.2,0.8-0.1,1.1c-2,2.7-1.4,6.4,1.3,8.4c2.1,1.6,5,1.6,7.1,0c0.3-0.2,0.7-0.3,1.1-0.1c0.3,0.2,0.5,0.6,0.5,1c-0.2,2.7-1.5,5.1-3.6,6.8C16.6,21.2,14.4,22,12.1,22zM9.3,4.4c-2.9,1-5,3.6-5.2,6.8c-0.4,4.4,2.8,8.3,7.2,8.7c2.1,0.2,4.2-0.4,5.8-1.8c1.1-0.9,1.9-2.1,2.4-3.4c-2.5,0.9-5.3,0.5-7.5-1.1C9.2,11.4,8.1,7.7,9.3,4.4z\"\n    />\n  </svg>\n</template>\n"
  },
  {
    "path": "packages-private/sfc-playground/src/icons/Reload.vue",
    "content": "<template>\n  <svg\n    fill=\"currentColor\"\n    width=\"1.7em\"\n    height=\"1.7em\"\n    viewBox=\"0 0 24 24\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n  >\n    <path\n      d=\"M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z\"\n    />\n    <path d=\"M0 0h24v24H0z\" fill=\"none\" />\n  </svg>\n</template>\n"
  },
  {
    "path": "packages-private/sfc-playground/src/icons/Share.vue",
    "content": "<template>\n  <svg width=\"1.4em\" height=\"1.4em\" viewBox=\"0 0 24 24\">\n    <g\n      fill=\"none\"\n      stroke=\"currentColor\"\n      stroke-width=\"2\"\n      stroke-linecap=\"round\"\n      stroke-linejoin=\"round\"\n    >\n      <circle cx=\"18\" cy=\"5\" r=\"3\" />\n      <circle cx=\"6\" cy=\"12\" r=\"3\" />\n      <circle cx=\"18\" cy=\"19\" r=\"3\" />\n      <path d=\"M8.59 13.51l6.83 3.98\" />\n      <path d=\"M15.41 6.51l-6.82 3.98\" />\n    </g>\n  </svg>\n</template>\n"
  },
  {
    "path": "packages-private/sfc-playground/src/icons/Sun.vue",
    "content": "<template>\n  <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\">\n    <path\n      fill=\"currentColor\"\n      d=\"M12,18c-3.3,0-6-2.7-6-6s2.7-6,6-6s6,2.7,6,6S15.3,18,12,18zM12,8c-2.2,0-4,1.8-4,4c0,2.2,1.8,4,4,4c2.2,0,4-1.8,4-4C16,9.8,14.2,8,12,8z\"\n    />\n    <path\n      fill=\"currentColor\"\n      d=\"M12,4c-0.6,0-1-0.4-1-1V1c0-0.6,0.4-1,1-1s1,0.4,1,1v2C13,3.6,12.6,4,12,4z\"\n    />\n    <path\n      fill=\"currentColor\"\n      d=\"M12,24c-0.6,0-1-0.4-1-1v-2c0-0.6,0.4-1,1-1s1,0.4,1,1v2C13,23.6,12.6,24,12,24z\"\n    />\n    <path\n      fill=\"currentColor\"\n      d=\"M5.6,6.6c-0.3,0-0.5-0.1-0.7-0.3L3.5,4.9c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l1.4,1.4c0.4,0.4,0.4,1,0,1.4C6.2,6.5,5.9,6.6,5.6,6.6z\"\n    />\n    <path\n      fill=\"currentColor\"\n      d=\"M19.8,20.8c-0.3,0-0.5-0.1-0.7-0.3l-1.4-1.4c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l1.4,1.4c0.4,0.4,0.4,1,0,1.4C20.3,20.7,20,20.8,19.8,20.8z\"\n    />\n    <path\n      fill=\"currentColor\"\n      d=\"M3,13H1c-0.6,0-1-0.4-1-1s0.4-1,1-1h2c0.6,0,1,0.4,1,1S3.6,13,3,13z\"\n    />\n    <path\n      fill=\"currentColor\"\n      d=\"M23,13h-2c-0.6,0-1-0.4-1-1s0.4-1,1-1h2c0.6,0,1,0.4,1,1S23.6,13,23,13z\"\n    />\n    <path\n      fill=\"currentColor\"\n      d=\"M4.2,20.8c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l1.4-1.4c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-1.4,1.4C4.7,20.7,4.5,20.8,4.2,20.8z\"\n    />\n    <path\n      fill=\"currentColor\"\n      d=\"M18.4,6.6c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l1.4-1.4c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-1.4,1.4C18.9,6.5,18.6,6.6,18.4,6.6z\"\n    />\n  </svg>\n</template>\n"
  },
  {
    "path": "packages-private/sfc-playground/src/main.ts",
    "content": "import { createApp } from 'vue'\nimport App from './App.vue'\n\n// @ts-expect-error Custom window property\nwindow.VUE_DEVTOOLS_CONFIG = {\n  defaultSelectedAppId: 'repl',\n}\n\ncreateApp(App).mount('#app')\n"
  },
  {
    "path": "packages-private/sfc-playground/src/vue-dev-proxy-prod.ts",
    "content": "// serve vue to the iframe sandbox during dev.\nexport * from 'vue/dist/vue.runtime.esm-browser.prod.js'\n"
  },
  {
    "path": "packages-private/sfc-playground/src/vue-dev-proxy.ts",
    "content": "// serve vue to the iframe sandbox during dev.\nexport * from 'vue'\n"
  },
  {
    "path": "packages-private/sfc-playground/src/vue-server-renderer-dev-proxy.ts",
    "content": "// serve vue/server-renderer to the iframe sandbox during dev.\nexport * from 'vue/server-renderer'\n"
  },
  {
    "path": "packages-private/sfc-playground/vercel.json",
    "content": "{\n  \"github\": {\n    \"silent\": true\n  },\n  \"headers\": [\n    {\n      \"source\": \"/assets/(.*)\",\n      \"headers\": [\n        {\n          \"key\": \"Cache-Control\",\n          \"value\": \"max-age=31536000, immutable\"\n        }\n      ]\n    }\n  ]\n}\n"
  },
  {
    "path": "packages-private/sfc-playground/vite.config.ts",
    "content": "import fs from 'node:fs'\nimport path from 'node:path'\nimport { type Plugin, defineConfig } from 'vite'\nimport vue from '@vitejs/plugin-vue'\nimport { spawnSync } from 'node:child_process'\n\nconst commit = spawnSync('git', ['rev-parse', '--short=7', 'HEAD'])\n  .stdout.toString()\n  .trim()\n\nexport default defineConfig({\n  plugins: [\n    vue({\n      script: {\n        fs: {\n          fileExists: fs.existsSync,\n          readFile: file => fs.readFileSync(file, 'utf-8'),\n        },\n      },\n    }),\n    copyVuePlugin(),\n  ],\n  define: {\n    __COMMIT__: JSON.stringify(commit),\n    __VUE_PROD_DEVTOOLS__: JSON.stringify(true),\n  },\n  optimizeDeps: {\n    exclude: ['@vue/repl'],\n  },\n})\n\nfunction copyVuePlugin(): Plugin {\n  return {\n    name: 'copy-vue',\n    generateBundle() {\n      const copyFile = (file: string) => {\n        const filePath = path.resolve(__dirname, '../../packages', file)\n        const basename = path.basename(file)\n        if (!fs.existsSync(filePath)) {\n          throw new Error(\n            `${basename} not built. ` +\n              `Run \"nr build vue -f esm-browser\" first.`,\n          )\n        }\n        this.emitFile({\n          type: 'asset',\n          fileName: basename,\n          source: fs.readFileSync(filePath, 'utf-8'),\n        })\n      }\n\n      copyFile(`vue/dist/vue.esm-browser.js`)\n      copyFile(`vue/dist/vue.esm-browser.prod.js`)\n      copyFile(`vue/dist/vue.runtime.esm-browser.js`)\n      copyFile(`vue/dist/vue.runtime.esm-browser.prod.js`)\n      copyFile(`server-renderer/dist/server-renderer.esm-browser.js`)\n    },\n  }\n}\n"
  },
  {
    "path": "packages-private/template-explorer/README.md",
    "content": "## Template Explorer\n\nLive explorer for template compilation output.\n\nTo run:\n\n- `npm run dev-compiler` in repo root\n- When the compilation is done, in another terminal run `npm run open`\n\nNote: `index.html` uses CDN for dependencies and is continuously deployed at [https://template-explorer.vuejs.org](https://template-explorer.vuejs.org). For local development, use the scripts above.\n"
  },
  {
    "path": "packages-private/template-explorer/_redirects",
    "content": "https://vue-next-template-explorer.netlify.app https://template-explorer.vuejs.org 301!\nhttps://vue-next-template-explorer.netlify.app/* https://template-explorer.vuejs.org/:splat 301!\n"
  },
  {
    "path": "packages-private/template-explorer/index.html",
    "content": "<title>Vue Template Explorer</title>\n<link\n  rel=\"stylesheet\"\n  data-name=\"vs/editor/editor.main\"\n  href=\"https://unpkg.com/monaco-editor@0.20.0/min/vs/editor/editor.main.css\"\n/>\n<link rel=\"stylesheet\" href=\"./style.css\" />\n\n<div id=\"header\"></div>\n<div id=\"source\" class=\"editor\"></div>\n<div id=\"output\" class=\"editor\"></div>\n\n<script src=\"https://unpkg.com/monaco-editor@0.20.0/min/vs/loader.js\"></script>\n<script>\n  require.config({\n    paths: {\n      vs: 'https://unpkg.com/monaco-editor@0.20.0/min/vs',\n    },\n  })\n</script>\n<script src=\"./dist/template-explorer.global.js\"></script>\n<script>\n  require(['vs/editor/editor.main'], init /* injected by build */)\n</script>\n"
  },
  {
    "path": "packages-private/template-explorer/local.html",
    "content": "<title>Vue Template Explorer</title>\n<link\n  rel=\"stylesheet\"\n  data-name=\"vs/editor/editor.main\"\n  href=\"./node_modules/monaco-editor/min/vs/editor/editor.main.css\"\n/>\n<link rel=\"stylesheet\" href=\"./style.css\" />\n\n<div id=\"header\"></div>\n<div id=\"source\" class=\"editor\"></div>\n<div id=\"output\" class=\"editor\"></div>\n\n<script src=\"./node_modules/monaco-editor/min/vs/loader.js\"></script>\n<script>\n  require.config({\n    paths: {\n      vs: './node_modules/monaco-editor/min/vs',\n    },\n  })\n</script>\n<script src=\"./dist/template-explorer.global.js\"></script>\n<script>\n  require(['vs/editor/editor.main'], init /* injected by build */)\n</script>\n"
  },
  {
    "path": "packages-private/template-explorer/package.json",
    "content": "{\n  \"name\": \"@vue/template-explorer\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"buildOptions\": {\n    \"formats\": [\n      \"global\"\n    ],\n    \"compat\": true,\n    \"env\": \"development\",\n    \"enableNonBrowserBranches\": true\n  },\n  \"dependencies\": {\n    \"monaco-editor\": \"^0.55.1\",\n    \"source-map-js\": \"^1.2.1\"\n  }\n}\n"
  },
  {
    "path": "packages-private/template-explorer/src/index.ts",
    "content": "import type * as m from 'monaco-editor'\nimport {\n  type CompilerError,\n  type CompilerOptions,\n  compile,\n} from '@vue/compiler-dom'\nimport { compile as ssrCompile } from '@vue/compiler-ssr'\nimport {\n  compilerOptions,\n  defaultOptions,\n  initOptions,\n  ssrMode,\n} from './options'\nimport { toRaw, watchEffect } from '@vue/runtime-dom'\nimport { SourceMapConsumer } from 'source-map-js'\nimport theme from './theme'\n\ndeclare global {\n  interface Window {\n    monaco: typeof m\n    _deps: any\n    init: () => void\n  }\n}\n\ninterface PersistedState {\n  src: string\n  ssr: boolean\n  options: CompilerOptions\n}\n\nconst sharedEditorOptions: m.editor.IStandaloneEditorConstructionOptions = {\n  fontSize: 14,\n  scrollBeyondLastLine: false,\n  renderWhitespace: 'selection',\n  minimap: {\n    enabled: false,\n  },\n}\n\nwindow.init = () => {\n  const monaco = window.monaco\n\n  monaco.editor.defineTheme('my-theme', theme)\n  monaco.editor.setTheme('my-theme')\n\n  let persistedState: PersistedState | undefined\n\n  try {\n    let hash = window.location.hash.slice(1)\n    try {\n      hash = escape(atob(hash))\n    } catch (e) {}\n    persistedState = JSON.parse(\n      decodeURIComponent(hash) || localStorage.getItem('state') || `{}`,\n    )\n  } catch (e: any) {\n    // bad stored state, clear it\n    console.warn(\n      'Persisted state in localStorage seems to be corrupted, please reload.\\n' +\n        e.message,\n    )\n    localStorage.clear()\n  }\n\n  if (persistedState) {\n    // functions are not persistable, so delete it in case we sometimes need\n    // to debug with custom nodeTransforms\n    delete persistedState.options?.nodeTransforms\n    ssrMode.value = persistedState.ssr\n    Object.assign(compilerOptions, persistedState.options)\n  }\n\n  let lastSuccessfulCode: string\n  let lastSuccessfulMap: SourceMapConsumer | undefined = undefined\n  function compileCode(source: string): string {\n    console.clear()\n    try {\n      const errors: CompilerError[] = []\n      const compileFn = ssrMode.value ? ssrCompile : compile\n      const start = performance.now()\n      const { code, ast, map } = compileFn(source, {\n        ...compilerOptions,\n        filename: 'ExampleTemplate.vue',\n        sourceMap: true,\n        onError: err => {\n          errors.push(err)\n        },\n      })\n      console.log(`Compiled in ${(performance.now() - start).toFixed(2)}ms.`)\n      monaco.editor.setModelMarkers(\n        editor.getModel()!,\n        `@vue/compiler-dom`,\n        errors.filter(e => e.loc).map(formatError),\n      )\n      console.log(`AST: `, ast)\n      console.log(`Options: `, toRaw(compilerOptions))\n      lastSuccessfulCode = code + `\\n\\n// Check the console for the AST`\n      lastSuccessfulMap = new SourceMapConsumer(map!)\n      lastSuccessfulMap!.computeColumnSpans()\n    } catch (e: any) {\n      lastSuccessfulCode = `/* ERROR: ${e.message} (see console for more info) */`\n      console.error(e)\n    }\n    return lastSuccessfulCode\n  }\n\n  function formatError(err: CompilerError) {\n    const loc = err.loc!\n    return {\n      severity: monaco.MarkerSeverity.Error,\n      startLineNumber: loc.start.line,\n      startColumn: loc.start.column,\n      endLineNumber: loc.end.line,\n      endColumn: loc.end.column,\n      message: `Vue template compilation error: ${err.message}`,\n      code: String(err.code),\n    }\n  }\n\n  function reCompile() {\n    const src = editor.getValue()\n    // every time we re-compile, persist current state\n\n    const optionsToSave = {}\n    let key: keyof CompilerOptions\n    for (key in compilerOptions) {\n      const val = compilerOptions[key]\n      if (typeof val !== 'object' && val !== defaultOptions[key]) {\n        // @ts-expect-error\n        optionsToSave[key] = val\n      }\n    }\n\n    const state = JSON.stringify({\n      src,\n      ssr: ssrMode.value,\n      options: optionsToSave,\n    } as PersistedState)\n    localStorage.setItem('state', state)\n    window.location.hash = btoa(unescape(encodeURIComponent(state)))\n    const res = compileCode(src)\n    if (res) {\n      output.setValue(res)\n    }\n  }\n\n  const editor = monaco.editor.create(document.getElementById('source')!, {\n    value: persistedState?.src || `<div>Hello World</div>`,\n    language: 'html',\n    ...sharedEditorOptions,\n    wordWrap: 'bounded',\n  })\n\n  editor.getModel()!.updateOptions({\n    tabSize: 2,\n  })\n\n  const output = monaco.editor.create(document.getElementById('output')!, {\n    value: '',\n    language: 'javascript',\n    readOnly: true,\n    ...sharedEditorOptions,\n  })\n  output.getModel()!.updateOptions({\n    tabSize: 2,\n  })\n\n  // handle resize\n  window.addEventListener('resize', () => {\n    editor.layout()\n    output.layout()\n  })\n\n  // update compile output when input changes\n  editor.onDidChangeModelContent(debounce(reCompile))\n\n  // highlight output code\n  let prevOutputDecos: string[] = []\n  function clearOutputDecos() {\n    prevOutputDecos = output.deltaDecorations(prevOutputDecos, [])\n  }\n\n  editor.onDidChangeCursorPosition(\n    debounce(e => {\n      clearEditorDecos()\n      if (lastSuccessfulMap) {\n        const pos = lastSuccessfulMap.generatedPositionFor({\n          source: 'ExampleTemplate.vue',\n          line: e.position.lineNumber,\n          column: e.position.column - 1,\n        })\n        if (pos.line != null && pos.column != null) {\n          prevOutputDecos = output.deltaDecorations(prevOutputDecos, [\n            {\n              range: new monaco.Range(\n                pos.line,\n                pos.column + 1,\n                pos.line,\n                pos.lastColumn ? pos.lastColumn + 2 : pos.column + 2,\n              ),\n              options: {\n                inlineClassName: `highlight`,\n              },\n            },\n          ])\n          output.revealPositionInCenter({\n            lineNumber: pos.line,\n            column: pos.column + 1,\n          })\n        } else {\n          clearOutputDecos()\n        }\n      }\n    }, 100),\n  )\n\n  let previousEditorDecos: string[] = []\n  function clearEditorDecos() {\n    previousEditorDecos = editor.deltaDecorations(previousEditorDecos, [])\n  }\n\n  output.onDidChangeCursorPosition(\n    debounce(e => {\n      clearOutputDecos()\n      if (lastSuccessfulMap) {\n        const pos = lastSuccessfulMap.originalPositionFor({\n          line: e.position.lineNumber,\n          column: e.position.column - 1,\n        })\n        if (\n          pos.line != null &&\n          pos.column != null &&\n          !(\n            // ignore mock location\n            (pos.line === 1 && pos.column === 0)\n          )\n        ) {\n          const translatedPos = {\n            column: pos.column + 1,\n            lineNumber: pos.line,\n          }\n          previousEditorDecos = editor.deltaDecorations(previousEditorDecos, [\n            {\n              range: new monaco.Range(\n                pos.line,\n                pos.column + 1,\n                pos.line,\n                pos.column + 1,\n              ),\n              options: {\n                isWholeLine: true,\n                className: `highlight`,\n              },\n            },\n          ])\n          editor.revealPositionInCenter(translatedPos)\n        } else {\n          clearEditorDecos()\n        }\n      }\n    }, 100),\n  )\n\n  initOptions()\n  watchEffect(reCompile)\n}\n\nfunction debounce<T extends (...args: any[]) => any>(\n  fn: T,\n  delay: number = 300,\n): T {\n  let prevTimer: number | null = null\n  return ((...args: any[]) => {\n    if (prevTimer) {\n      clearTimeout(prevTimer)\n    }\n    prevTimer = window.setTimeout(() => {\n      fn(...args)\n      prevTimer = null\n    }, delay)\n  }) as T\n}\n"
  },
  {
    "path": "packages-private/template-explorer/src/options.ts",
    "content": "import { createApp, h, reactive, ref } from 'vue'\nimport type { CompilerOptions } from '@vue/compiler-dom'\nimport { BindingTypes } from '@vue/compiler-core'\n\nexport const ssrMode = ref(false)\n\nexport const defaultOptions: CompilerOptions = {\n  mode: 'module',\n  filename: 'Foo.vue',\n  prefixIdentifiers: false,\n  hoistStatic: false,\n  cacheHandlers: false,\n  scopeId: null,\n  inline: false,\n  ssrCssVars: `{ color }`,\n  compatConfig: { MODE: 3 },\n  whitespace: 'condense',\n  bindingMetadata: {\n    TestComponent: BindingTypes.SETUP_CONST,\n    setupRef: BindingTypes.SETUP_REF,\n    setupConst: BindingTypes.SETUP_CONST,\n    setupLet: BindingTypes.SETUP_LET,\n    setupMaybeRef: BindingTypes.SETUP_MAYBE_REF,\n    setupProp: BindingTypes.PROPS,\n    vMySetupDir: BindingTypes.SETUP_CONST,\n  },\n}\n\nexport const compilerOptions: CompilerOptions = reactive(\n  Object.assign({}, defaultOptions),\n)\n\nconst App = {\n  setup() {\n    return () => {\n      const isSSR = ssrMode.value\n      const isModule = compilerOptions.mode === 'module'\n      const usePrefix =\n        compilerOptions.prefixIdentifiers || compilerOptions.mode === 'module'\n\n      return [\n        h('h1', `Vue 3 Template Explorer`),\n        h(\n          'a',\n          {\n            href: `https://github.com/vuejs/core/tree/${__COMMIT__}`,\n            target: `_blank`,\n          },\n          `@${__COMMIT__}`,\n        ),\n        ' | ',\n        h(\n          'a',\n          {\n            href: 'https://app.netlify.com/sites/vue-next-template-explorer/deploys',\n            target: `_blank`,\n          },\n          'History',\n        ),\n\n        h('div', { id: 'options-wrapper' }, [\n          h('div', { id: 'options-label' }, 'Options ↘'),\n          h('ul', { id: 'options' }, [\n            // mode selection\n            h('li', { id: 'mode' }, [\n              h('span', { class: 'label' }, 'Mode: '),\n              h('input', {\n                type: 'radio',\n                id: 'mode-module',\n                name: 'mode',\n                checked: isModule,\n                onChange() {\n                  compilerOptions.mode = 'module'\n                },\n              }),\n              h('label', { for: 'mode-module' }, 'module'),\n              ' ',\n              h('input', {\n                type: 'radio',\n                id: 'mode-function',\n                name: 'mode',\n                checked: !isModule,\n                onChange() {\n                  compilerOptions.mode = 'function'\n                },\n              }),\n              h('label', { for: 'mode-function' }, 'function'),\n            ]),\n\n            // whitespace handling\n            h('li', { id: 'whitespace' }, [\n              h('span', { class: 'label' }, 'whitespace: '),\n              h('input', {\n                type: 'radio',\n                id: 'whitespace-condense',\n                name: 'whitespace',\n                checked: compilerOptions.whitespace === 'condense',\n                onChange() {\n                  compilerOptions.whitespace = 'condense'\n                },\n              }),\n              h('label', { for: 'whitespace-condense' }, 'condense'),\n              ' ',\n              h('input', {\n                type: 'radio',\n                id: 'whitespace-preserve',\n                name: 'whitespace',\n                checked: compilerOptions.whitespace === 'preserve',\n                onChange() {\n                  compilerOptions.whitespace = 'preserve'\n                },\n              }),\n              h('label', { for: 'whitespace-preserve' }, 'preserve'),\n            ]),\n\n            // SSR\n            h('li', [\n              h('input', {\n                type: 'checkbox',\n                id: 'ssr',\n                name: 'ssr',\n                checked: ssrMode.value,\n                onChange(e: Event) {\n                  ssrMode.value = (e.target as HTMLInputElement).checked\n                },\n              }),\n              h('label', { for: 'ssr' }, 'SSR'),\n            ]),\n\n            // toggle prefixIdentifiers\n            h('li', [\n              h('input', {\n                type: 'checkbox',\n                id: 'prefix',\n                disabled: isModule || isSSR,\n                checked: usePrefix || isSSR,\n                onChange(e: Event) {\n                  compilerOptions.prefixIdentifiers =\n                    (e.target as HTMLInputElement).checked || isModule\n                },\n              }),\n              h('label', { for: 'prefix' }, 'prefixIdentifiers'),\n            ]),\n\n            // toggle hoistStatic\n            h('li', [\n              h('input', {\n                type: 'checkbox',\n                id: 'hoist',\n                checked: compilerOptions.hoistStatic && !isSSR,\n                disabled: isSSR,\n                onChange(e: Event) {\n                  compilerOptions.hoistStatic = (\n                    e.target as HTMLInputElement\n                  ).checked\n                },\n              }),\n              h('label', { for: 'hoist' }, 'hoistStatic'),\n            ]),\n\n            // toggle cacheHandlers\n            h('li', [\n              h('input', {\n                type: 'checkbox',\n                id: 'cache',\n                checked: usePrefix && compilerOptions.cacheHandlers && !isSSR,\n                disabled: !usePrefix || isSSR,\n                onChange(e: Event) {\n                  compilerOptions.cacheHandlers = (\n                    e.target as HTMLInputElement\n                  ).checked\n                },\n              }),\n              h('label', { for: 'cache' }, 'cacheHandlers'),\n            ]),\n\n            // toggle scopeId\n            h('li', [\n              h('input', {\n                type: 'checkbox',\n                id: 'scope-id',\n                disabled: !isModule,\n                checked: isModule && compilerOptions.scopeId,\n                onChange(e: Event) {\n                  compilerOptions.scopeId =\n                    isModule && (e.target as HTMLInputElement).checked\n                      ? 'scope-id'\n                      : null\n                },\n              }),\n              h('label', { for: 'scope-id' }, 'scopeId'),\n            ]),\n\n            // inline mode\n            h('li', [\n              h('input', {\n                type: 'checkbox',\n                id: 'inline',\n                checked: compilerOptions.inline,\n                onChange(e: Event) {\n                  compilerOptions.inline = (\n                    e.target as HTMLInputElement\n                  ).checked\n                },\n              }),\n              h('label', { for: 'inline' }, 'inline'),\n            ]),\n\n            // compat mode\n            h('li', [\n              h('input', {\n                type: 'checkbox',\n                id: 'compat',\n                checked: compilerOptions.compatConfig!.MODE === 2,\n                onChange(e: Event) {\n                  compilerOptions.compatConfig!.MODE = (\n                    e.target as HTMLInputElement\n                  ).checked\n                    ? 2\n                    : 3\n                },\n              }),\n              h('label', { for: 'compat' }, 'v2 compat mode'),\n            ]),\n          ]),\n        ]),\n      ]\n    }\n  },\n}\n\nexport function initOptions() {\n  createApp(App).mount(document.getElementById('header')!)\n}\n"
  },
  {
    "path": "packages-private/template-explorer/src/theme.ts",
    "content": "export default {\n  base: 'vs-dark' as const,\n  inherit: true,\n  rules: [\n    {\n      foreground: 'de935f',\n      token: 'number',\n    },\n    {\n      foreground: '969896',\n      token: 'comment',\n    },\n    {\n      foreground: 'ced1cf',\n      token: 'keyword.operator.class',\n    },\n    {\n      foreground: 'ced1cf',\n      token: 'constant.other',\n    },\n    {\n      foreground: 'ced1cf',\n      token: 'source.php.embedded.line',\n    },\n    {\n      foreground: 'cc6666',\n      token: 'variable',\n    },\n    {\n      foreground: 'cc6666',\n      token: 'support.other.variable',\n    },\n    {\n      foreground: 'cc6666',\n      token: 'string.other.link',\n    },\n    {\n      foreground: 'cc6666',\n      token: 'string.regexp',\n    },\n    {\n      foreground: 'cc6666',\n      token: 'entity.name.tag',\n    },\n    {\n      foreground: 'cc6666',\n      token: 'entity.other.attribute-name',\n    },\n    {\n      foreground: 'cc6666',\n      token: 'meta.tag',\n    },\n    {\n      foreground: 'cc6666',\n      token: 'declaration.tag',\n    },\n    {\n      foreground: 'cc6666',\n      token: 'markup.deleted.git_gutter',\n    },\n    {\n      foreground: 'de935f',\n      token: 'constant.numeric',\n    },\n    {\n      foreground: 'de935f',\n      token: 'constant.language',\n    },\n    {\n      foreground: 'de935f',\n      token: 'support.constant',\n    },\n    {\n      foreground: 'de935f',\n      token: 'constant.character',\n    },\n    {\n      foreground: 'de935f',\n      token: 'variable.parameter',\n    },\n    {\n      foreground: 'de935f',\n      token: 'punctuation.section.embedded',\n    },\n    {\n      foreground: 'de935f',\n      token: 'keyword.other.unit',\n    },\n    {\n      foreground: 'f0c674',\n      token: 'entity.name.class',\n    },\n    {\n      foreground: 'f0c674',\n      token: 'entity.name.type.class',\n    },\n    {\n      foreground: 'f0c674',\n      token: 'support.type',\n    },\n    {\n      foreground: 'f0c674',\n      token: 'support.class',\n    },\n    {\n      foreground: 'b5bd68',\n      token: 'string',\n    },\n    {\n      foreground: 'b5bd68',\n      token: 'constant.other.symbol',\n    },\n    {\n      foreground: 'b5bd68',\n      token: 'entity.other.inherited-class',\n    },\n    {\n      foreground: 'b5bd68',\n      token: 'markup.heading',\n    },\n    {\n      foreground: 'b5bd68',\n      token: 'markup.inserted.git_gutter',\n    },\n    {\n      foreground: '8abeb7',\n      token: 'keyword.operator',\n    },\n    {\n      foreground: '8abeb7',\n      token: 'constant.other.color',\n    },\n    {\n      foreground: '81a2be',\n      token: 'entity.name.function',\n    },\n    {\n      foreground: '81a2be',\n      token: 'meta.function-call',\n    },\n    {\n      foreground: '81a2be',\n      token: 'support.function',\n    },\n    {\n      foreground: '81a2be',\n      token: 'keyword.other.special-method',\n    },\n    {\n      foreground: '81a2be',\n      token: 'meta.block-level',\n    },\n    {\n      foreground: '81a2be',\n      token: 'markup.changed.git_gutter',\n    },\n    {\n      foreground: 'b294bb',\n      token: 'keyword',\n    },\n    {\n      foreground: 'b294bb',\n      token: 'storage',\n    },\n    {\n      foreground: 'b294bb',\n      token: 'storage.type',\n    },\n    {\n      foreground: 'b294bb',\n      token: 'entity.name.tag.css',\n    },\n    {\n      foreground: 'ced2cf',\n      background: 'df5f5f',\n      token: 'invalid',\n    },\n    {\n      foreground: 'ced2cf',\n      background: '82a3bf',\n      token: 'meta.separator',\n    },\n    {\n      foreground: 'ced2cf',\n      background: 'b798bf',\n      token: 'invalid.deprecated',\n    },\n    {\n      foreground: 'ffffff',\n      token: 'markup.inserted.diff',\n    },\n    {\n      foreground: 'ffffff',\n      token: 'markup.deleted.diff',\n    },\n    {\n      foreground: 'ffffff',\n      token: 'meta.diff.header.to-file',\n    },\n    {\n      foreground: 'ffffff',\n      token: 'meta.diff.header.from-file',\n    },\n    {\n      foreground: '718c00',\n      token: 'markup.inserted.diff',\n    },\n    {\n      foreground: '718c00',\n      token: 'meta.diff.header.to-file',\n    },\n    {\n      foreground: 'c82829',\n      token: 'markup.deleted.diff',\n    },\n    {\n      foreground: 'c82829',\n      token: 'meta.diff.header.from-file',\n    },\n    {\n      foreground: 'ffffff',\n      background: '4271ae',\n      token: 'meta.diff.header.from-file',\n    },\n    {\n      foreground: 'ffffff',\n      background: '4271ae',\n      token: 'meta.diff.header.to-file',\n    },\n    {\n      foreground: '3e999f',\n      fontStyle: 'italic',\n      token: 'meta.diff.range',\n    },\n  ],\n  colors: {\n    'editor.foreground': '#C5C8C6',\n    'editor.background': '#1D1F21',\n    'editor.selectionBackground': '#373B41',\n    'editor.lineHighlightBackground': '#282A2E',\n    'editorCursor.foreground': '#AEAFAD',\n    'editorWhitespace.foreground': '#4B4E55',\n  },\n}\n"
  },
  {
    "path": "packages-private/template-explorer/style.css",
    "content": "body {\n  margin: 0;\n  overflow: hidden;\n  font-family:\n    -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu,\n    Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;\n  --bg: #1d1f21;\n  --border: #333;\n}\n\n#header {\n  position: absolute;\n  top: 0;\n  left: 0;\n  right: 0;\n  height: 60px;\n  box-sizing: border-box;\n  background-color: var(--bg);\n  border-bottom: 1px solid var(--border);\n  padding: 0.3em 1.6em;\n  color: #fff;\n  z-index: 1;\n}\n\nh1 {\n  font-size: 18px;\n  display: inline-block;\n  margin-right: 15px;\n}\n\n#options-wrapper {\n  position: absolute;\n  top: 20px;\n  right: 10px;\n}\n\n#options-wrapper:hover #options {\n  display: block;\n}\n\n#options-label {\n  cursor: pointer;\n  text-align: right;\n  padding-right: 10px;\n  font-weight: bold;\n}\n\n#options {\n  display: none;\n  margin-top: 15px;\n  list-style-type: none;\n  background-color: var(--bg);\n  border: 1px solid var(--border);\n  padding: 15px 30px;\n}\n\n#options li {\n  margin: 8px 0;\n}\n\n#header a {\n  font-weight: 600;\n  color: rgb(101, 163, 221);\n}\n\n#header .label {\n  font-weight: bold;\n}\n\n#header input {\n  margin-right: 6px;\n}\n\n#header label {\n  color: #999;\n}\n\n.editor {\n  position: absolute;\n  top: 60px;\n  bottom: 0;\n  box-sizing: border-box;\n}\n\n#source {\n  left: 0;\n  width: 45%;\n}\n\n#output {\n  left: 45%;\n  width: 55%;\n}\n\n.highlight {\n  background-color: rgba(46, 120, 190, 0.5);\n}\n"
  },
  {
    "path": "packages-private/tsconfig.json",
    "content": "{\n  \"extends\": \"../tsconfig.json\",\n  \"compilerOptions\": {\n    \"isolatedDeclarations\": false\n  },\n  \"include\": [\".\"]\n}\n"
  },
  {
    "path": "packages-private/vite-debug/App.vue",
    "content": "<script setup>\nimport { ref } from 'vue'\n\nconst count = ref(0)\n</script>\n\n<template>\n  <button @click=\"count++\">{{ count }}</button>\n</template>\n\n<style>\nbutton {\n  color: red;\n}\n</style>\n"
  },
  {
    "path": "packages-private/vite-debug/README.md",
    "content": "This package is used for debugging issues that are related to `@vitejs/plugin-vue`, or can only be reproduced in a Vite-based setup. It aims to be as close to production as possible so Vue packages are resolved to the dist files instead of source.\n"
  },
  {
    "path": "packages-private/vite-debug/index.html",
    "content": "<script type=\"module\" src=\"./main.ts\"></script>\n<div id=\"app\"></div>\n"
  },
  {
    "path": "packages-private/vite-debug/main.ts",
    "content": "import { createApp } from 'vue'\nimport App from './App.vue'\n\nconst app = createApp(App)\n\napp.mount('#app')\n"
  },
  {
    "path": "packages-private/vite-debug/package.json",
    "content": "{\n  \"name\": \"vite-debug\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"serve\": \"vite preview\"\n  },\n  \"devDependencies\": {\n    \"@vitejs/plugin-vue\": \"catalog:\",\n    \"vite\": \"catalog:\",\n    \"vue\": \"workspace:*\"\n  }\n}\n"
  },
  {
    "path": "packages-private/vite-debug/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"module\": \"esnext\",\n    \"moduleResolution\": \"bundler\"\n  },\n  \"include\": [\"./*\"]\n}\n"
  },
  {
    "path": "packages-private/vite-debug/vite.config.ts",
    "content": "import { defineConfig } from 'vite'\nimport vue from '@vitejs/plugin-vue'\n\nexport default defineConfig({\n  plugins: [vue()],\n})\n"
  },
  {
    "path": "pnpm-workspace.yaml",
    "content": "packages:\n  - 'packages/*'\n  - 'packages-private/*'\n\ncatalog:\n  '@babel/parser': ^7.29.0\n  '@babel/types': ^7.29.0\n  'entities': '^7.0.1'\n  'estree-walker': ^2.0.2\n  'magic-string': ^0.30.21\n  'source-map-js': ^1.2.1\n  'vite': ^7.3.1\n  '@vitejs/plugin-vue': ^6.0.4\n\nonlyBuiltDependencies:\n  - '@swc/core'\n  - 'esbuild'\n  - 'puppeteer'\n  - 'simple-git-hooks'\n  - 'unrs-resolver'\n\npeerDependencyRules:\n  allowedVersions:\n    'typescript-eslint>eslint': '^9.0.0'\n    '@typescript-eslint/eslint-plugin>eslint': '^9.0.0'\n    '@typescript-eslint/parser>eslint': '^9.0.0'\n    '@typescript-eslint/type-utils>eslint': '^9.0.0'\n    '@typescript-eslint/utils>eslint': '^9.0.0'\n"
  },
  {
    "path": "rollup.config.js",
    "content": "// @ts-check\nimport assert from 'node:assert/strict'\nimport { createRequire } from 'node:module'\nimport { fileURLToPath } from 'node:url'\nimport fs from 'node:fs'\nimport path from 'node:path'\nimport replace from '@rollup/plugin-replace'\nimport json from '@rollup/plugin-json'\nimport pico from 'picocolors'\nimport commonJS from '@rollup/plugin-commonjs'\nimport polyfillNode from 'rollup-plugin-polyfill-node'\nimport { nodeResolve } from '@rollup/plugin-node-resolve'\nimport esbuild from 'rollup-plugin-esbuild'\nimport alias from '@rollup/plugin-alias'\nimport { entries } from './scripts/aliases.js'\nimport { inlineEnums } from './scripts/inline-enums.js'\nimport { minify as minifySwc } from '@swc/core'\n\n/**\n * @template T\n * @template {keyof T} K\n * @typedef { Omit<T, K> & Required<Pick<T, K>> } MarkRequired\n */\n/** @typedef {'cjs' | 'esm-bundler' | 'global' | 'global-runtime' | 'esm-browser' | 'esm-bundler-runtime' | 'esm-browser-runtime'} PackageFormat */\n/** @typedef {MarkRequired<import('rollup').OutputOptions, 'file' | 'format'>} OutputOptions */\n\nif (!process.env.TARGET) {\n  throw new Error('TARGET package must be specified via --environment flag.')\n}\n\nconst require = createRequire(import.meta.url)\nconst __dirname = fileURLToPath(new URL('.', import.meta.url))\n\nconst masterVersion = require('./package.json').version\nconst consolidatePkg = require('@vue/consolidate/package.json')\n\nconst privatePackages = fs.readdirSync('packages-private')\nconst pkgBase = privatePackages.includes(process.env.TARGET)\n  ? `packages-private`\n  : `packages`\nconst packagesDir = path.resolve(__dirname, pkgBase)\nconst packageDir = path.resolve(packagesDir, process.env.TARGET)\n\nconst resolve = (/** @type {string} */ p) => path.resolve(packageDir, p)\nconst pkg = require(resolve(`package.json`))\nconst packageOptions = pkg.buildOptions || {}\nconst name = packageOptions.filename || path.basename(packageDir)\n\nconst banner = `/**\n* ${pkg.name} v${masterVersion}\n* (c) 2018-present Yuxi (Evan) You and Vue contributors\n* @license MIT\n**/`\n\nconst [enumPlugin, enumDefines] = inlineEnums()\n\n/** @type {Record<PackageFormat, OutputOptions>} */\nconst outputConfigs = {\n  'esm-bundler': {\n    file: resolve(`dist/${name}.esm-bundler.js`),\n    format: 'es',\n  },\n  'esm-browser': {\n    file: resolve(`dist/${name}.esm-browser.js`),\n    format: 'es',\n  },\n  cjs: {\n    file: resolve(`dist/${name}.cjs.js`),\n    format: 'cjs',\n  },\n  global: {\n    file: resolve(`dist/${name}.global.js`),\n    format: 'iife',\n  },\n  // runtime-only builds, for main \"vue\" package only\n  'esm-bundler-runtime': {\n    file: resolve(`dist/${name}.runtime.esm-bundler.js`),\n    format: 'es',\n  },\n  'esm-browser-runtime': {\n    file: resolve(`dist/${name}.runtime.esm-browser.js`),\n    format: 'es',\n  },\n  'global-runtime': {\n    file: resolve(`dist/${name}.runtime.global.js`),\n    format: 'iife',\n  },\n}\n\n/** @type {ReadonlyArray<PackageFormat>} */\nconst defaultFormats = ['esm-bundler', 'cjs']\n/** @type {ReadonlyArray<PackageFormat>} */\nconst inlineFormats = /** @type {any} */ (\n  process.env.FORMATS && process.env.FORMATS.split(',')\n)\n/** @type {ReadonlyArray<PackageFormat>} */\nconst packageFormats = inlineFormats || packageOptions.formats || defaultFormats\nconst packageConfigs = process.env.PROD_ONLY\n  ? []\n  : packageFormats.map(format => createConfig(format, outputConfigs[format]))\n\nif (process.env.NODE_ENV === 'production') {\n  packageFormats.forEach(format => {\n    if (packageOptions.prod === false) {\n      return\n    }\n    if (format === 'cjs') {\n      packageConfigs.push(createProductionConfig(format))\n    }\n    if (/^(global|esm-browser)(-runtime)?/.test(format)) {\n      packageConfigs.push(createMinifiedConfig(format))\n    }\n  })\n}\n\nexport default packageConfigs\n\n/**\n *\n * @param {PackageFormat} format\n * @param {OutputOptions} output\n * @param {ReadonlyArray<import('rollup').Plugin>} plugins\n * @returns {import('rollup').RollupOptions}\n */\nfunction createConfig(format, output, plugins = []) {\n  if (!output) {\n    console.log(pico.yellow(`invalid format: \"${format}\"`))\n    process.exit(1)\n  }\n\n  const isProductionBuild =\n    process.env.__DEV__ === 'false' || /\\.prod\\.js$/.test(output.file)\n  const isBundlerESMBuild = /esm-bundler/.test(format)\n  const isBrowserESMBuild = /esm-browser/.test(format)\n  const isServerRenderer = name === 'server-renderer'\n  const isCJSBuild = format === 'cjs'\n  const isGlobalBuild = /global/.test(format)\n  const isCompatPackage = pkg.name === '@vue/compat'\n  const isCompatBuild = !!packageOptions.compat\n  const isBrowserBuild =\n    (isGlobalBuild || isBrowserESMBuild || isBundlerESMBuild) &&\n    !packageOptions.enableNonBrowserBranches\n\n  output.banner = banner\n\n  output.exports = isCompatPackage ? 'auto' : 'named'\n  if (isCJSBuild) {\n    output.esModule = true\n  }\n  output.sourcemap = !!process.env.SOURCE_MAP\n  output.externalLiveBindings = false\n  // https://github.com/rollup/rollup/pull/5380\n  output.reexportProtoFromExternal = false\n\n  if (isGlobalBuild) {\n    output.name = packageOptions.name\n  }\n\n  let entryFile = /runtime$/.test(format) ? `src/runtime.ts` : `src/index.ts`\n\n  // the compat build needs both default AND named exports. This will cause\n  // Rollup to complain for non-ESM targets, so we use separate entries for\n  // esm vs. non-esm builds.\n  if (isCompatPackage && (isBrowserESMBuild || isBundlerESMBuild)) {\n    entryFile = /runtime$/.test(format)\n      ? `src/esm-runtime.ts`\n      : `src/esm-index.ts`\n  }\n\n  function resolveDefine() {\n    /** @type {Record<string, string>} */\n    const replacements = {\n      __COMMIT__: `\"${process.env.COMMIT}\"`,\n      __VERSION__: `\"${masterVersion}\"`,\n      // this is only used during Vue's internal tests\n      __TEST__: `false`,\n      // If the build is expected to run directly in the browser (global / esm builds)\n      __BROWSER__: String(isBrowserBuild),\n      __GLOBAL__: String(isGlobalBuild),\n      __ESM_BUNDLER__: String(isBundlerESMBuild),\n      __ESM_BROWSER__: String(isBrowserESMBuild),\n      // is targeting Node (SSR)?\n      __CJS__: String(isCJSBuild),\n      // need SSR-specific branches?\n      __SSR__: String(!isGlobalBuild),\n\n      // 2.x compat build\n      __COMPAT__: String(isCompatBuild),\n\n      // feature flags\n      __FEATURE_SUSPENSE__: `true`,\n      __FEATURE_OPTIONS_API__: isBundlerESMBuild\n        ? `__VUE_OPTIONS_API__`\n        : `true`,\n      __FEATURE_PROD_DEVTOOLS__: isBundlerESMBuild\n        ? `__VUE_PROD_DEVTOOLS__`\n        : `false`,\n      __FEATURE_PROD_HYDRATION_MISMATCH_DETAILS__: isBundlerESMBuild\n        ? `__VUE_PROD_HYDRATION_MISMATCH_DETAILS__`\n        : `false`,\n    }\n\n    if (!isBundlerESMBuild) {\n      // hard coded dev/prod builds\n      replacements.__DEV__ = String(!isProductionBuild)\n    }\n\n    // allow inline overrides like\n    //__RUNTIME_COMPILE__=true pnpm build runtime-core\n    Object.keys(replacements).forEach(key => {\n      if (key in process.env) {\n        const value = process.env[key]\n        assert(typeof value === 'string')\n        replacements[key] = value\n      }\n    })\n    return replacements\n  }\n\n  // esbuild define is a bit strict and only allows literal json or identifiers\n  // so we still need replace plugin in some cases\n  function resolveReplace() {\n    const replacements = { ...enumDefines }\n\n    if (isProductionBuild && isBrowserBuild) {\n      Object.assign(replacements, {\n        'context.onError(': `/*@__PURE__*/ context.onError(`,\n        'emitError(': `/*@__PURE__*/ emitError(`,\n        'createCompilerError(': `/*@__PURE__*/ createCompilerError(`,\n        'createDOMCompilerError(': `/*@__PURE__*/ createDOMCompilerError(`,\n      })\n    }\n\n    if (isBundlerESMBuild) {\n      Object.assign(replacements, {\n        // preserve to be handled by bundlers\n        __DEV__: `!!(process.env.NODE_ENV !== 'production')`,\n      })\n    }\n\n    // for compiler-sfc browser build inlined deps\n    if (isBrowserESMBuild) {\n      Object.assign(replacements, {\n        'process.env': '({})',\n        'process.platform': '\"\"',\n        'process.stdout': 'null',\n      })\n    }\n\n    if (Object.keys(replacements).length) {\n      return [replace({ values: replacements, preventAssignment: true })]\n    } else {\n      return []\n    }\n  }\n\n  function resolveExternal() {\n    const treeShakenDeps = [\n      'source-map-js',\n      '@babel/parser',\n      'estree-walker',\n      'entities/decode',\n    ]\n\n    if (isGlobalBuild || isBrowserESMBuild || isCompatPackage) {\n      if (!packageOptions.enableNonBrowserBranches) {\n        // normal browser builds - non-browser only imports are tree-shaken,\n        // they are only listed here to suppress warnings.\n        return treeShakenDeps\n      }\n    } else {\n      // Node / esm-bundler builds.\n      // externalize all direct deps unless it's the compat build.\n      return [\n        ...Object.keys(pkg.dependencies || {}),\n        ...Object.keys(pkg.peerDependencies || {}),\n        // for @vue/compiler-sfc / server-renderer\n        ...['path', 'url', 'stream'],\n        // somehow these throw warnings for runtime-* package builds\n        ...treeShakenDeps,\n      ]\n    }\n  }\n\n  function resolveNodePlugins() {\n    // we are bundling forked consolidate.js in compiler-sfc which dynamically\n    // requires a ton of template engines which should be ignored.\n    /** @type {ReadonlyArray<string>} */\n    let cjsIgnores = []\n    if (pkg.name === '@vue/compiler-sfc') {\n      cjsIgnores = [\n        ...Object.keys(consolidatePkg.devDependencies),\n        'vm',\n        'crypto',\n        'react-dom/server',\n        'teacup/lib/express',\n        'arc-templates/dist/es5',\n        'then-pug',\n        'then-jade',\n      ]\n    }\n\n    const nodePlugins =\n      (format === 'cjs' && Object.keys(pkg.devDependencies || {}).length) ||\n      packageOptions.enableNonBrowserBranches\n        ? [\n            commonJS({\n              sourceMap: false,\n              ignore: cjsIgnores,\n            }),\n            ...(format === 'cjs' ? [] : [polyfillNode()]),\n            nodeResolve(),\n          ]\n        : []\n\n    return nodePlugins\n  }\n\n  return {\n    input: resolve(entryFile),\n    // Global and Browser ESM builds inlines everything so that they can be\n    // used alone.\n    external: resolveExternal(),\n    plugins: [\n      json({\n        namedExports: false,\n      }),\n      alias({\n        entries,\n      }),\n      enumPlugin,\n      ...resolveReplace(),\n      esbuild({\n        tsconfig: path.resolve(__dirname, 'tsconfig.json'),\n        sourceMap: output.sourcemap,\n        minify: false,\n        target: isServerRenderer || isCJSBuild ? 'es2019' : 'es2016',\n        define: resolveDefine(),\n      }),\n      ...resolveNodePlugins(),\n      ...plugins,\n    ],\n    output,\n    onwarn: (msg, warn) => {\n      if (msg.code !== 'CIRCULAR_DEPENDENCY') {\n        warn(msg)\n      }\n    },\n    treeshake: {\n      moduleSideEffects: false,\n    },\n  }\n}\n\nfunction createProductionConfig(/** @type {PackageFormat} */ format) {\n  return createConfig(format, {\n    file: resolve(`dist/${name}.${format}.prod.js`),\n    format: outputConfigs[format].format,\n  })\n}\n\nfunction createMinifiedConfig(/** @type {PackageFormat} */ format) {\n  return createConfig(\n    format,\n    {\n      file: outputConfigs[format].file.replace(/\\.js$/, '.prod.js'),\n      format: outputConfigs[format].format,\n    },\n    [\n      {\n        name: 'swc-minify',\n\n        async renderChunk(contents, _, { format }) {\n          const { code } = await minifySwc(contents, {\n            module: format === 'es',\n            format: {\n              comments: false,\n            },\n            compress: {\n              ecma: 2016,\n              pure_getters: true,\n            },\n            safari10: true,\n            mangle: true,\n          })\n\n          return { code: banner + code, map: null }\n        },\n      },\n    ],\n  )\n}\n"
  },
  {
    "path": "rollup.dts.config.js",
    "content": "// @ts-check\nimport assert from 'node:assert/strict'\nimport { parse } from '@babel/parser'\nimport { existsSync, readFileSync, readdirSync, writeFileSync } from 'node:fs'\nimport MagicString from 'magic-string'\nimport dts from 'rollup-plugin-dts'\n\nif (!existsSync('temp/packages')) {\n  console.warn(\n    'no temp dts files found. run `tsc -p tsconfig.build.json --noCheck` first.',\n  )\n  process.exit(1)\n}\n\nconst packages = readdirSync('temp/packages')\nconst targets = process.env.TARGETS ? process.env.TARGETS.split(',') : null\nconst targetPackages = targets\n  ? packages.filter(pkg => targets.includes(pkg))\n  : packages\n\nexport default targetPackages.map(\n  /** @returns {import('rollup').RollupOptions} */\n  pkg => {\n    return {\n      input: `./temp/packages/${pkg}/src/index.d.ts`,\n      output: {\n        file: `packages/${pkg}/dist/${pkg}.d.ts`,\n        format: 'es',\n      },\n      plugins: [dts(), patchTypes(pkg), ...(pkg === 'vue' ? [copyMts()] : [])],\n      onwarn(warning, warn) {\n        // during dts rollup, everything is externalized by default\n        if (\n          warning.code === 'UNRESOLVED_IMPORT' &&\n          !warning.exporter?.startsWith('.')\n        ) {\n          return\n        }\n        warn(warning)\n      },\n    }\n  },\n)\n\n/**\n * Patch the dts generated by rollup-plugin-dts\n * 1. Convert all types to inline exports\n *    and remove them from the big export {} declaration\n *    otherwise it gets weird in vitepress `defineComponent` call with\n *    \"the inferred type cannot be named without a reference\"\n * 2. Append custom augmentations (jsx, macros)\n *\n * @param {string} pkg\n * @returns {import('rollup').Plugin}\n */\nfunction patchTypes(pkg) {\n  return {\n    name: 'patch-types',\n    renderChunk(code, chunk) {\n      const s = new MagicString(code)\n      const ast = parse(code, {\n        plugins: ['typescript'],\n        sourceType: 'module',\n      })\n\n      /**\n       * @param {import('@babel/types').VariableDeclarator | import('@babel/types').TSTypeAliasDeclaration | import('@babel/types').TSInterfaceDeclaration | import('@babel/types').TSDeclareFunction | import('@babel/types').TSInterfaceDeclaration | import('@babel/types').TSEnumDeclaration | import('@babel/types').ClassDeclaration} node\n       * @param {import('@babel/types').VariableDeclaration} [parentDecl]\n       */\n      function processDeclaration(node, parentDecl) {\n        if (!node.id) {\n          return\n        }\n        assert(node.id.type === 'Identifier')\n        const name = node.id.name\n        if (name.startsWith('_')) {\n          return\n        }\n        shouldRemoveExport.add(name)\n        if (isExported.has(name)) {\n          const start = (parentDecl || node).start\n          assert(typeof start === 'number')\n          s.prependLeft(start, `export `)\n        }\n      }\n\n      const isExported = new Set()\n      const shouldRemoveExport = new Set()\n\n      // pass 0: check all exported types\n      for (const node of ast.program.body) {\n        if (node.type === 'ExportNamedDeclaration' && !node.source) {\n          for (let i = 0; i < node.specifiers.length; i++) {\n            const spec = node.specifiers[i]\n            if (spec.type === 'ExportSpecifier') {\n              isExported.add(spec.local.name)\n            }\n          }\n        }\n      }\n\n      // pass 1: add exports\n      for (const node of ast.program.body) {\n        if (node.type === 'VariableDeclaration') {\n          processDeclaration(node.declarations[0], node)\n          if (node.declarations.length > 1) {\n            assert(typeof node.start === 'number')\n            assert(typeof node.end === 'number')\n            throw new Error(\n              `unhandled declare const with more than one declarators:\\n${code.slice(\n                node.start,\n                node.end,\n              )}`,\n            )\n          }\n        } else if (\n          node.type === 'TSTypeAliasDeclaration' ||\n          node.type === 'TSInterfaceDeclaration' ||\n          node.type === 'TSDeclareFunction' ||\n          node.type === 'TSEnumDeclaration' ||\n          node.type === 'ClassDeclaration'\n        ) {\n          processDeclaration(node)\n        }\n      }\n\n      // pass 2: remove exports\n      for (const node of ast.program.body) {\n        if (node.type === 'ExportNamedDeclaration' && !node.source) {\n          let removed = 0\n          for (let i = 0; i < node.specifiers.length; i++) {\n            const spec = node.specifiers[i]\n            if (\n              spec.type === 'ExportSpecifier' &&\n              shouldRemoveExport.has(spec.local.name)\n            ) {\n              assert(spec.exported.type === 'Identifier')\n              const exported = spec.exported.name\n              if (exported !== spec.local.name) {\n                // this only happens if we have something like\n                //   type Foo\n                //   export { Foo as Bar }\n                continue\n              }\n              const next = node.specifiers[i + 1]\n              if (next) {\n                assert(typeof spec.start === 'number')\n                assert(typeof next.start === 'number')\n                s.remove(spec.start, next.start)\n              } else {\n                // last one\n                const prev = node.specifiers[i - 1]\n                assert(typeof spec.start === 'number')\n                assert(typeof spec.end === 'number')\n                s.remove(\n                  prev\n                    ? (assert(typeof prev.end === 'number'), prev.end)\n                    : spec.start,\n                  spec.end,\n                )\n              }\n              removed++\n            }\n          }\n          if (removed === node.specifiers.length) {\n            assert(typeof node.start === 'number')\n            assert(typeof node.end === 'number')\n            s.remove(node.start, node.end)\n          }\n        }\n      }\n      code = s.toString()\n\n      // append pkg specific types\n      const additionalTypeDir = `packages/${pkg}/types`\n      if (existsSync(additionalTypeDir)) {\n        code +=\n          '\\n' +\n          readdirSync(additionalTypeDir)\n            .map(file => readFileSync(`${additionalTypeDir}/${file}`, 'utf-8'))\n            .join('\\n')\n      }\n      return code\n    },\n  }\n}\n\n/**\n * According to https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-7.html#packagejson-exports-imports-and-self-referencing\n * the only way to correct provide types for both Node ESM and CJS is to have\n * two separate declaration files, so we need to copy vue.d.ts to vue.d.mts\n * upon build.\n *\n * @returns {import('rollup').Plugin}\n */\nfunction copyMts() {\n  return {\n    name: 'copy-vue-mts',\n    writeBundle(_, bundle) {\n      assert('code' in bundle['vue.d.ts'])\n      writeFileSync('packages/vue/dist/vue.d.mts', bundle['vue.d.ts'].code)\n    },\n  }\n}\n"
  },
  {
    "path": "scripts/aliases.js",
    "content": "// @ts-check\n// these aliases are shared between vitest and rollup\nimport { readdirSync, statSync } from 'node:fs'\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nconst resolveEntryForPkg = (/** @type {string} */ p) =>\n  path.resolve(\n    fileURLToPath(import.meta.url),\n    `../../packages/${p}/src/index.ts`,\n  )\n\nconst dirs = readdirSync(new URL('../packages', import.meta.url))\n\n/** @type {Record<string, string>} */\nconst entries = {\n  vue: resolveEntryForPkg('vue'),\n  'vue/compiler-sfc': resolveEntryForPkg('compiler-sfc'),\n  'vue/server-renderer': resolveEntryForPkg('server-renderer'),\n  '@vue/compat': resolveEntryForPkg('vue-compat'),\n}\n\nconst nonSrcPackages = ['sfc-playground', 'template-explorer', 'dts-test']\n\nfor (const dir of dirs) {\n  const key = `@vue/${dir}`\n  if (\n    dir !== 'vue' &&\n    !nonSrcPackages.includes(dir) &&\n    !(key in entries) &&\n    statSync(new URL(`../packages/${dir}`, import.meta.url)).isDirectory()\n  ) {\n    entries[key] = resolveEntryForPkg(dir)\n  }\n}\n\nexport { entries }\n"
  },
  {
    "path": "scripts/build.js",
    "content": "// @ts-check\n\n/*\nProduces production builds and stitches together d.ts files.\n\nTo specify the package to build, simply pass its name and the desired build\nformats to output (defaults to `buildOptions.formats` specified in that package,\nor \"esm,cjs\"):\n\n```\n# name supports fuzzy match. will build all packages with name containing \"dom\":\nnr build dom\n\n# specify the format to output\nnr build core --formats cjs\n```\n*/\n\nimport fs from 'node:fs'\nimport { parseArgs } from 'node:util'\nimport path from 'node:path'\nimport { brotliCompressSync, gzipSync } from 'node:zlib'\nimport pico from 'picocolors'\nimport { cpus } from 'node:os'\nimport { targets as allTargets, exec, fuzzyMatchTarget } from './utils.js'\nimport { scanEnums } from './inline-enums.js'\nimport prettyBytes from 'pretty-bytes'\nimport { spawnSync } from 'node:child_process'\n\nconst commit = spawnSync('git', ['rev-parse', '--short=7', 'HEAD'])\n  .stdout.toString()\n  .trim()\n\nconst { values, positionals: targets } = parseArgs({\n  allowPositionals: true,\n  options: {\n    formats: {\n      type: 'string',\n      short: 'f',\n    },\n    devOnly: {\n      type: 'boolean',\n      short: 'd',\n    },\n    prodOnly: {\n      type: 'boolean',\n      short: 'p',\n    },\n    withTypes: {\n      type: 'boolean',\n      short: 't',\n    },\n    sourceMap: {\n      type: 'boolean',\n      short: 's',\n    },\n    release: {\n      type: 'boolean',\n    },\n    all: {\n      type: 'boolean',\n      short: 'a',\n    },\n    size: {\n      type: 'boolean',\n    },\n  },\n})\n\nconst {\n  formats,\n  all: buildAllMatching,\n  devOnly,\n  prodOnly,\n  withTypes: buildTypes,\n  sourceMap,\n  release: isRelease,\n  size: writeSize,\n} = values\n\nconst sizeDir = path.resolve('temp/size')\n\nrun()\n\nasync function run() {\n  if (writeSize) fs.mkdirSync(sizeDir, { recursive: true })\n  const removeCache = scanEnums()\n  try {\n    const resolvedTargets = targets.length\n      ? fuzzyMatchTarget(targets, buildAllMatching)\n      : allTargets\n    await buildAll(resolvedTargets)\n    await checkAllSizes(resolvedTargets)\n    if (buildTypes) {\n      await exec(\n        'pnpm',\n        [\n          'run',\n          'build-dts',\n          ...(targets.length\n            ? ['--environment', `TARGETS:${resolvedTargets.join(',')}`]\n            : []),\n        ],\n        {\n          stdio: 'inherit',\n        },\n      )\n    }\n  } finally {\n    removeCache()\n  }\n}\n\n/**\n * Builds all the targets in parallel.\n * @param {Array<string>} targets - An array of targets to build.\n * @returns {Promise<void>} - A promise representing the build process.\n */\nasync function buildAll(targets) {\n  await runParallel(cpus().length, targets, build)\n}\n\n/**\n * Runs iterator function in parallel.\n * @template T - The type of items in the data source\n * @param {number} maxConcurrency - The maximum concurrency.\n * @param {Array<T>} source - The data source\n * @param {(item: T) => Promise<void>} iteratorFn - The iteratorFn\n * @returns {Promise<void[]>} - A Promise array containing all iteration results.\n */\nasync function runParallel(maxConcurrency, source, iteratorFn) {\n  /**@type {Promise<void>[]} */\n  const ret = []\n  /**@type {Promise<void>[]} */\n  const executing = []\n  for (const item of source) {\n    const p = Promise.resolve().then(() => iteratorFn(item))\n    ret.push(p)\n\n    if (maxConcurrency <= source.length) {\n      const e = p.then(() => {\n        executing.splice(executing.indexOf(e), 1)\n      })\n      executing.push(e)\n      if (executing.length >= maxConcurrency) {\n        await Promise.race(executing)\n      }\n    }\n  }\n  return Promise.all(ret)\n}\n\nconst privatePackages = fs.readdirSync('packages-private')\n\n/**\n * Builds the target.\n * @param {string} target - The target to build.\n * @returns {Promise<void>} - A promise representing the build process.\n */\nasync function build(target) {\n  const pkgBase = privatePackages.includes(target)\n    ? `packages-private`\n    : `packages`\n  const pkgDir = path.resolve(`${pkgBase}/${target}`)\n  const pkg = JSON.parse(fs.readFileSync(`${pkgDir}/package.json`, 'utf-8'))\n\n  // if this is a full build (no specific targets), ignore private packages\n  if ((isRelease || !targets.length) && pkg.private) {\n    return\n  }\n\n  // if building a specific format, do not remove dist.\n  if (!formats && fs.existsSync(`${pkgDir}/dist`)) {\n    fs.rmSync(`${pkgDir}/dist`, { recursive: true })\n  }\n\n  const env =\n    (pkg.buildOptions && pkg.buildOptions.env) ||\n    (devOnly ? 'development' : 'production')\n\n  await exec(\n    'rollup',\n    [\n      '-c',\n      '--environment',\n      [\n        `COMMIT:${commit}`,\n        `NODE_ENV:${env}`,\n        `TARGET:${target}`,\n        formats ? `FORMATS:${formats}` : ``,\n        prodOnly ? `PROD_ONLY:true` : ``,\n        sourceMap ? `SOURCE_MAP:true` : ``,\n      ]\n        .filter(Boolean)\n        .join(','),\n    ],\n    { stdio: 'inherit' },\n  )\n}\n\n/**\n * Checks the sizes of all targets.\n * @param {string[]} targets - The targets to check sizes for.\n * @returns {Promise<void>}\n */\nasync function checkAllSizes(targets) {\n  if (devOnly || (formats && !formats.includes('global'))) {\n    return\n  }\n  console.log()\n  for (const target of targets) {\n    await checkSize(target)\n  }\n  console.log()\n}\n\n/**\n * Checks the size of a target.\n * @param {string} target - The target to check the size for.\n * @returns {Promise<void>}\n */\nasync function checkSize(target) {\n  const pkgDir = path.resolve(`packages/${target}`)\n  await checkFileSize(`${pkgDir}/dist/${target}.global.prod.js`)\n  if (!formats || formats.includes('global-runtime')) {\n    await checkFileSize(`${pkgDir}/dist/${target}.runtime.global.prod.js`)\n  }\n}\n\n/**\n * Checks the file size.\n * @param {string} filePath - The path of the file to check the size for.\n * @returns {Promise<void>}\n */\nasync function checkFileSize(filePath) {\n  if (!fs.existsSync(filePath)) {\n    return\n  }\n  const file = fs.readFileSync(filePath)\n  const fileName = path.basename(filePath)\n\n  const gzipped = gzipSync(file)\n  const brotli = brotliCompressSync(file)\n\n  console.log(\n    `${pico.gray(pico.bold(fileName))} min:${prettyBytes(\n      file.length,\n    )} / gzip:${prettyBytes(gzipped.length)} / brotli:${prettyBytes(\n      brotli.length,\n    )}`,\n  )\n\n  if (writeSize)\n    fs.writeFileSync(\n      path.resolve(sizeDir, `${fileName}.json`),\n      JSON.stringify({\n        file: fileName,\n        size: file.length,\n        gzip: gzipped.length,\n        brotli: brotli.length,\n      }),\n      'utf-8',\n    )\n}\n"
  },
  {
    "path": "scripts/dev.js",
    "content": "// @ts-check\n\n// Using esbuild for faster dev builds.\n// We are still using Rollup for production builds because it generates\n// smaller files and provides better tree-shaking.\n\nimport esbuild from 'esbuild'\nimport fs from 'node:fs'\nimport { dirname, relative, resolve } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { createRequire } from 'node:module'\nimport { parseArgs } from 'node:util'\nimport { polyfillNode } from 'esbuild-plugin-polyfill-node'\n\nconst require = createRequire(import.meta.url)\nconst __dirname = dirname(fileURLToPath(import.meta.url))\n\nconst {\n  values: { format: rawFormat, prod, inline: inlineDeps },\n  positionals,\n} = parseArgs({\n  allowPositionals: true,\n  options: {\n    format: {\n      type: 'string',\n      short: 'f',\n      default: 'global',\n    },\n    prod: {\n      type: 'boolean',\n      short: 'p',\n      default: false,\n    },\n    inline: {\n      type: 'boolean',\n      short: 'i',\n      default: false,\n    },\n  },\n})\n\nconst format = rawFormat || 'global'\nconst targets = positionals.length ? positionals : ['vue']\n\n// resolve output\nconst outputFormat = format.startsWith('global')\n  ? 'iife'\n  : format === 'cjs'\n    ? 'cjs'\n    : 'esm'\n\nconst postfix = format.endsWith('-runtime')\n  ? `runtime.${format.replace(/-runtime$/, '')}`\n  : format\n\nconst privatePackages = fs.readdirSync('packages-private')\n\nfor (const target of targets) {\n  const pkgBase = privatePackages.includes(target)\n    ? `packages-private`\n    : `packages`\n  const pkgBasePath = `../${pkgBase}/${target}`\n  const pkg = require(`${pkgBasePath}/package.json`)\n  const outfile = resolve(\n    __dirname,\n    `${pkgBasePath}/dist/${\n      target === 'vue-compat' ? `vue` : target\n    }.${postfix}.${prod ? `prod.` : ``}js`,\n  )\n  const relativeOutfile = relative(process.cwd(), outfile)\n\n  // resolve externals\n  // TODO this logic is largely duplicated from rollup.config.js\n  /** @type {string[]} */\n  let external = []\n  if (!inlineDeps) {\n    // cjs & esm-bundler: external all deps\n    if (format === 'cjs' || format.includes('esm-bundler')) {\n      external = [\n        ...external,\n        ...Object.keys(pkg.dependencies || {}),\n        ...Object.keys(pkg.peerDependencies || {}),\n        // for @vue/compiler-sfc / server-renderer\n        'path',\n        'url',\n        'stream',\n      ]\n    }\n\n    if (target === 'compiler-sfc') {\n      const consolidatePkgPath = require.resolve(\n        '@vue/consolidate/package.json',\n        {\n          paths: [resolve(__dirname, `../packages/${target}/`)],\n        },\n      )\n      const consolidateDeps = Object.keys(\n        require(consolidatePkgPath).devDependencies,\n      )\n      external = [\n        ...external,\n        ...consolidateDeps,\n        'fs',\n        'vm',\n        'crypto',\n        'react-dom/server',\n        'teacup/lib/express',\n        'arc-templates/dist/es5',\n        'then-pug',\n        'then-jade',\n      ]\n    }\n  }\n  /** @type {Array<import('esbuild').Plugin>} */\n  const plugins = [\n    {\n      name: 'log-rebuild',\n      setup(build) {\n        build.onEnd(() => {\n          console.log(`built: ${relativeOutfile}`)\n        })\n      },\n    },\n  ]\n\n  if (format !== 'cjs' && pkg.buildOptions?.enableNonBrowserBranches) {\n    plugins.push(polyfillNode())\n  }\n\n  esbuild\n    .context({\n      entryPoints: [resolve(__dirname, `${pkgBasePath}/src/index.ts`)],\n      outfile,\n      bundle: true,\n      external,\n      sourcemap: true,\n      format: outputFormat,\n      globalName: pkg.buildOptions?.name,\n      platform: format === 'cjs' ? 'node' : 'browser',\n      plugins,\n      define: {\n        __COMMIT__: `\"dev\"`,\n        __VERSION__: `\"${pkg.version}\"`,\n        __DEV__: prod ? `false` : `true`,\n        __TEST__: `false`,\n        __BROWSER__: String(\n          format !== 'cjs' && !pkg.buildOptions?.enableNonBrowserBranches,\n        ),\n        __GLOBAL__: String(format === 'global'),\n        __ESM_BUNDLER__: String(format.includes('esm-bundler')),\n        __ESM_BROWSER__: String(format.includes('esm-browser')),\n        __CJS__: String(format === 'cjs'),\n        __SSR__: String(format !== 'global'),\n        __COMPAT__: String(target === 'vue-compat'),\n        __FEATURE_SUSPENSE__: `true`,\n        __FEATURE_OPTIONS_API__: `true`,\n        __FEATURE_PROD_DEVTOOLS__: `false`,\n        __FEATURE_PROD_HYDRATION_MISMATCH_DETAILS__: `true`,\n      },\n    })\n    .then(ctx => ctx.watch())\n}\n"
  },
  {
    "path": "scripts/inline-enums.js",
    "content": "// @ts-check\n\n/**\n * We used const enums before, but it caused some issues: #1228, so we\n * switched to regular enums. But we still want to keep the zero-cost benefit\n * of const enums, and minimize the impact on bundle size as much as possible.\n *\n * Here we pre-process all the enums in the project and turn them into\n * global replacements, and rewrite the original declarations as object literals.\n *\n * This file is expected to be executed with project root as cwd.\n */\n\nimport * as assert from 'node:assert'\nimport {\n  existsSync,\n  mkdirSync,\n  readFileSync,\n  rmSync,\n  writeFileSync,\n} from 'node:fs'\nimport * as path from 'node:path'\nimport { parse } from '@babel/parser'\nimport { spawnSync } from 'node:child_process'\nimport MagicString from 'magic-string'\n\n/**\n * @typedef {{ readonly name: string, readonly value: string | number }} EnumMember\n * @typedef {{ readonly id: string, readonly range: readonly [start: number, end: number], readonly members: ReadonlyArray<EnumMember>}} EnumDeclaration\n * @typedef {{ readonly declarations: { readonly [file: string] : ReadonlyArray<EnumDeclaration>}, readonly defines: { readonly [ id_key: `${string}.${string}`]: string } }} EnumData\n */\n\nconst ENUM_CACHE_PATH = 'temp/enum.json'\n\n/**\n * @param {string} exp\n * @returns {string | number}\n */\nfunction evaluate(exp) {\n  return new Function(`return ${exp}`)()\n}\n\n// this is called in the build script entry once\n// so the data can be shared across concurrent Rollup processes\nexport function scanEnums() {\n  /** @type {{ [file: string]: EnumDeclaration[] }} */\n  const declarations = Object.create(null)\n  /** @type {{ [id_key: `${string}.${string}`]: string; }} */\n  const defines = Object.create(null)\n\n  // 1. grep for files with exported enum\n  const { stdout } = spawnSync('git', ['grep', `export enum`])\n  const files = [\n    ...new Set(\n      stdout\n        .toString()\n        .trim()\n        .split('\\n')\n        .map(line => line.split(':')[0]),\n    ),\n  ]\n\n  // 2. parse matched files to collect enum info\n  for (const relativeFile of files) {\n    const file = path.resolve(process.cwd(), relativeFile)\n    const content = readFileSync(file, 'utf-8')\n    const ast = parse(content, {\n      plugins: ['typescript'],\n      sourceType: 'module',\n    })\n\n    /** @type {Set<string>} */\n    const enumIds = new Set()\n    for (const node of ast.program.body) {\n      if (\n        node.type === 'ExportNamedDeclaration' &&\n        node.declaration &&\n        node.declaration.type === 'TSEnumDeclaration'\n      ) {\n        const decl = node.declaration\n        const id = decl.id.name\n        if (enumIds.has(id)) {\n          throw new Error(\n            `not support declaration merging for enum ${id} in ${file}`,\n          )\n        }\n        enumIds.add(id)\n        /** @type {string | number | undefined} */\n        let lastInitialized\n        /** @type {Array<EnumMember>} */\n        const members = []\n\n        for (let i = 0; i < decl.members.length; i++) {\n          const e = decl.members[i]\n          const key = e.id.type === 'Identifier' ? e.id.name : e.id.value\n          const fullKey = /** @type {const} */ (`${id}.${key}`)\n          const saveValue = (/** @type {string | number} */ value) => {\n            // We need allow same name enum in different file.\n            // For example: enum ErrorCodes exist in both @vue/compiler-core and @vue/runtime-core\n            // But not allow `ErrorCodes.__EXTEND_POINT__` appear in two same name enum\n            if (fullKey in defines) {\n              throw new Error(`name conflict for enum ${id} in ${file}`)\n            }\n            members.push({\n              name: key,\n              value,\n            })\n            defines[fullKey] = JSON.stringify(value)\n          }\n          const init = e.initializer\n          if (init) {\n            /** @type {string | number} */\n            let value\n            if (\n              init.type === 'StringLiteral' ||\n              init.type === 'NumericLiteral'\n            ) {\n              value = init.value\n            }\n            // e.g. 1 << 2\n            else if (init.type === 'BinaryExpression') {\n              const resolveValue = (\n                /** @type {import('@babel/types').Expression | import('@babel/types').PrivateName} */ node,\n              ) => {\n                assert.ok(typeof node.start === 'number')\n                assert.ok(typeof node.end === 'number')\n                if (\n                  node.type === 'NumericLiteral' ||\n                  node.type === 'StringLiteral'\n                ) {\n                  return node.value\n                } else if (node.type === 'MemberExpression') {\n                  const exp = /** @type {`${string}.${string}`} */ (\n                    content.slice(node.start, node.end)\n                  )\n                  if (!(exp in defines)) {\n                    throw new Error(\n                      `unhandled enum initialization expression ${exp} in ${file}`,\n                    )\n                  }\n                  return defines[exp]\n                } else {\n                  throw new Error(\n                    `unhandled BinaryExpression operand type ${node.type} in ${file}`,\n                  )\n                }\n              }\n              const exp = `${resolveValue(init.left)}${\n                init.operator\n              }${resolveValue(init.right)}`\n              value = evaluate(exp)\n            } else if (init.type === 'UnaryExpression') {\n              if (\n                init.argument.type === 'StringLiteral' ||\n                init.argument.type === 'NumericLiteral'\n              ) {\n                const exp = `${init.operator}${init.argument.value}`\n                value = evaluate(exp)\n              } else {\n                throw new Error(\n                  `unhandled UnaryExpression argument type ${init.argument.type} in ${file}`,\n                )\n              }\n            } else {\n              throw new Error(\n                `unhandled initializer type ${init.type} for ${fullKey} in ${file}`,\n              )\n            }\n            lastInitialized = value\n            saveValue(lastInitialized)\n          } else {\n            if (lastInitialized === undefined) {\n              // first initialized\n              lastInitialized = 0\n              saveValue(lastInitialized)\n            } else if (typeof lastInitialized === 'number') {\n              lastInitialized++\n              saveValue(lastInitialized)\n            } else {\n              // should not happen\n              throw new Error(`wrong enum initialization sequence in ${file}`)\n            }\n          }\n        }\n\n        if (!(file in declarations)) {\n          declarations[file] = []\n        }\n        assert.ok(typeof node.start === 'number')\n        assert.ok(typeof node.end === 'number')\n        declarations[file].push({\n          id,\n          range: [node.start, node.end],\n          members,\n        })\n      }\n    }\n  }\n\n  // 3. save cache\n  if (!existsSync('temp')) mkdirSync('temp')\n\n  /** @type {EnumData} */\n  const enumData = {\n    declarations,\n    defines,\n  }\n\n  writeFileSync(ENUM_CACHE_PATH, JSON.stringify(enumData))\n\n  return () => {\n    rmSync(ENUM_CACHE_PATH, { force: true })\n  }\n}\n\n/**\n * @returns {[import('rollup').Plugin, Record<string, string>]}\n */\nexport function inlineEnums() {\n  if (!existsSync(ENUM_CACHE_PATH)) {\n    throw new Error('enum cache needs to be initialized before creating plugin')\n  }\n  /**\n   * @type {EnumData}\n   */\n  const enumData = JSON.parse(readFileSync(ENUM_CACHE_PATH, 'utf-8'))\n\n  // 3. during transform:\n  //    3.1 files w/ enum declaration: rewrite declaration as object literal\n  //    3.2 files using enum: inject into esbuild define\n  /**\n   * @type {import('rollup').Plugin}\n   */\n  const plugin = {\n    name: 'inline-enum',\n    transform(code, id) {\n      /**\n       * @type {MagicString | undefined}\n       */\n      let s\n\n      if (id in enumData.declarations) {\n        s = s || new MagicString(code)\n        for (const declaration of enumData.declarations[id]) {\n          const {\n            range: [start, end],\n            id,\n            members,\n          } = declaration\n          s.update(\n            start,\n            end,\n            `export const ${id} = {${members\n              .flatMap(({ name, value }) => {\n                const forwardMapping =\n                  JSON.stringify(name) + ': ' + JSON.stringify(value)\n                const reverseMapping =\n                  JSON.stringify(value.toString()) + ': ' + JSON.stringify(name)\n\n                // see https://www.typescriptlang.org/docs/handbook/enums.html#reverse-mappings\n                return typeof value === 'string'\n                  ? [\n                      forwardMapping,\n                      // string enum members do not get a reverse mapping generated at all\n                    ]\n                  : [\n                      forwardMapping,\n                      // other enum members should support enum reverse mapping\n                      reverseMapping,\n                    ]\n              })\n              .join(',\\n')}}`,\n          )\n        }\n      }\n\n      if (s) {\n        return {\n          code: s.toString(),\n          map: s.generateMap(),\n        }\n      }\n    },\n  }\n\n  return [plugin, enumData.defines]\n}\n"
  },
  {
    "path": "scripts/pre-dev-sfc.js",
    "content": "// @ts-check\nimport fs from 'node:fs'\n\nconst packagesToCheck = [\n  'compiler-sfc',\n  'compiler-core',\n  'compiler-dom',\n  'compiler-ssr',\n  'shared',\n]\n\nlet allFilesPresent = true\n\nfor (const pkg of packagesToCheck) {\n  if (\n    !fs.existsSync(\n      new URL(`../packages/${pkg}/dist/${pkg}.cjs.js`, import.meta.url),\n    )\n  ) {\n    allFilesPresent = false\n    break\n  }\n}\n\nif (!allFilesPresent) {\n  process.exit(1)\n}\n"
  },
  {
    "path": "scripts/release.js",
    "content": "// @ts-check\nimport fs from 'node:fs'\nimport path from 'node:path'\nimport pico from 'picocolors'\nimport semver from 'semver'\nimport enquirer from 'enquirer'\nimport { createRequire } from 'node:module'\nimport { fileURLToPath } from 'node:url'\nimport { exec } from './utils.js'\nimport { parseArgs } from 'node:util'\n\n/**\n * @typedef {{\n *   name: string\n *   version: string\n *   dependencies?: { [dependenciesPackageName: string]: string }\n *   peerDependencies?: { [peerDependenciesPackageName: string]: string }\n * }} Package\n */\n\nlet versionUpdated = false\n\nconst { prompt } = enquirer\nconst currentVersion = createRequire(import.meta.url)('../package.json').version\nconst __dirname = path.dirname(fileURLToPath(import.meta.url))\n\nconst { values: args, positionals } = parseArgs({\n  allowPositionals: true,\n  options: {\n    preid: {\n      type: 'string',\n    },\n    dry: {\n      type: 'boolean',\n    },\n    tag: {\n      type: 'string',\n    },\n    skipBuild: {\n      type: 'boolean',\n    },\n    skipTests: {\n      type: 'boolean',\n    },\n    skipGit: {\n      type: 'boolean',\n    },\n    skipPrompts: {\n      type: 'boolean',\n    },\n    publish: {\n      type: 'boolean',\n      default: false,\n    },\n    publishOnly: {\n      type: 'boolean',\n    },\n    registry: {\n      type: 'string',\n    },\n  },\n})\n\nconst preId = args.preid || semver.prerelease(currentVersion)?.[0]\nconst isDryRun = args.dry\n/** @type {boolean | undefined} */\nlet skipTests = args.skipTests\nconst skipBuild = args.skipBuild\nconst skipPrompts = args.skipPrompts\nconst skipGit = args.skipGit\n\nconst packages = fs\n  .readdirSync(path.resolve(__dirname, '../packages'))\n  .filter(p => {\n    const pkgRoot = path.resolve(__dirname, '../packages', p)\n    if (fs.statSync(pkgRoot).isDirectory()) {\n      const pkg = JSON.parse(\n        fs.readFileSync(path.resolve(pkgRoot, 'package.json'), 'utf-8'),\n      )\n      return !pkg.private\n    }\n  })\n\nconst isCorePackage = (/** @type {string} */ pkgName) => {\n  if (!pkgName) return\n\n  if (pkgName === 'vue' || pkgName === '@vue/compat') {\n    return true\n  }\n\n  return (\n    pkgName.startsWith('@vue') &&\n    packages.includes(pkgName.replace(/^@vue\\//, ''))\n  )\n}\n\nconst keepThePackageName = (/** @type {string} */ pkgName) => pkgName\n\n/** @type {string[]} */\nconst skippedPackages = []\n\n/** @type {ReadonlyArray<import('semver').ReleaseType>} */\nconst versionIncrements = [\n  'patch',\n  'minor',\n  'major',\n  ...(preId\n    ? /** @type {const} */ (['prepatch', 'preminor', 'premajor', 'prerelease'])\n    : []),\n]\n\nconst inc = (/** @type {import('semver').ReleaseType} */ i) =>\n  semver.inc(currentVersion, i, typeof preId === 'string' ? preId : undefined)\nconst run = async (\n  /** @type {string} */ bin,\n  /** @type {ReadonlyArray<string>} */ args,\n  /** @type {import('node:child_process').SpawnOptions} */ opts = {},\n) => exec(bin, args, { stdio: 'inherit', ...opts })\nconst dryRun = async (\n  /** @type {string} */ bin,\n  /** @type {ReadonlyArray<string>} */ args,\n  /** @type {import('node:child_process').SpawnOptions} */ opts = {},\n) => console.log(pico.blue(`[dryrun] ${bin} ${args.join(' ')}`), opts)\nconst runIfNotDry = isDryRun ? dryRun : run\nconst getPkgRoot = (/** @type {string} */ pkg) =>\n  path.resolve(__dirname, '../packages/' + pkg)\nconst step = (/** @type {string} */ msg) => console.log(pico.cyan(msg))\n\nasync function main() {\n  if (!(await isInSyncWithRemote())) {\n    return\n  } else {\n    console.log(`${pico.green(`✓`)} commit is up-to-date with remote.\\n`)\n  }\n\n  let targetVersion = positionals[0]\n\n  if (!targetVersion) {\n    // no explicit version, offer suggestions\n    /** @type {{ release: string }} */\n    const { release } = await prompt({\n      type: 'select',\n      name: 'release',\n      message: 'Select release type',\n      choices: versionIncrements\n        .map(i => `${i} (${inc(i)})`)\n        .concat(['custom']),\n    })\n\n    if (release === 'custom') {\n      /** @type {{ version: string }} */\n      const result = await prompt({\n        type: 'input',\n        name: 'version',\n        message: 'Input custom version',\n        initial: currentVersion,\n      })\n      targetVersion = result.version\n    } else {\n      targetVersion = release.match(/\\((.*)\\)/)?.[1] ?? ''\n    }\n  }\n\n  // @ts-expect-error\n  if (versionIncrements.includes(targetVersion)) {\n    // @ts-expect-error\n    targetVersion = inc(targetVersion)\n  }\n\n  if (!semver.valid(targetVersion)) {\n    throw new Error(`invalid target version: ${targetVersion}`)\n  }\n\n  if (skipPrompts) {\n    step(`Releasing v${targetVersion}...`)\n  } else {\n    /** @type {{ yes: boolean }} */\n    const { yes: confirmRelease } = await prompt({\n      type: 'confirm',\n      name: 'yes',\n      message: `Releasing v${targetVersion}. Confirm?`,\n    })\n\n    if (!confirmRelease) {\n      return\n    }\n  }\n\n  await runTestsIfNeeded()\n\n  // update all package versions and inter-dependencies\n  step('\\nUpdating cross dependencies...')\n  updateVersions(targetVersion, keepThePackageName)\n  versionUpdated = true\n\n  // generate changelog\n  step('\\nGenerating changelog...')\n  await run(`pnpm`, ['run', 'changelog'])\n\n  if (!skipPrompts) {\n    /** @type {{ yes: boolean }} */\n    const { yes: changelogOk } = await prompt({\n      type: 'confirm',\n      name: 'yes',\n      message: `Changelog generated. Does it look good?`,\n    })\n\n    if (!changelogOk) {\n      return\n    }\n  }\n\n  // update pnpm-lock.yaml\n  step('\\nUpdating lockfile...')\n  await run(`pnpm`, ['install', '--prefer-offline'])\n\n  if (!skipGit) {\n    const { stdout } = await run('git', ['diff'], { stdio: 'pipe' })\n    if (stdout) {\n      step('\\nCommitting changes...')\n      await runIfNotDry('git', ['add', '-A'])\n      await runIfNotDry('git', ['commit', '-m', `release: v${targetVersion}`])\n    } else {\n      console.log('No changes to commit.')\n    }\n  }\n\n  // publish packages\n  if (args.publish) {\n    await buildPackages()\n    await publishPackages(targetVersion)\n  }\n\n  // push to GitHub\n  if (!skipGit) {\n    step('\\nPushing to GitHub...')\n    await runIfNotDry('git', ['tag', `v${targetVersion}`])\n    await runIfNotDry('git', ['push', 'origin', `refs/tags/v${targetVersion}`])\n    await runIfNotDry('git', ['push'])\n  }\n\n  if (!args.publish) {\n    console.log(\n      pico.yellow(\n        '\\nRelease will be done via GitHub Actions.\\n' +\n          'Check status at https://github.com/vuejs/core/actions/workflows/release.yml',\n      ),\n    )\n  }\n\n  if (isDryRun) {\n    console.log(`\\nDry run finished - run git diff to see package changes.`)\n  }\n\n  if (skippedPackages.length) {\n    console.log(\n      pico.yellow(\n        `The following packages are skipped and NOT published:\\n- ${skippedPackages.join(\n          '\\n- ',\n        )}`,\n      ),\n    )\n  }\n  console.log()\n}\n\nasync function runTestsIfNeeded() {\n  if (!skipTests) {\n    step('Checking CI status for HEAD...')\n    let isCIPassed = await getCIResult()\n    skipTests ||= isCIPassed\n\n    if (isCIPassed) {\n      if (!skipPrompts) {\n        /** @type {{ yes: boolean }} */\n        const { yes: promptSkipTests } = await prompt({\n          type: 'confirm',\n          name: 'yes',\n          message: `CI for this commit passed. Skip local tests?`,\n        })\n        skipTests = promptSkipTests\n      } else {\n        skipTests = true\n      }\n    } else if (skipPrompts) {\n      throw new Error(\n        'CI for the latest commit has not passed yet. ' +\n          'Only run the release workflow after the CI has passed.',\n      )\n    }\n  }\n\n  if (!skipTests) {\n    step('\\nRunning tests...')\n    if (!isDryRun) {\n      await run('pnpm', ['run', 'test', '--run'])\n    } else {\n      console.log(`Skipped (dry run)`)\n    }\n  } else {\n    step('Tests skipped.')\n  }\n}\n\nasync function getCIResult() {\n  try {\n    const sha = await getSha()\n    const res = await fetch(\n      `https://api.github.com/repos/vuejs/core/actions/runs?head_sha=${sha}` +\n        `&status=success&exclude_pull_requests=true`,\n    )\n    /** @type {{ workflow_runs: ({ name: string, conclusion: string })[] }} */\n    const data = await res.json()\n    return data.workflow_runs.some(({ name, conclusion }) => {\n      return name === 'ci' && conclusion === 'success'\n    })\n  } catch {\n    console.error('Failed to get CI status for current commit.')\n    return false\n  }\n}\n\nasync function isInSyncWithRemote() {\n  try {\n    const branch = await getBranch()\n    const res = await fetch(\n      `https://api.github.com/repos/vuejs/core/commits/${branch}?per_page=1`,\n    )\n    const data = await res.json()\n    if (data.sha === (await getSha())) {\n      return true\n    } else {\n      /** @type {{ yes: boolean }} */\n      const { yes } = await prompt({\n        type: 'confirm',\n        name: 'yes',\n        message: pico.red(\n          `Local HEAD is not up-to-date with remote. Are you sure you want to continue?`,\n        ),\n      })\n      return yes\n    }\n  } catch {\n    console.error(\n      pico.red('Failed to check whether local HEAD is up-to-date with remote.'),\n    )\n    return false\n  }\n}\n\nasync function getSha() {\n  return (await exec('git', ['rev-parse', 'HEAD'])).stdout\n}\n\nasync function getBranch() {\n  return (await exec('git', ['rev-parse', '--abbrev-ref', 'HEAD'])).stdout\n}\n\n/**\n * @param {string} version\n * @param {(pkgName: string) => string} getNewPackageName\n */\nfunction updateVersions(version, getNewPackageName = keepThePackageName) {\n  // 1. update root package.json\n  updatePackage(path.resolve(__dirname, '..'), version, getNewPackageName)\n  // 2. update all packages\n  packages.forEach(p =>\n    updatePackage(getPkgRoot(p), version, getNewPackageName),\n  )\n}\n\n/**\n * @param {string} pkgRoot\n * @param {string} version\n * @param {(pkgName: string) => string} getNewPackageName\n */\nfunction updatePackage(pkgRoot, version, getNewPackageName) {\n  const pkgPath = path.resolve(pkgRoot, 'package.json')\n  /** @type {Package} */\n  const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'))\n  pkg.name = getNewPackageName(pkg.name)\n  pkg.version = version\n  fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\\n')\n}\n\nasync function buildPackages() {\n  step('\\nBuilding all packages...')\n  if (!skipBuild) {\n    await run('pnpm', ['run', 'build', '--withTypes'])\n  } else {\n    console.log(`(skipped)`)\n  }\n}\n\n/**\n * @param {string} version\n */\nasync function publishPackages(version) {\n  // publish packages\n  step('\\nPublishing packages...')\n\n  const additionalPublishFlags = []\n  if (isDryRun) {\n    additionalPublishFlags.push('--dry-run')\n  }\n  if (isDryRun || skipGit || process.env.CI) {\n    additionalPublishFlags.push('--no-git-checks')\n  }\n  // add provenance metadata when releasing from CI\n  // skip provenance if not publishing to actual npm\n  if (process.env.CI && !args.registry) {\n    additionalPublishFlags.push('--provenance')\n  }\n\n  for (const pkg of packages) {\n    await publishPackage(pkg, version, additionalPublishFlags)\n  }\n}\n\n/**\n * @param {string} pkgName\n * @param {string} version\n * @param {ReadonlyArray<string>} additionalFlags\n */\nasync function publishPackage(pkgName, version, additionalFlags) {\n  if (skippedPackages.includes(pkgName)) {\n    return\n  }\n\n  let releaseTag = null\n  if (args.tag) {\n    releaseTag = args.tag\n  } else if (version.includes('alpha')) {\n    releaseTag = 'alpha'\n  } else if (version.includes('beta')) {\n    releaseTag = 'beta'\n  } else if (version.includes('rc')) {\n    releaseTag = 'rc'\n  }\n\n  step(`Publishing ${pkgName}...`)\n  try {\n    // Don't change the package manager here as we rely on pnpm to handle\n    // workspace:* deps\n    await run(\n      'pnpm',\n      [\n        'publish',\n        ...(releaseTag ? ['--tag', releaseTag] : []),\n        '--access',\n        'public',\n        ...(args.registry ? ['--registry', args.registry] : []),\n        ...additionalFlags,\n      ],\n      {\n        cwd: getPkgRoot(pkgName),\n        stdio: 'pipe',\n      },\n    )\n    console.log(pico.green(`Successfully published ${pkgName}@${version}`))\n  } catch (/** @type {any} */ e) {\n    if (e.message?.match(/previously published/)) {\n      console.log(pico.red(`Skipping already published: ${pkgName}`))\n    } else {\n      throw e\n    }\n  }\n}\n\nasync function publishOnly() {\n  const targetVersion = positionals[0]\n  if (targetVersion) {\n    updateVersions(targetVersion)\n  }\n  await buildPackages()\n  await publishPackages(currentVersion)\n}\n\nconst fnToRun = args.publishOnly ? publishOnly : main\n\nfnToRun().catch(err => {\n  if (versionUpdated) {\n    // revert to current version on failed releases\n    updateVersions(currentVersion)\n  }\n  console.error(err)\n  process.exit(1)\n})\n"
  },
  {
    "path": "scripts/setup-vitest.ts",
    "content": "import type { MockInstance } from 'vitest'\n\ndeclare module 'vitest' {\n  interface Assertion<T = any> extends CustomMatchers<T> {}\n  interface AsymmetricMatchersContaining extends CustomMatchers {}\n}\n\ninterface CustomMatchers<R = unknown> {\n  toHaveBeenWarned(): R\n  toHaveBeenWarnedLast(): R\n  toHaveBeenWarnedTimes(n: number): R\n}\n\nvi.stubGlobal('MathMLElement', class MathMLElement {})\n\nexpect.extend({\n  toHaveBeenWarned(received: string) {\n    const passed = warn.mock.calls.some(args => args[0].includes(received))\n    if (passed) {\n      asserted.add(received)\n      return {\n        pass: true,\n        message: () => `expected \"${received}\" not to have been warned.`,\n      }\n    } else {\n      const msgs = warn.mock.calls.map(args => args[0]).join('\\n - ')\n      return {\n        pass: false,\n        message: () =>\n          `expected \"${received}\" to have been warned` +\n          (msgs.length\n            ? `.\\n\\nActual messages:\\n\\n - ${msgs}`\n            : ` but no warning was recorded.`),\n      }\n    }\n  },\n\n  toHaveBeenWarnedLast(received: string) {\n    const passed =\n      warn.mock.calls[warn.mock.calls.length - 1][0].includes(received)\n    if (passed) {\n      asserted.add(received)\n      return {\n        pass: true,\n        message: () => `expected \"${received}\" not to have been warned last.`,\n      }\n    } else {\n      const msgs = warn.mock.calls.map(args => args[0]).join('\\n - ')\n      return {\n        pass: false,\n        message: () =>\n          `expected \"${received}\" to have been warned last.\\n\\nActual messages:\\n\\n - ${msgs}`,\n      }\n    }\n  },\n\n  toHaveBeenWarnedTimes(received: string, n: number) {\n    let found = 0\n    warn.mock.calls.forEach(args => {\n      if (args[0].includes(received)) {\n        found++\n      }\n    })\n\n    if (found === n) {\n      asserted.add(received)\n      return {\n        pass: true,\n        message: () => `expected \"${received}\" to have been warned ${n} times.`,\n      }\n    } else {\n      return {\n        pass: false,\n        message: () =>\n          `expected \"${received}\" to have been warned ${n} times but got ${found}.`,\n      }\n    }\n  },\n})\n\nlet warn: MockInstance\nconst asserted: Set<string> = new Set()\n\nbeforeEach(() => {\n  asserted.clear()\n  warn = vi.spyOn(console, 'warn')\n  warn.mockImplementation(() => {})\n})\n\nafterEach(() => {\n  const assertedArray = Array.from(asserted)\n  const nonAssertedWarnings = warn.mock.calls\n    .map(args => args[0])\n    .filter(received => {\n      return !assertedArray.some(assertedMsg => {\n        return received.includes(assertedMsg)\n      })\n    })\n  warn.mockRestore()\n  if (nonAssertedWarnings.length) {\n    throw new Error(\n      `test case threw unexpected warnings:\\n - ${nonAssertedWarnings.join(\n        '\\n - ',\n      )}`,\n    )\n  }\n})\n"
  },
  {
    "path": "scripts/size-report.js",
    "content": "// @ts-check\nimport path from 'node:path'\nimport { markdownTable } from 'markdown-table'\nimport prettyBytes from 'pretty-bytes'\nimport { readdir } from 'node:fs/promises'\nimport { existsSync } from 'node:fs'\n\n/**\n * @typedef {Object} SizeResult\n * @property {number} size\n * @property {number} gzip\n * @property {number} brotli\n */\n\n/**\n * @typedef {SizeResult & { file: string }} BundleResult\n */\n\n/**\n * @typedef {Record<string, SizeResult & { name: string }>} UsageResult\n */\n\nconst currDir = path.resolve('temp/size')\nconst prevDir = path.resolve('temp/size-prev')\nlet output = '## Size Report\\n\\n'\nconst sizeHeaders = ['Size', 'Gzip', 'Brotli']\n\nrun()\n\n/**\n * Runs the main process of rendering file and usage data\n */\nasync function run() {\n  await renderFiles()\n  await renderUsages()\n\n  process.stdout.write(output)\n}\n\n/**\n * Renders file sizes and diffs between current and previous versions\n */\nasync function renderFiles() {\n  const filterFiles = files =>\n    files.filter(file => file[0] !== '_' && !file.endsWith('.txt'))\n\n  const curr = filterFiles(await readdir(currDir))\n  const prev = existsSync(prevDir) ? filterFiles(await readdir(prevDir)) : []\n  const fileList = new Set([...curr, ...prev])\n\n  const rows = []\n  for (const file of fileList) {\n    const currPath = path.resolve(currDir, file)\n    const prevPath = path.resolve(prevDir, file)\n\n    const curr = await importJSON(currPath)\n    const prev = await importJSON(prevPath)\n    const fileName = curr?.file || prev?.file || ''\n\n    if (!curr) {\n      rows.push([`~~${fileName}~~`])\n    } else {\n      rows.push([\n        fileName,\n        `${prettyBytes(curr.size)}${getDiff(curr.size, prev?.size)}`,\n        `${prettyBytes(curr.gzip)}${getDiff(curr.gzip, prev?.gzip)}`,\n        `${prettyBytes(curr.brotli)}${getDiff(curr.brotli, prev?.brotli)}`,\n      ])\n    }\n  }\n\n  output += '### Bundles\\n\\n'\n  output += markdownTable([['File', ...sizeHeaders], ...rows])\n  output += '\\n\\n'\n}\n\n/**\n * Renders usage data comparing current and previous usage results\n */\nasync function renderUsages() {\n  const curr = await importJSON(path.resolve(currDir, '_usages.json'))\n  const prev = await importJSON(path.resolve(prevDir, '_usages.json'))\n\n  output += '\\n### Usages\\n\\n'\n\n  const data = Object.values(curr)\n    .map(usage => {\n      const prevUsage = prev?.[usage.name]\n      const diffSize = getDiff(usage.size, prevUsage?.size)\n      const diffGzipped = getDiff(usage.gzip, prevUsage?.gzip)\n      const diffBrotli = getDiff(usage.brotli, prevUsage?.brotli)\n\n      return [\n        usage.name,\n        `${prettyBytes(usage.size)}${diffSize}`,\n        `${prettyBytes(usage.gzip)}${diffGzipped}`,\n        `${prettyBytes(usage.brotli)}${diffBrotli}`,\n      ]\n    })\n    .filter(usage => !!usage)\n\n  output += `${markdownTable([['Name', ...sizeHeaders], ...data])}\\n\\n`\n}\n\n/**\n * Imports JSON data from a specified path\n *\n * @template T\n * @param {string} filePath - Path to the JSON file\n * @returns {Promise<T | undefined>} The JSON content or undefined if the file does not exist\n */\nasync function importJSON(filePath) {\n  if (!existsSync(filePath)) return undefined\n  return (await import(filePath, { with: { type: 'json' } })).default\n}\n\n/**\n * Calculates the difference between the current and previous sizes\n *\n * @param {number} curr - The current size\n * @param {number} [prev] - The previous size\n * @returns {string} The difference in pretty format\n */\nfunction getDiff(curr, prev) {\n  if (prev === undefined) return ''\n  const diff = curr - prev\n  if (diff === 0) return ''\n  const sign = diff > 0 ? '+' : ''\n  return ` (**${sign}${prettyBytes(diff)}**)`\n}\n"
  },
  {
    "path": "scripts/usage-size.js",
    "content": "// @ts-check\nimport { mkdir, writeFile } from 'node:fs/promises'\nimport path from 'node:path'\nimport { rollup } from 'rollup'\nimport nodeResolve from '@rollup/plugin-node-resolve'\nimport { minify } from '@swc/core'\nimport replace from '@rollup/plugin-replace'\nimport { brotliCompressSync, gzipSync } from 'node:zlib'\nimport { parseArgs } from 'node:util'\nimport pico from 'picocolors'\nimport prettyBytes from 'pretty-bytes'\n\nconst {\n  values: { write },\n} = parseArgs({\n  options: {\n    write: {\n      type: 'boolean',\n      default: false,\n    },\n  },\n})\n\nconst sizeDir = path.resolve('temp/size')\nconst entry = path.resolve('./packages/vue/dist/vue.runtime.esm-bundler.js')\n\n/**\n * @typedef {Object} Preset\n * @property {string} name - The name of the preset\n * @property {string[]} imports - The imports that are part of this preset\n * @property {Record<string, string>} [replace]\n */\n\n/** @type {Preset[]} */\nconst presets = [\n  {\n    name: 'createApp (CAPI only)',\n    imports: ['createApp'],\n    replace: { __VUE_OPTIONS_API__: 'false' },\n  },\n  { name: 'createApp', imports: ['createApp'] },\n  { name: 'createSSRApp', imports: ['createSSRApp'] },\n  { name: 'defineCustomElement', imports: ['defineCustomElement'] },\n  {\n    name: 'overall',\n    imports: [\n      'createApp',\n      'ref',\n      'watch',\n      'Transition',\n      'KeepAlive',\n      'Suspense',\n    ],\n  },\n]\n\nmain()\n\n/**\n * Main function that initiates the bundling process for the presets\n */\nasync function main() {\n  console.log()\n  /** @type {Promise<{name: string, size: number, gzip: number, brotli: number}>[]} */\n  const tasks = []\n  for (const preset of presets) {\n    tasks.push(generateBundle(preset))\n  }\n  const results = await Promise.all(tasks)\n\n  for (const r of results) {\n    console.log(\n      `${pico.green(pico.bold(r.name))} - ` +\n        `min:${prettyBytes(r.size, { minimumFractionDigits: 3 })} / ` +\n        `gzip:${prettyBytes(r.gzip, { minimumFractionDigits: 3 })} / ` +\n        `brotli:${prettyBytes(r.brotli, { minimumFractionDigits: 3 })}`,\n    )\n  }\n\n  await mkdir(sizeDir, { recursive: true })\n  await writeFile(\n    path.resolve(sizeDir, '_usages.json'),\n    JSON.stringify(Object.fromEntries(results.map(r => [r.name, r])), null, 2),\n    'utf-8',\n  )\n}\n\n/**\n * Generates a bundle for a given preset\n *\n * @param {Preset} preset - The preset to generate the bundle for\n * @returns {Promise<{name: string, size: number, gzip: number, brotli: number}>} - The result of the bundling process\n */\nasync function generateBundle(preset) {\n  const id = 'virtual:entry'\n  const content = `export { ${preset.imports.join(', ')} } from '${entry}'`\n\n  const result = await rollup({\n    input: id,\n    plugins: [\n      {\n        name: 'usage-size-plugin',\n        resolveId(_id) {\n          if (_id === id) return id\n          return null\n        },\n        load(_id) {\n          if (_id === id) return content\n        },\n      },\n      nodeResolve(),\n      replace({\n        'process.env.NODE_ENV': '\"production\"',\n        __VUE_PROD_DEVTOOLS__: 'false',\n        __VUE_PROD_HYDRATION_MISMATCH_DETAILS__: 'false',\n        __VUE_OPTIONS_API__: 'true',\n        preventAssignment: true,\n        ...preset.replace,\n      }),\n    ],\n  })\n\n  const generated = await result.generate({})\n  const bundled = generated.output[0].code\n  const minified = (\n    await minify(bundled, {\n      module: true,\n      toplevel: true,\n    })\n  ).code\n\n  const size = minified.length\n  const gzip = gzipSync(minified).length\n  const brotli = brotliCompressSync(minified).length\n\n  if (write) {\n    await writeFile(path.resolve(sizeDir, preset.name + '.js'), bundled)\n  }\n\n  return {\n    name: preset.name,\n    size,\n    gzip,\n    brotli,\n  }\n}\n"
  },
  {
    "path": "scripts/utils.js",
    "content": "// @ts-check\nimport fs from 'node:fs'\nimport pico from 'picocolors'\nimport { createRequire } from 'node:module'\nimport { spawn } from 'node:child_process'\n\nconst require = createRequire(import.meta.url)\n\nexport const targets = fs\n  .readdirSync('packages')\n  .filter(f => {\n    if (\n      !fs.statSync(`packages/${f}`).isDirectory() ||\n      !fs.existsSync(`packages/${f}/package.json`)\n    ) {\n      return false\n    }\n    const pkg = require(`../packages/${f}/package.json`)\n    if (pkg.private && !pkg.buildOptions) {\n      return false\n    }\n    return true\n  })\n  .concat('template-explorer')\n\n/**\n *\n * @param {ReadonlyArray<string>} partialTargets\n * @param {boolean | undefined} includeAllMatching\n */\nexport function fuzzyMatchTarget(partialTargets, includeAllMatching) {\n  /** @type {Array<string>} */\n  const matched = []\n  partialTargets.forEach(partialTarget => {\n    for (const target of targets) {\n      if (target.match(partialTarget)) {\n        matched.push(target)\n        if (!includeAllMatching) {\n          break\n        }\n      }\n    }\n  })\n  if (matched.length) {\n    return matched\n  } else {\n    console.log()\n    console.error(\n      `  ${pico.white(pico.bgRed(' ERROR '))} ${pico.red(\n        `Target ${pico.underline(partialTargets.toString())} not found!`,\n      )}`,\n    )\n    console.log()\n\n    process.exit(1)\n  }\n}\n\n/**\n * @param {string} command\n * @param {ReadonlyArray<string>} args\n * @param {object} [options]\n */\nexport async function exec(command, args, options) {\n  return new Promise((resolve, reject) => {\n    const _process = spawn(command, args, {\n      stdio: [\n        'ignore', // stdin\n        'pipe', // stdout\n        'pipe', // stderr\n      ],\n      ...options,\n      shell: process.platform === 'win32',\n    })\n\n    /**\n     * @type {Buffer[]}\n     */\n    const stderrChunks = []\n    /**\n     * @type {Buffer[]}\n     */\n    const stdoutChunks = []\n\n    _process.stderr?.on('data', chunk => {\n      stderrChunks.push(chunk)\n    })\n\n    _process.stdout?.on('data', chunk => {\n      stdoutChunks.push(chunk)\n    })\n\n    _process.on('error', error => {\n      reject(error)\n    })\n\n    _process.on('exit', code => {\n      const ok = code === 0\n      const stderr = Buffer.concat(stderrChunks).toString().trim()\n      const stdout = Buffer.concat(stdoutChunks).toString().trim()\n\n      if (ok) {\n        const result = { ok, code, stderr, stdout }\n        resolve(result)\n      } else {\n        reject(\n          new Error(\n            `Failed to execute command: ${command} ${args.join(' ')}: ${stderr}`,\n          ),\n        )\n      }\n    })\n  })\n}\n"
  },
  {
    "path": "scripts/verify-commit.js",
    "content": "// @ts-check\nimport pico from 'picocolors'\nimport { readFileSync } from 'node:fs'\nimport path from 'node:path'\n\nconst msgPath = path.resolve('.git/COMMIT_EDITMSG')\nconst msg = readFileSync(msgPath, 'utf-8').trim()\n\nconst commitRE =\n  /^(revert: )?(feat|fix|docs|dx|style|refactor|perf|test|workflow|build|ci|chore|types|wip|release)(\\(.+\\))?: .{1,50}/\n\nif (!commitRE.test(msg)) {\n  console.log()\n  console.error(\n    `  ${pico.white(pico.bgRed(' ERROR '))} ${pico.red(\n      `invalid commit message format.`,\n    )}\\n\\n` +\n      pico.red(\n        `  Proper commit message format is required for automated changelog generation. Examples:\\n\\n`,\n      ) +\n      `    ${pico.green(`feat(compiler): add 'comments' option`)}\\n` +\n      `    ${pico.green(\n        `fix(v-model): handle events on blur (close #28)`,\n      )}\\n\\n` +\n      pico.red(`  See .github/commit-convention.md for more details.\\n`),\n  )\n  process.exit(1)\n}\n"
  },
  {
    "path": "scripts/verify-treeshaking.js",
    "content": "// @ts-check\nimport fs from 'node:fs'\nimport { exec } from './utils.js'\n\nexec('pnpm', ['build', 'vue', '-f', 'global-runtime']).then(() => {\n  const errors = []\n\n  const devBuild = fs.readFileSync(\n    'packages/vue/dist/vue.runtime.global.js',\n    'utf-8',\n  )\n\n  if (devBuild.includes('__spreadValues')) {\n    errors.push(\n      'dev build contains unexpected esbuild object spread helper.\\n' +\n        'This means { ...obj } syntax is used in runtime code. This should be ' +\n        'refactored to use the `extend` helper to avoid the extra code.',\n    )\n  }\n\n  const prodBuild = fs.readFileSync(\n    'packages/vue/dist/vue.runtime.global.prod.js',\n    'utf-8',\n  )\n\n  if (prodBuild.includes('Vue warn')) {\n    errors.push(\n      'prod build contains unexpected warning-related code.\\n' +\n        'This means there are calls of warn() that are not guarded by the __DEV__ condition.',\n    )\n  }\n\n  if (\n    prodBuild.includes('html,body,base') ||\n    prodBuild.includes('svg,animate,animateMotion') ||\n    prodBuild.includes('annotation,annotation-xml,maction')\n  ) {\n    errors.push(\n      'prod build contains unexpected domTagConfig lists.\\n' +\n        'This means helpers like isHTMLTag() is used in runtime code paths when it should be compiler-only.',\n    )\n  }\n\n  if (errors.length) {\n    throw new Error(\n      `Found the following treeshaking errors:\\n\\n- ${errors.join('\\n\\n- ')}`,\n    )\n  }\n})\n"
  },
  {
    "path": "tsconfig.build.json",
    "content": "{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"types\": [\"node\"],\n    \"declaration\": true,\n    \"emitDeclarationOnly\": true,\n    \"stripInternal\": true,\n    \"composite\": false\n  },\n  \"include\": [\n    \"packages/global.d.ts\",\n    \"packages/vue/src\",\n    \"packages/vue-compat/src\",\n    \"packages/compiler-core/src\",\n    \"packages/compiler-dom/src\",\n    \"packages/runtime-core/src\",\n    \"packages/runtime-dom/src\",\n    \"packages/reactivity/src\",\n    \"packages/shared/src\",\n    \"packages/compiler-sfc/src\",\n    \"packages/compiler-ssr/src\",\n    \"packages/server-renderer/src\"\n  ]\n}\n"
  },
  {
    "path": "tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"baseUrl\": \".\",\n    \"outDir\": \"temp\",\n    \"sourceMap\": false,\n    \"target\": \"es2016\",\n    \"newLine\": \"LF\",\n    \"useDefineForClassFields\": false,\n    \"module\": \"esnext\",\n    \"moduleResolution\": \"bundler\",\n    \"allowJs\": false,\n    \"strict\": true,\n    \"noUnusedLocals\": true,\n    \"experimentalDecorators\": true,\n    \"resolveJsonModule\": true,\n    \"isolatedModules\": true,\n    \"skipLibCheck\": true,\n    \"esModuleInterop\": true,\n    \"removeComments\": false,\n    \"jsx\": \"preserve\",\n    \"lib\": [\"es2016\", \"dom\"],\n    \"types\": [\"vitest/globals\", \"puppeteer\", \"node\"],\n    \"rootDir\": \".\",\n    \"paths\": {\n      \"@vue/compat\": [\"packages/vue-compat/src\"],\n      \"@vue/*\": [\"packages/*/src\"],\n      \"vue\": [\"packages/vue/src\"]\n    },\n    \"isolatedDeclarations\": true,\n    \"composite\": true\n  },\n  \"include\": [\n    \"packages/global.d.ts\",\n    \"packages/*/src\",\n    \"packages/*/__tests__\",\n    \"packages/vue/jsx-runtime\",\n    \"packages/runtime-dom/types/jsx.d.ts\",\n    \"scripts/*\",\n    \"rollup.*.js\"\n  ],\n  \"exclude\": [\"packages-private/sfc-playground/src/vue-dev-proxy*\"]\n}\n"
  },
  {
    "path": "vitest.config.ts",
    "content": "import { configDefaults, defineConfig } from 'vitest/config'\nimport { entries } from './scripts/aliases.js'\n\nexport default defineConfig({\n  define: {\n    __DEV__: true,\n    __TEST__: true,\n    __VERSION__: '\"test\"',\n    __BROWSER__: false,\n    __GLOBAL__: false,\n    __ESM_BUNDLER__: true,\n    __ESM_BROWSER__: false,\n    __CJS__: true,\n    __SSR__: true,\n    __FEATURE_OPTIONS_API__: true,\n    __FEATURE_SUSPENSE__: true,\n    __FEATURE_PROD_DEVTOOLS__: false,\n    __FEATURE_PROD_HYDRATION_MISMATCH_DETAILS__: false,\n    __COMPAT__: true,\n  },\n  resolve: {\n    alias: entries,\n  },\n  test: {\n    globals: true,\n    pool: 'threads',\n    setupFiles: 'scripts/setup-vitest.ts',\n    sequence: {\n      hooks: 'list',\n    },\n    coverage: {\n      provider: 'v8',\n      reporter: ['text', 'html'],\n      include: ['packages/*/src/**'],\n      exclude: [\n        // entries that are not really used during tests\n        'packages/vue-compat/**',\n        'packages/vue/src/dev.ts',\n        'packages/vue/src/runtime.ts',\n        // not testable during unit tests\n        'packages/runtime-core/src/profiling.ts',\n        'packages/runtime-core/src/featureFlags.ts',\n        'packages/runtime-core/src/customFormatter.ts',\n        // tested via e2e so no coverage is collected\n        'packages/runtime-core/src/hydrationStrategies.ts',\n        'packages/runtime-dom/src/components/Transition*',\n      ],\n    },\n\n    projects: [\n      {\n        extends: true,\n        test: {\n          name: 'unit',\n          exclude: [\n            ...configDefaults.exclude,\n            '**/e2e/**',\n            '**/{vue,vue-compat,runtime-dom}/**',\n          ],\n        },\n      },\n      {\n        extends: true,\n        test: {\n          name: 'unit-jsdom',\n          include: ['packages/{vue,vue-compat,runtime-dom}/**/*.{test,spec}.*'],\n          exclude: [...configDefaults.exclude, '**/e2e/**'],\n          environment: 'jsdom',\n        },\n      },\n      {\n        extends: true,\n        test: {\n          name: 'e2e',\n          environment: 'jsdom',\n          isolate: true,\n          include: ['packages/vue/__tests__/e2e/*.spec.ts'],\n        },\n      },\n    ],\n  },\n})\n"
  }
]